diff --git a/.changeset/chilly-ladybugs-visit.md b/.changeset/chilly-ladybugs-visit.md new file mode 100644 index 00000000000..aaa2dfc3ef4 --- /dev/null +++ b/.changeset/chilly-ladybugs-visit.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Cleanup txm tests #internal diff --git a/.changeset/cool-turtles-think.md b/.changeset/cool-turtles-think.md new file mode 100644 index 00000000000..87632021656 --- /dev/null +++ b/.changeset/cool-turtles-think.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal return hashed capability ids diff --git a/.changeset/four-knives-stare.md b/.changeset/four-knives-stare.md new file mode 100644 index 00000000000..edac39bc894 --- /dev/null +++ b/.changeset/four-knives-stare.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal [Keystone] Merge version field with ID diff --git a/.changeset/happy-oranges-heal.md b/.changeset/happy-oranges-heal.md new file mode 100644 index 00000000000..9041c861a79 --- /dev/null +++ b/.changeset/happy-oranges-heal.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Add workflow validation diff --git a/.changeset/healthy-shoes-lie.md b/.changeset/healthy-shoes-lie.md new file mode 100644 index 00000000000..85c0cc0beed --- /dev/null +++ b/.changeset/healthy-shoes-lie.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal [Keystone] Add remote target to syncer diff --git a/.changeset/moody-dogs-begin.md b/.changeset/moody-dogs-begin.md new file mode 100644 index 00000000000..7b0753fd73d --- /dev/null +++ b/.changeset/moody-dogs-begin.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal update error message when node does not exist diff --git a/.changeset/olive-experts-matter.md b/.changeset/olive-experts-matter.md new file mode 100644 index 00000000000..cb212f638f4 --- /dev/null +++ b/.changeset/olive-experts-matter.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#db_update Add account_address_public_key to feeds_manager_chain_configs diff --git a/.changeset/popular-cycles-divide.md b/.changeset/popular-cycles-divide.md new file mode 100644 index 00000000000..e2ea186e7cc --- /dev/null +++ b/.changeset/popular-cycles-divide.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#bugfix use correct internal id in workflow auto-approval diff --git a/.changeset/rotten-hats-search.md b/.changeset/rotten-hats-search.md new file mode 100644 index 00000000000..d34a2283801 --- /dev/null +++ b/.changeset/rotten-hats-search.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Move chaintype #internal diff --git a/.changeset/shy-deers-hope.md b/.changeset/shy-deers-hope.md new file mode 100644 index 00000000000..0408383bd03 --- /dev/null +++ b/.changeset/shy-deers-hope.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/common/client/mocks/config.go b/common/client/mocks/config.go index 308fab55790..d1007f39f0f 100644 --- a/common/client/mocks/config.go +++ b/common/client/mocks/config.go @@ -1,23 +1,14 @@ package mocks -import ( - "time" - - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" -) +import "time" type ChainConfig struct { IsFinalityTagEnabled bool FinalityDepthVal uint32 NoNewHeadsThresholdVal time.Duration - ChainTypeVal commonconfig.ChainType FinalizedBlockOffsetVal uint32 } -func (t ChainConfig) ChainType() commonconfig.ChainType { - return t.ChainTypeVal -} - func (t ChainConfig) NodeNoNewHeadsThreshold() time.Duration { return t.NoNewHeadsThresholdVal } diff --git a/common/client/multi_node.go b/common/client/multi_node.go index d60c7071b23..4502bb40edd 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -17,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils" - "github.com/smartcontractkit/chainlink/v2/common/config" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -73,7 +72,6 @@ type MultiNode[ BatchCallContextAll(ctx context.Context, b []BATCH_ELEM) error ConfiguredChainID() CHAIN_ID - IsL2() bool } type multiNode[ @@ -95,7 +93,6 @@ type multiNode[ nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT] sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT] chainID CHAIN_ID - chainType config.ChainType lggr logger.SugaredLogger selectionMode string noNewHeadsThreshold time.Duration @@ -138,7 +135,6 @@ func NewMultiNode[ nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT], sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT], chainID CHAIN_ID, - chainType config.ChainType, chainFamily string, classifySendTxError func(tx TX, err error) SendTxReturnCode, sendTxSoftTimeout time.Duration, @@ -154,7 +150,6 @@ func NewMultiNode[ nodes: nodes, sendonlys: sendonlys, chainID: chainID, - chainType: chainType, lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), selectionMode: selectionMode, noNewHeadsThreshold: noNewHeadsThreshold, @@ -524,10 +519,6 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP 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, BATCH_ELEM]) 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, BATCH_ELEM]) CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) (code []byte, err error) { n, err := c.selectNode() if err != nil { @@ -556,10 +547,6 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP 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, BATCH_ELEM]) 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, BATCH_ELEM]) LatestBlockHeight(ctx context.Context) (h *big.Int, err error) { n, err := c.selectNode() if err != nil { diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 589a3a7e24b..6d41325425a 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -17,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -37,7 +36,6 @@ type multiNodeOpts struct { nodes []Node[types.ID, types.Head[Hashable], multiNodeRPCClient] sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient] chainID types.ID - chainType config.ChainType chainFamily string classifySendTxError func(tx any, err error) SendTxReturnCode sendTxSoftTimeout time.Duration @@ -51,7 +49,7 @@ func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { result := NewMultiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any](opts.logger, opts.selectionMode, opts.leaseDuration, opts.noNewHeadsThreshold, opts.nodes, opts.sendonlys, - opts.chainID, opts.chainType, opts.chainFamily, opts.classifySendTxError, opts.sendTxSoftTimeout) + opts.chainID, opts.chainFamily, opts.classifySendTxError, opts.sendTxSoftTimeout) return testMultiNode{ result.(*multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any]), diff --git a/common/client/node.go b/common/client/node.go index fdee5ff54a6..e8eaa94c5cb 100644 --- a/common/client/node.go +++ b/common/client/node.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -51,7 +50,6 @@ type ChainConfig interface { NodeNoNewHeadsThreshold() time.Duration FinalityDepth() uint32 FinalityTagEnabled() bool - ChainType() commonconfig.ChainType FinalizedBlockOffset() uint32 } diff --git a/contracts/.changeset/long-jars-protect.md b/contracts/.changeset/long-jars-protect.md new file mode 100644 index 00000000000..2e5a11e3c8b --- /dev/null +++ b/contracts/.changeset/long-jars-protect.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +update error message when node does not exist diff --git a/contracts/.changeset/new-bugs-draw.md b/contracts/.changeset/new-bugs-draw.md new file mode 100644 index 00000000000..93fba83b558 --- /dev/null +++ b/contracts/.changeset/new-bugs-draw.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/swift-ads-stare.md b/contracts/.changeset/swift-ads-stare.md new file mode 100644 index 00000000000..33a5d0cf16d --- /dev/null +++ b/contracts/.changeset/swift-ads-stare.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +return hashed capability ids diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot index d01543529cb..fb41fa7d637 100644 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ b/contracts/gas-snapshots/keystone.gas-snapshot @@ -1,99 +1,105 @@ -CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 152088) -CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 176069) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24678) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145679) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94561) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92916) -CapabilityRegistry_AddDONTest:test_AddDON() (gas: 499044) -CapabilityRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19249) -CapabilityRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 291958) -CapabilityRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 365106) -CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 375985) -CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 177974) -CapabilityRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43337) -CapabilityRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 306419) -CapabilityRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184267) -CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17624) -CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18520) -CapabilityRegistry_AddNodesTest:test_AddsNodeInfo() (gas: 355458) -CapabilityRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 355446) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301431) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55243) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24962) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27738) -CapabilityRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25130) -CapabilityRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27444) -CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27083) -CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309850) -CapabilityRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 92873) -CapabilityRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 93001) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22879) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16166) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 94265) -CapabilityRegistry_GetCapabilitiesTest:test_ExcludesDeprecatedCapabilities() (gas: 119306) -CapabilityRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 54034) -CapabilityRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65704) -CapabilityRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 88473) +CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 152156) +CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 176137) +CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) +CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145769) +CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) +CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) +CapabilityRegistry_AddDONTest:test_AddDON() (gas: 499005) +CapabilityRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19247) +CapabilityRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 291948) +CapabilityRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 365161) +CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 375975) +CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 177964) +CapabilityRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43332) +CapabilityRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 306409) +CapabilityRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184333) +CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) +CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) +CapabilityRegistry_AddNodesTest:test_AddsNodeInfo() (gas: 355400) +CapabilityRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 355388) +CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301350) +CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55207) +CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24940) +CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27702) +CapabilityRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) +CapabilityRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) +CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) +CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309778) +CapabilityRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 92938) +CapabilityRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 93066) +CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) +CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) +CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 94395) +CapabilityRegistry_GetCapabilitiesTest:test_ExcludesDeprecatedCapabilities() (gas: 122130) +CapabilityRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 58327) +CapabilityRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65746) +CapabilityRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 88461) CapabilityRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) CapabilityRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilityRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36675) -CapabilityRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38982) -CapabilityRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 59880) -CapabilityRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 71576) -CapabilityRegistry_RemoveDONsTest:test_RemovesDON() (gas: 60696) -CapabilityRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15669) -CapabilityRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16540) -CapabilityRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36069) -CapabilityRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15838) -CapabilityRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 114067) -CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 371521) -CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 712537) -CapabilityRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 72324) -CapabilityRegistry_RemoveNodesTest:test_RemovesNode() (gas: 74158) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 24871) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18373) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfDON() (gas: 385126) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18385) +CapabilityRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36653) +CapabilityRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38938) +CapabilityRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 59861) +CapabilityRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 71597) +CapabilityRegistry_RemoveDONsTest:test_RemovesDON() (gas: 60669) +CapabilityRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) +CapabilityRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16518) +CapabilityRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) +CapabilityRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) +CapabilityRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 114054) +CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 371555) +CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 712587) +CapabilityRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 72342) +CapabilityRegistry_RemoveNodesTest:test_RemovesNode() (gas: 74176) +CapabilityRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 24916) +CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) +CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfDON() (gas: 385167) +CapabilityRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18430) CapabilityRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19406) +CapabilityRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19411) CapabilityRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 157904) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17826) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 231052) +CapabilityRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17831) +CapabilityRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 231117) CapabilityRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 241977) CapabilityRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 103722) CapabilityRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 172410) -CapabilityRegistry_UpdateDONTest:test_UpdatesDON() (gas: 433638) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20583) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20004) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19742) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15382) -CapabilityRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36903) -CapabilityRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 250725) -CapabilityRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 158858) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35985) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25086) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27325) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29206) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27313) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26996) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25560) -CapabilityRegistry_UpdateNodesTest:test_UpdatesNodeInfo() (gas: 158847) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2676465) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 150738) -KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyProcessed() (gas: 158024) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 111634) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 143377) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 119553) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 98500) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 98757) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 67777) -KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 77819) -KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 78543) +CapabilityRegistry_UpdateDONTest:test_UpdatesDON() (gas: 433641) +CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20627) +CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20048) +CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19786) +CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15426) +CapabilityRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36991) +CapabilityRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 250659) +CapabilityRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 158814) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35963) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25064) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27303) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29184) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27291) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26974) +CapabilityRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25538) +CapabilityRegistry_UpdateNodesTest:test_UpdatesNodeInfo() (gas: 158803) +KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 1807115) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 132145) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 133638) +KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 162153) +KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyAttempted() (gas: 157192) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86392) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118530) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94560) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75914) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76282) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45569) +KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55282) +KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56028) KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20162) KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 90143) KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14511) KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 90874) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 847644) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 2224138) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 2365984) -KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) \ No newline at end of file +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 116644) +KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1543588) +KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1540255) +KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) +KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10956) +KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10879) +KeystoneRouter_SetConfigTest:test_Route_RevertWhen_Unauthorized() (gas: 18509) +KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 75585) \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_keystone b/contracts/scripts/native_solc_compile_all_keystone index 1530b307dbd..5450cd654c8 100755 --- a/contracts/scripts/native_solc_compile_all_keystone +++ b/contracts/scripts/native_solc_compile_all_keystone @@ -30,4 +30,5 @@ compileContract () { compileContract keystone/CapabilityRegistry.sol compileContract keystone/KeystoneForwarder.sol +compileContract keystone/KeystoneRouter.sol compileContract keystone/OCR3Capability.sol diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 664d0920131..81745f5ac9b 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -159,7 +159,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice The f value for the DON. This is the number of faulty nodes /// that the DON can tolerate. This can be different from the f value of /// the OCR instances that capabilities spawn. - uint32 f; + uint8 f; /// @notice True if the DON is public. A public DON means that it accepts /// external capability requests bool isPublic; @@ -177,7 +177,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice The f value for the DON. This is the number of faulty nodes /// that the DON can tolerate. This can be different from the f value of /// the OCR instances that capabilities spawn. - uint32 f; + uint8 f; /// @notice True if the DON is public. A public DON means that it accepts /// external capability requests bool isPublic; @@ -196,7 +196,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 configCount; bool isPublic; bool acceptsWorkflows; - uint32 f; + uint8 f; } /// @notice This error is thrown when a caller is not allowed @@ -215,7 +215,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { error InvalidNodeOperatorAdmin(); /// @notice This error is thrown when trying to add a node with P2P ID that - /// is empty bytes or a duplicate. + /// is empty bytes /// @param p2pId The provided P2P ID error InvalidNodeP2PId(bytes32 p2pId); @@ -233,12 +233,17 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// been used by another node error InvalidNodeSigner(); - /// @notice This error is thrown when trying add a capability that already + /// @notice This error is thrown when trying to add a capability that already /// exists. /// @param hashedCapabilityId The hashed capability ID of the capability /// that already exists error CapabilityAlreadyExists(bytes32 hashedCapabilityId); + /// @notice This error is thrown when trying to add a node that already + /// exists. + /// @param nodeP2PId The P2P ID of the node that already exists + error NodeAlreadyExists(bytes32 nodeP2PId); + /// @notice This error is thrown when trying to add a node to a DON where /// the node does not support the capability /// @param nodeP2PId The P2P ID of the node @@ -260,7 +265,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// fault tolerance value. /// @param f The proposed fault tolerance value /// @param nodeCount The proposed number of nodes in the DON - error InvalidFaultTolerance(uint32 f, uint256 nodeCount); + error InvalidFaultTolerance(uint8 f, uint256 nodeCount); /// @notice This error is thrown when a capability with the provided hashed ID is /// not found. @@ -272,6 +277,11 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param hashedCapabilityId The hashed ID of the capability that is deprecated. error CapabilityIsDeprecated(bytes32 hashedCapabilityId); + /// @notice This error is thrown when a node with the provided P2P ID is + /// not found. + /// @param nodeP2PId The node P2P ID used for the lookup. + error NodeDoesNotExist(bytes32 nodeP2PId); + /// @notice This error is thrown when a node operator does not exist /// @param nodeOperatorId The ID of the node operator that does not exist error NodeOperatorDoesNotExist(uint32 nodeOperatorId); @@ -469,9 +479,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); Node storage storedNode = s_nodes[node.p2pId]; - if (storedNode.signer != bytes32("") || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + if (storedNode.signer != bytes32("")) revert NodeAlreadyExists(node.p2pId); + if (node.p2pId == bytes32("")) revert InvalidNodeP2PId(node.p2pId); - if (bytes32(node.signer) == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); + if (node.signer == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); bytes32[] memory capabilityIds = node.hashedCapabilityIds; if (capabilityIds.length == 0) revert InvalidNodeCapabilities(capabilityIds); @@ -503,7 +514,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { Node storage node = s_nodes[p2pId]; - if (bytes32(node.signer) == bytes32("")) revert InvalidNodeP2PId(p2pId); + if (node.signer == bytes32("")) revert NodeDoesNotExist(p2pId); if (node.supportedDONIds.length() > 0) revert NodePartOfDON(p2pId); if (!isOwner && msg.sender != s_nodeOperators[node.nodeOperatorId].admin) revert AccessForbidden(msg.sender); @@ -526,11 +537,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); Node storage storedNode = s_nodes[node.p2pId]; - if (storedNode.signer == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId); - if ( - bytes32(node.signer) == bytes32("") || (storedNode.signer != node.signer && s_nodeSigners.contains(node.signer)) - ) revert InvalidNodeSigner(); + if (node.signer == bytes32("") || (storedNode.signer != node.signer && s_nodeSigners.contains(node.signer))) + revert InvalidNodeSigner(); bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds; if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); @@ -574,12 +584,12 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } /// @notice Gets all nodes - /// @return NodeInfo[] All nodes in the capability registry - /// @return uint32[] All the config counts for the nodes in the capability registry - function getNodes() external view returns (NodeInfo[] memory, uint32[] memory) { + /// @return nodeInfo NodeInfo[] All nodes in the capability registry + /// @return configCounts uint32[] All the config counts for the nodes in the capability registry + function getNodes() external view returns (NodeInfo[] memory nodeInfo, uint32[] memory configCounts) { bytes32[] memory p2pIds = s_nodeP2PIds.values(); - NodeInfo[] memory nodeInfo = new NodeInfo[](p2pIds.length); - uint32[] memory configCounts = new uint32[](p2pIds.length); + nodeInfo = new NodeInfo[](p2pIds.length); + configCounts = new uint32[](p2pIds.length); for (uint256 i; i < p2pIds.length; ++i) { (nodeInfo[i], configCounts[i]) = getNode(p2pIds[i]); @@ -623,15 +633,17 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice Returns all capabilities. This operation will copy capabilities /// to memory, which can be quite expensive. This is designed to mostly be /// used by view accessors that are queried without any gas fees. - /// @return Capability[] An array of capabilities - function getCapabilities() external view returns (Capability[] memory) { + /// @return bytes32[] List of hashed capability Ids + /// @return Capability[] List of capabilities + function getCapabilities() external view returns (bytes32[] memory, Capability[] memory) { bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); + uint256 numSupportedCapabilities = hashedCapabilityIds.length - s_deprecatedHashedCapabilityIds.length(); + // Solidity does not support dynamic arrays in memory, so we create a // fixed-size array and copy the capabilities into it. - Capability[] memory capabilities = new Capability[]( - hashedCapabilityIds.length - s_deprecatedHashedCapabilityIds.length() - ); + Capability[] memory capabilities = new Capability[](numSupportedCapabilities); + bytes32[] memory supportedHashedCapabilityIds = new bytes32[](numSupportedCapabilities); // We need to keep track of the new index because we are skipping // deprecated capabilities. @@ -642,11 +654,12 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { if (!s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) { capabilities[newIndex] = s_capabilities[hashedCapabilityId]; - newIndex++; + supportedHashedCapabilityIds[newIndex] = hashedCapabilityId; + ++newIndex; } } - return capabilities; + return (supportedHashedCapabilityIds, capabilities); } /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access @@ -676,7 +689,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { CapabilityConfiguration[] calldata capabilityConfigurations, bool isPublic, bool acceptsWorkflows, - uint32 f + uint8 f ) external onlyOwner { uint32 id = s_nextDONId++; s_dons[id].id = id; @@ -702,7 +715,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { CapabilityConfiguration[] calldata capabilityConfigurations, bool isPublic, bool acceptsWorkflows, - uint32 f + uint8 f ) external onlyOwner { uint32 configCount = s_dons[donId].configCount; if (configCount == 0) revert DONDoesNotExist(donId); diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index e886c6011dc..3b2d151ed32 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -2,17 +2,15 @@ pragma solidity ^0.8.19; import {IReceiver} from "./interfaces/IReceiver.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner { +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { event FeedReceived(bytes32 indexed feedId, int192 price, uint32 timestamp); error UnauthorizedSender(address sender); error UnauthorizedWorkflowOwner(address workflowOwner); error UnauthorizedWorkflowName(bytes10 workflowName); - constructor() ConfirmedOwner(msg.sender) {} - struct ReceivedFeedReport { bytes32 FeedId; int192 Price; @@ -26,55 +24,55 @@ contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner { mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports; address[] internal s_allowedSendersList; - mapping(address => bool) internal s_allowedSenders; + mapping(address sender => bool) internal s_allowedSenders; address[] internal s_allowedWorkflowOwnersList; - mapping(address => bool) internal s_allowedWorkflowOwners; + mapping(address owner => bool) internal s_allowedWorkflowOwners; bytes10[] internal s_allowedWorkflowNamesList; - mapping(bytes10 => bool) internal s_allowedWorkflowNames; + mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames; function setConfig( address[] calldata _allowedSendersList, address[] calldata _allowedWorkflowOwnersList, bytes10[] calldata _allowedWorkflowNamesList ) external onlyOwner { - for (uint32 i = 0; i < s_allowedSendersList.length; i++) { + for (uint32 i = 0; i < s_allowedSendersList.length; ++i) { s_allowedSenders[s_allowedSendersList[i]] = false; } - for (uint32 i = 0; i < _allowedSendersList.length; i++) { + for (uint32 i = 0; i < _allowedSendersList.length; ++i) { s_allowedSenders[_allowedSendersList[i]] = true; } s_allowedSendersList = _allowedSendersList; - for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; i++) { + for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) { s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false; } - for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; i++) { + for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) { s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true; } s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList; - for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; i++) { + for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) { s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false; } - for (uint32 i = 0; i < _allowedWorkflowNamesList.length; i++) { + for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) { s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true; } s_allowedWorkflowNamesList = _allowedWorkflowNamesList; } function onReport(bytes calldata metadata, bytes calldata rawReport) external { - if (s_allowedSenders[msg.sender] == false) { + if (!s_allowedSenders[msg.sender]) { revert UnauthorizedSender(msg.sender); } (bytes10 workflowName, address workflowOwner) = _getInfo(metadata); - if (s_allowedWorkflowNames[workflowName] == false) { + if (!s_allowedWorkflowNames[workflowName]) { revert UnauthorizedWorkflowName(workflowName); } - if (s_allowedWorkflowOwners[workflowOwner] == false) { + if (!s_allowedWorkflowOwners[workflowOwner]) { revert UnauthorizedWorkflowOwner(workflowOwner); } ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[])); - for (uint32 i = 0; i < feeds.length; i++) { + for (uint256 i = 0; i < feeds.length; ++i) { s_feedReports[feeds[i].FeedId] = StoredFeedReport(feeds[i].Price, feeds[i].Timestamp); emit FeedReceived(feeds[i].FeedId, feeds[i].Price, feeds[i].Timestamp); } diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index e8885bb7543..644f4842be7 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -1,25 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; import {IForwarder} from "./interfaces/IForwarder.sol"; -import {IReceiver} from "./interfaces/IReceiver.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; /// @notice This is an entry point for `write_${chain}` Target capability. It /// allows nodes to determine if reports have been processed (successfully or /// not) in a decentralized and product-agnostic way by recording processed /// reports. -contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterface { - error ReentrantCall(); - +contract KeystoneForwarder is IForwarder, OwnerIsCreator, ITypeAndVersion { /// @notice This error is returned when the report is shorter than /// REPORT_METADATA_LENGTH, which is the minimum length of a report. error InvalidReport(); - /// @notice This error is returned when the metadata version is not supported. - error InvalidVersion(uint8 version); - /// @notice This error is thrown whenever trying to set a config with a fault /// tolerance of 0. error FaultToleranceMustBePositive(); @@ -49,9 +45,8 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac /// @notice This error is thrown whenever a report specifies a configuration that /// does not exist. - /// @param donId The DON ID that was provided in the report - /// @param configVersion The config version that was provided in the report - error InvalidConfig(uint32 donId, uint32 configVersion); + /// @param configId (uint64(donId) << 32) | configVersion + error InvalidConfig(uint64 configId); /// @notice This error is thrown whenever a signer address is not in the /// configuration. @@ -62,37 +57,35 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac /// @param signature The signature that was invalid error InvalidSignature(bytes signature); - /// @notice This error is thrown whenever a message has already been processed. - /// @param messageId The ID of the message that was already processed - error AlreadyProcessed(bytes32 messageId); - - bool internal s_reentrancyGuard; // guard against reentrancy - /// @notice Contains the signing address of each oracle struct OracleSet { uint8 f; // Number of faulty nodes allowed address[] signers; - mapping(address => uint256) _positions; // 1-indexed to detect unset values + mapping(address signer => uint256 position) _positions; // 1-indexed to detect unset values } - /// @notice Contains the configuration for each DON ID - // @param configId keccak256(donId, donConfigVersion) - mapping(bytes32 configId => OracleSet) internal s_configs; + address internal s_router; - struct DeliveryStatus { - address transmitter; - bool success; - } + /// @notice Contains the configuration for each DON ID + // @param configId (uint64(donId) << 32) | configVersion + mapping(uint64 configId => OracleSet) internal s_configs; - mapping(bytes32 reportId => DeliveryStatus status) internal s_reports; + event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); /// @notice Emitted when a report is processed - /// @param receiver The address of the receiver contract - /// @param workflowExecutionId The ID of the workflow execution /// @param result The result of the attempted delivery. True if successful. - event ReportProcessed(address indexed receiver, bytes32 indexed workflowExecutionId, bool result); + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); + + string public constant override typeAndVersion = "KeystoneForwarder 1.0.0"; - constructor() ConfirmedOwner(msg.sender) {} + constructor(address router) OwnerIsCreator() { + s_router = router; + } uint256 internal constant MAX_ORACLES = 31; uint256 internal constant METADATA_LENGTH = 109; @@ -104,145 +97,124 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac if (signers.length > MAX_ORACLES) revert ExcessSigners(signers.length, MAX_ORACLES); if (signers.length <= 3 * f) revert InsufficientSigners(signers.length, 3 * f + 1); - bytes32 configId = keccak256(abi.encode(donId, configVersion)); + uint64 configId = (uint64(donId) << 32) | configVersion; // remove any old signer addresses - for (uint256 i; i < s_configs[configId].signers.length; ++i) { - address signer = s_configs[configId].signers[i]; - delete s_configs[configId]._positions[signer]; + for (uint256 i = 0; i < s_configs[configId].signers.length; ++i) { + delete s_configs[configId]._positions[s_configs[configId].signers[i]]; } // add new signer addresses - s_configs[configId].signers = signers; - for (uint256 i; i < signers.length; ++i) { + for (uint256 i = 0; i < signers.length; ++i) { // assign indices, detect duplicates address signer = signers[i]; if (s_configs[configId]._positions[signer] != 0) revert DuplicateSigner(signer); - s_configs[configId]._positions[signer] = uint8(i) + 1; - s_configs[configId].signers.push(signer); + s_configs[configId]._positions[signer] = i + 1; } + s_configs[configId].signers = signers; s_configs[configId].f = f; + + emit ConfigSet(donId, configVersion, f, signers); } function clearConfig(uint32 donId, uint32 configVersion) external onlyOwner { - bytes32 configId = keccak256(abi.encode(donId, configVersion)); - - // remove any old signer addresses - for (uint256 i; i < s_configs[configId].signers.length; ++i) { - address signer = s_configs[configId].signers[i]; - delete s_configs[configId]._positions[signer]; - } + // We are not removing old signer positions, because it is sufficient to + // clear the f value for `report` function. If we decide to restore + // the configId in the future, the setConfig function clears the positions. + s_configs[(uint64(donId) << 32) | configVersion].f = 0; - s_configs[configId].f = 0; + emit ConfigSet(donId, configVersion, 0, new address[](0)); } // send a report to receiver function report( - address receiverAddress, + address receiver, bytes calldata rawReport, bytes calldata reportContext, bytes[] calldata signatures - ) external nonReentrant { + ) external { if (rawReport.length < METADATA_LENGTH) { revert InvalidReport(); } bytes32 workflowExecutionId; bytes2 reportId; - bytes32 configId; { - uint32 donId; - uint32 configVersion; - (workflowExecutionId, donId, configVersion, reportId) = _getMetadata(rawReport); - - configId = keccak256(abi.encode(donId, configVersion)); + uint64 configId; + (workflowExecutionId, configId, reportId) = _getMetadata(rawReport); + OracleSet storage config = s_configs[configId]; - uint8 f = s_configs[configId].f; + uint8 f = config.f; // f can never be 0, so this means the config doesn't actually exist - if (f == 0) revert InvalidConfig(donId, configVersion); + if (f == 0) revert InvalidConfig(configId); if (f + 1 != signatures.length) revert InvalidSignatureCount(f + 1, signatures.length); - } - - bytes32 combinedId = _combinedId(receiverAddress, workflowExecutionId, reportId); - if (s_reports[combinedId].transmitter != address(0)) revert AlreadyProcessed(combinedId); - // validate signatures - { + // validate signatures bytes32 completeHash = keccak256(abi.encodePacked(keccak256(rawReport), reportContext)); - - address[MAX_ORACLES] memory signed; - uint8 index; - for (uint256 i; i < signatures.length; ++i) { - (bytes32 r, bytes32 s, uint8 v) = _splitSignature(signatures[i]); - address signer = ecrecover(completeHash, v + 27, r, s); + address[MAX_ORACLES + 1] memory signed; + for (uint256 i = 0; i < signatures.length; ++i) { + bytes calldata signature = signatures[i]; + if (signature.length != SIGNATURE_LENGTH) revert InvalidSignature(signature); + address signer = ecrecover( + completeHash, + uint8(signature[64]) + 27, + bytes32(signature[0:32]), + bytes32(signature[32:64]) + ); // validate signer is trusted and signature is unique - index = uint8(s_configs[configId]._positions[signer]); + uint256 index = config._positions[signer]; if (index == 0) revert InvalidSigner(signer); // index is 1-indexed so we can detect unset signers - index -= 1; if (signed[index] != address(0)) revert DuplicateSigner(signer); signed[index] = signer; } } - bool success; - try - IReceiver(receiverAddress).onReport( - rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], - rawReport[METADATA_LENGTH:] - ) - { - success = true; - } catch { - // Do nothing, success is already false - } - - s_reports[combinedId] = DeliveryStatus(msg.sender, success); - emit ReportProcessed(receiverAddress, workflowExecutionId, success); - } + bool success = IRouter(s_router).route( + getTransmissionId(receiver, workflowExecutionId, reportId), + msg.sender, + receiver, + rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], + rawReport[METADATA_LENGTH:] + ); - function _combinedId(address receiver, bytes32 workflowExecutionId, bytes2 reportId) internal pure returns (bytes32) { - // TODO: gas savings: could we just use a bytes key and avoid another keccak256 call - return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); + emit ReportProcessed(receiver, workflowExecutionId, reportId, success); } - // get transmitter of a given report or 0x0 if it wasn't transmitted yet function getTransmitter( address receiver, bytes32 workflowExecutionId, bytes2 reportId ) external view returns (address) { - bytes32 combinedId = _combinedId(receiver, workflowExecutionId, reportId); - return s_reports[combinedId].transmitter; + return IRouter(s_router).getTransmitter(getTransmissionId(receiver, workflowExecutionId, reportId)); } - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _splitSignature(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) { - if (sig.length != SIGNATURE_LENGTH) revert InvalidSignature(sig); - - assembly { - /* - First 32 bytes stores the length of the signature - - add(sig, 32) = pointer of sig + 32 - effectively, skips first 32 bytes of signature + function getTransmissionState( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (IRouter.TransmissionState) { + return IRouter(s_router).getTransmissionState(getTransmissionId(receiver, workflowExecutionId, reportId)); + } - mload(p) loads next 32 bytes starting at the memory address p into memory - */ + function getTransmissionId( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) public pure returns (bytes32) { + // This is slightly cheaper compared to + // keccak256(abi.encode(receiver, workflowExecutionId, reportId)); + return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); + } - // first 32 bytes, after the length prefix - r := mload(add(sig, 32)) - // second 32 bytes - s := mload(add(sig, 64)) - // final byte (first byte of the next 32 bytes) - v := byte(0, mload(add(sig, 96))) - } + function getRouter() external view returns (address) { + return s_router; } // solhint-disable-next-line chainlink-solidity/explicit-returns function _getMetadata( bytes memory rawReport - ) internal pure returns (bytes32 workflowExecutionId, uint32 donId, uint32 donConfigVersion, bytes2 reportId) { + ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { // (first 32 bytes of memory contain length of the report) // version // offset 32, size 1 // workflow_execution_id // offset 33, size 32 @@ -252,32 +224,12 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac // workflow_cid // offset 77, size 32 // workflow_name // offset 109, size 10 // workflow_owner // offset 119, size 20 - // report_name // offset 139, size 2 - if (uint8(rawReport[0]) != 1) { - revert InvalidVersion(uint8(rawReport[0])); - } + // report_id // offset 139, size 2 assembly { workflowExecutionId := mload(add(rawReport, 33)) - // shift right by 28 bytes to get the actual value - donId := shr(mul(28, 8), mload(add(rawReport, 69))) - // shift right by 28 bytes to get the actual value - donConfigVersion := shr(mul(28, 8), mload(add(rawReport, 73))) + // shift right by 24 bytes to get the combined don_id and don_config_version + configId := shr(mul(24, 8), mload(add(rawReport, 69))) reportId := mload(add(rawReport, 139)) } } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "KeystoneForwarder 1.0.0"; - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_reentrancyGuard) revert ReentrantCall(); - s_reentrancyGuard = true; - _; - s_reentrancyGuard = false; - } } diff --git a/contracts/src/v0.8/keystone/KeystoneRouter.sol b/contracts/src/v0.8/keystone/KeystoneRouter.sol new file mode 100644 index 00000000000..aacb83d8c6a --- /dev/null +++ b/contracts/src/v0.8/keystone/KeystoneRouter.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; +import {IReceiver} from "./interfaces/IReceiver.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +contract KeystoneRouter is IRouter, OwnerIsCreator, ITypeAndVersion { + error Unauthorized(); + error AlreadyAttempted(bytes32 transmissionId); + + event ForwarderAdded(address indexed forwarder); + event ForwarderRemoved(address indexed forwarder); + + mapping(address forwarder => bool) internal s_forwarders; + mapping(bytes32 transmissionId => TransmissionInfo) internal s_transmissions; + + string public constant override typeAndVersion = "KeystoneRouter 1.0.0"; + + struct TransmissionInfo { + address transmitter; + bool state; + } + + function addForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = true; + emit ForwarderAdded(forwarder); + } + + function removeForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = false; + emit ForwarderRemoved(forwarder); + } + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata report + ) external returns (bool) { + if (!s_forwarders[msg.sender]) { + revert Unauthorized(); + } + + if (s_transmissions[transmissionId].transmitter != address(0)) revert AlreadyAttempted(transmissionId); + s_transmissions[transmissionId].transmitter = transmitter; + + if (receiver.code.length == 0) return false; + + try IReceiver(receiver).onReport(metadata, report) { + s_transmissions[transmissionId].state = true; + return true; + } catch { + return false; + } + } + + /// @notice Get transmitter of a given report or 0x0 if it wasn't transmitted yet + function getTransmitter(bytes32 transmissionId) external view returns (address) { + return s_transmissions[transmissionId].transmitter; + } + + /// @notice Get delivery status of a given report + function getTransmissionState(bytes32 transmissionId) external view returns (IRouter.TransmissionState) { + if (s_transmissions[transmissionId].transmitter == address(0)) return IRouter.TransmissionState.NOT_ATTEMPTED; + return + s_transmissions[transmissionId].state ? IRouter.TransmissionState.SUCCEEDED : IRouter.TransmissionState.FAILED; + } + + function isForwarder(address forwarder) external view returns (bool) { + return s_forwarders[forwarder]; + } +} diff --git a/contracts/src/v0.8/keystone/interfaces/IRouter.sol b/contracts/src/v0.8/keystone/interfaces/IRouter.sol new file mode 100644 index 00000000000..63ddd865c21 --- /dev/null +++ b/contracts/src/v0.8/keystone/interfaces/IRouter.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title IRouter - delivers keystone reports to receiver +interface IRouter { + enum TransmissionState { + NOT_ATTEMPTED, + SUCCEEDED, + FAILED + } + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata report + ) external returns (bool); + + function getTransmitter(bytes32 transmissionId) external view returns (address); + function getTransmissionState(bytes32 transmissionId) external view returns (TransmissionState); +} diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 3df0b6ca7c7..795bb40843e 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -46,7 +46,7 @@ contract BaseTest is Test, Constants { s_nonExistentHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); } - function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { + function _getNodeOperators() internal pure returns (CapabilityRegistry.NodeOperator[] memory) { CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](3); nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_ONE_ADMIN, name: NODE_OPERATOR_ONE_NAME}); nodeOperators[1] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_TWO_ADMIN, name: NODE_OPERATOR_TWO_NAME}); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol index 941712edb15..7bb4eb43c4d 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -121,7 +121,7 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { s_capabilityRegistry.addNodes(nodes); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, P2P_ID)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeAlreadyExists.selector, P2P_ID)); s_capabilityRegistry.addNodes(nodes); } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol index 60890db3377..e2dff281252 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol @@ -14,7 +14,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { } function test_ReturnsCapabilities() public view { - CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); + (bytes32[] memory hashedCapabilityIds, CapabilityRegistry.Capability[] memory capabilities) = s_capabilityRegistry + .getCapabilities(); + + assertEq(hashedCapabilityIds.length, 2); + assertEq(hashedCapabilityIds[0], keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); + assertEq(hashedCapabilityIds[1], keccak256(abi.encode(capabilities[1].labelledName, capabilities[1].version))); assertEq(capabilities.length, 2); @@ -43,7 +48,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { deprecatedCapabilities[0] = hashedCapabilityId; s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); - CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); + (bytes32[] memory hashedCapabilityIds, CapabilityRegistry.Capability[] memory capabilities) = s_capabilityRegistry + .getCapabilities(); + + assertEq(hashedCapabilityIds.length, 1); + assertEq(hashedCapabilityIds[0], keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); + assertEq(capabilities.length, 1); assertEq(capabilities[0].labelledName, "read-ethereum-mainnet-gas-price"); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol index 0c6b4a9651c..ac59435e35a 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol @@ -62,7 +62,7 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = INVALID_P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, INVALID_P2P_ID)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); s_capabilityRegistry.removeNodes(nodes); } @@ -71,7 +71,7 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = bytes32(""); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, bytes32(""))); s_capabilityRegistry.removeNodes(nodes); } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol index a419f2c198e..da4e811c3ec 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol @@ -75,7 +75,7 @@ contract CapabilityRegistry_UpdateNodesTest is BaseTest { hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, INVALID_P2P_ID)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); s_capabilityRegistry.updateNodes(nodes); } @@ -93,7 +93,7 @@ contract CapabilityRegistry_UpdateNodesTest is BaseTest { hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, bytes32(""))); s_capabilityRegistry.updateNodes(nodes); } diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol index 9b13bd91f58..23c80eea9f1 100644 --- a/contracts/src/v0.8/keystone/test/Constants.t.sol +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -23,7 +23,7 @@ contract Constants { bytes32 internal constant NODE_OPERATOR_THREE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(5555))); bytes32 internal constant P2P_ID_THREE = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a06"; - uint32 internal constant F_VALUE = 1; + uint8 internal constant F_VALUE = 1; uint32 internal constant DON_ID = 1; uint32 internal constant DON_ID_TWO = 2; diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol index fc5c3a160d5..2b1adfb9622 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {Receiver} from "./mocks/Receiver.sol"; +import {KeystoneRouter} from "../KeystoneRouter.sol"; import {KeystoneForwarder} from "../KeystoneForwarder.sol"; contract BaseTest is Test { @@ -20,11 +21,14 @@ contract BaseTest is Test { Signer[MAX_ORACLES] internal s_signers; KeystoneForwarder internal s_forwarder; + KeystoneRouter internal s_router; Receiver internal s_receiver; function setUp() public virtual { vm.startPrank(ADMIN); - s_forwarder = new KeystoneForwarder(); + s_router = new KeystoneRouter(); + s_forwarder = new KeystoneForwarder(address(s_router)); + s_router.addForwarder(address(s_forwarder)); s_receiver = new Receiver(); uint256 seed = 0; diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol index f68917ba85a..cf9d1ad3eee 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol @@ -2,11 +2,18 @@ pragma solidity ^0.8.19; import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; +import {KeystoneRouter} from "../KeystoneRouter.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; import {KeystoneForwarder} from "../KeystoneForwarder.sol"; contract KeystoneForwarder_ReportTest is BaseTest { event MessageReceived(bytes metadata, bytes[] mercuryReports); - event ReportProcessed(address indexed receiver, bytes32 indexed workflowExecutionId, bool result); + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); uint8 internal version = 1; uint32 internal timestamp = 0; @@ -28,6 +35,9 @@ contract KeystoneForwarder_ReportTest is BaseTest { BaseTest.setUp(); s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + s_router.addForwarder(address(s_forwarder)); + + assertEq(s_forwarder.getRouter(), address(s_router), "router mismatch"); mercuryReports[0] = hex"010203"; mercuryReports[1] = hex"aabbccdd"; @@ -57,7 +67,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { rawReports ); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, invalidDONId, CONFIG_VERSION)); + uint64 configId = (uint64(invalidDONId) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); } @@ -75,7 +86,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { rawReports ); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, DON_ID, CONFIG_VERSION + 1)); + uint64 configId = (uint64(DON_ID) << 32) | (CONFIG_VERSION + 1); + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); } @@ -132,11 +144,11 @@ contract KeystoneForwarder_ReportTest is BaseTest { s_forwarder.report(address(s_receiver), report, reportContext, signatures); } - function test_RevertWhen_AlreadyProcessed() public { + function test_RevertWhen_AlreadyAttempted() public { s_forwarder.report(address(s_receiver), report, reportContext, signatures); - bytes32 combinedId = keccak256(bytes.concat(bytes20(uint160(address(s_receiver))), executionId, reportId)); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.AlreadyProcessed.selector, combinedId)); + bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); + vm.expectRevert(abi.encodeWithSelector(KeystoneRouter.AlreadyAttempted.selector, transmissionId)); s_forwarder.report(address(s_receiver), report, reportContext, signatures); } @@ -145,13 +157,54 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(metadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, true); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); s_forwarder.report(address(s_receiver), report, reportContext, signatures); - // validate transmitter was recorded - address transmitter = s_forwarder.getTransmitter(address(s_receiver), executionId, reportId); - assertEq(transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq( + s_forwarder.getTransmitter(address(s_receiver), executionId, reportId), + TRANSMITTER, + "transmitter mismatch" + ); + assertEq( + uint8(s_forwarder.getTransmissionState(address(s_receiver), executionId, reportId)), + uint8(IRouter.TransmissionState.SUCCEEDED), + "TransmissionState mismatch" + ); + } + + function test_Report_FailedDeliveryWhenReceiverNotContract() public { + // Receiver is not a contract + address receiver = address(404); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + assertEq(s_forwarder.getTransmitter(receiver, executionId, reportId), TRANSMITTER, "transmitter mismatch"); + assertEq( + uint8(s_forwarder.getTransmissionState(receiver, executionId, reportId)), + uint8(IRouter.TransmissionState.FAILED), + "TransmissionState mismatch" + ); + } + + function test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() public { + // Receiver is a contract but doesn't implement the required interface + address receiver = address(s_forwarder); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + assertEq(s_forwarder.getTransmitter(receiver, executionId, reportId), TRANSMITTER, "transmitter mismatch"); + assertEq( + uint8(s_forwarder.getTransmissionState(receiver, executionId, reportId)), + uint8(IRouter.TransmissionState.FAILED), + "TransmissionState mismatch" + ); } function test_Report_ConfigVersion() public { @@ -165,7 +218,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(metadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, true); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), report, reportContext, signatures); @@ -174,7 +227,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { vm.prank(ADMIN); s_forwarder.clearConfig(DON_ID, CONFIG_VERSION); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, DON_ID, CONFIG_VERSION)); + uint64 configId = (uint64(DON_ID) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), report, reportContext, signatures); @@ -197,7 +251,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(newMetadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), newExecutionId, true); + emit ReportProcessed(address(s_receiver), newExecutionId, reportId, true); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), newReport, reportContext, newSignatures); diff --git a/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol new file mode 100644 index 00000000000..60c40eec573 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {IReceiver} from "../interfaces/IReceiver.sol"; +import {KeystoneRouter} from "../KeystoneRouter.sol"; + +contract KeystoneRouter_SetConfigTest is Test { + address internal ADMIN = address(1); + address internal constant STRANGER = address(2); + address internal constant FORWARDER = address(99); + address internal constant TRANSMITTER = address(50); + address internal constant RECEIVER = address(51); + + bytes internal metadata = hex"01020304"; + bytes internal report = hex"9998"; + bytes32 internal id = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + + KeystoneRouter internal s_router; + + function setUp() public virtual { + vm.prank(ADMIN); + s_router = new KeystoneRouter(); + } + + function test_AddForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.addForwarder(FORWARDER); + } + + function test_RemoveForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.removeForwarder(FORWARDER); + } + + function test_Route_RevertWhen_Unauthorized() public { + vm.prank(STRANGER); + vm.expectRevert(KeystoneRouter.Unauthorized.selector); + s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); + } + + function test_Route_Success() public { + assertEq(s_router.isForwarder(FORWARDER), false); + + vm.prank(ADMIN); + s_router.addForwarder(FORWARDER); + assertEq(s_router.isForwarder(FORWARDER), true); + + vm.prank(FORWARDER); + vm.mockCall(RECEIVER, abi.encodeCall(IReceiver.onReport, (metadata, report)), abi.encode()); + vm.expectCall(RECEIVER, abi.encodeCall(IReceiver.onReport, (metadata, report))); + s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); + } +} diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 042e5dfca90..84174e0232f 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -145,7 +145,7 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error } r.m[id] = c - r.lggr.Infow("capability added", "id", id, "type", info.CapabilityType, "description", info.Description, "version", info.Version) + r.lggr.Infow("capability added", "id", id, "type", info.CapabilityType, "description", info.Description, "version", info.Version()) return nil } diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 3bed31a957a..5208781700a 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -2,6 +2,7 @@ package capabilities_test import ( "context" + "fmt" "testing" "github.com/google/uuid" @@ -36,12 +37,11 @@ func TestRegistry(t *testing.T) { r := coreCapabilities.NewRegistry(logger.TestLogger(t)) - id := "capability-1" + id := "capability-1@1.0.0" ci, err := capabilities.NewCapabilityInfo( id, capabilities.CapabilityTypeAction, "capability-1-description", - "v1.0.0", ) require.NoError(t, err) @@ -64,12 +64,11 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { ctx := testutils.Context(t) r := coreCapabilities.NewRegistry(logger.TestLogger(t)) - id := "capability-1" + id := "capability-1@1.0.0" ci, err := capabilities.NewCapabilityInfo( id, capabilities.CapabilityTypeAction, "capability-1-description", - "v1.0.0", ) require.NoError(t, err) @@ -81,13 +80,12 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { id, capabilities.CapabilityTypeConsensus, "capability-2-description", - "v1.0.0", ) require.NoError(t, err) c2 := &mockCapability{CapabilityInfo: ci} err = r.Add(ctx, c2) - assert.ErrorContains(t, err, "capability with id: capability-1 already exists") + assert.ErrorContains(t, err, "capability with id: capability-1@1.0.0 already exists") } func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { @@ -100,12 +98,11 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { { name: "action", newCapability: func(ctx context.Context, reg *coreCapabilities.Registry) (string, error) { - id := uuid.New().String() + id := fmt.Sprintf("%s@%s", uuid.New().String(), "1.0.0") ci, err := capabilities.NewCapabilityInfo( id, capabilities.CapabilityTypeAction, "capability-1-description", - "v1.0.0", ) require.NoError(t, err) @@ -120,12 +117,11 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { { name: "target", newCapability: func(ctx context.Context, reg *coreCapabilities.Registry) (string, error) { - id := uuid.New().String() + id := fmt.Sprintf("%s@%s", uuid.New().String(), "1.0.0") ci, err := capabilities.NewCapabilityInfo( id, capabilities.CapabilityTypeTarget, "capability-1-description", - "v1.0.0", ) require.NoError(t, err) @@ -153,12 +149,11 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { { name: "consensus", newCapability: func(ctx context.Context, reg *coreCapabilities.Registry) (string, error) { - id := uuid.New().String() + id := fmt.Sprintf("%s@%s", uuid.New().String(), "1.0.0") ci, err := capabilities.NewCapabilityInfo( id, capabilities.CapabilityTypeConsensus, "capability-1-description", - "v1.0.0", ) require.NoError(t, err) diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index 44b00c035f1..63b0fad7e98 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -72,6 +72,7 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId string, receiver rem return fmt.Errorf("receiver already exists for capability %s and don %s", capabilityId, donId) } d.receivers[k] = receiver + d.lggr.Debugw("receiver set", "capabilityId", capabilityId, "donId", donId) return nil } @@ -79,6 +80,7 @@ func (d *dispatcher) RemoveReceiver(capabilityId string, donId string) { d.mu.Lock() defer d.mu.Unlock() delete(d.receivers, key{capabilityId, donId}) + d.lggr.Debugw("receiver removed", "capabilityId", capabilityId, "donId", donId) } func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { diff --git a/core/capabilities/remote/target/client.go b/core/capabilities/remote/target/client.go index ceab11dfcb0..2fb11930164 100644 --- a/core/capabilities/remote/target/client.go +++ b/core/capabilities/remote/target/client.go @@ -7,8 +7,8 @@ import ( "sync" "time" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target/request" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -22,44 +22,34 @@ import ( // // client communicates with corresponding server on remote nodes. type client struct { + services.StateMachine lggr logger.Logger remoteCapabilityInfo commoncap.CapabilityInfo - localDONInfo capabilities.DON + localDONInfo commoncap.DON dispatcher types.Dispatcher requestTimeout time.Duration messageIDToCallerRequest map[string]*request.ClientRequest mutex sync.Mutex + stopCh services.StopChan + wg sync.WaitGroup } var _ commoncap.TargetCapability = &client{} var _ types.Receiver = &client{} +var _ services.Service = &client{} -func NewClient(ctx context.Context, lggr logger.Logger, remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, - requestTimeout time.Duration) *client { - c := &client{ +func NewClient(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, dispatcher types.Dispatcher, + requestTimeout time.Duration, lggr logger.Logger) *client { + return &client{ lggr: lggr, remoteCapabilityInfo: remoteCapabilityInfo, localDONInfo: localDonInfo, dispatcher: dispatcher, requestTimeout: requestTimeout, messageIDToCallerRequest: make(map[string]*request.ClientRequest), + stopCh: make(services.StopChan), } - - go func() { - ticker := time.NewTicker(requestTimeout) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - c.expireRequests() - } - } - }() - - return c } func (c *client) expireRequests() { @@ -74,6 +64,36 @@ func (c *client) expireRequests() { } } +func (c *client) Start(ctx context.Context) error { + return c.StartOnce(c.Name(), func() error { + c.wg.Add(1) + go func() { + defer c.wg.Done() + ticker := time.NewTicker(c.requestTimeout) + defer ticker.Stop() + c.lggr.Info("TargetClient started") + for { + select { + case <-c.stopCh: + return + case <-ticker.C: + c.expireRequests() + } + } + }() + return nil + }) +} + +func (c *client) Close() error { + return c.StopOnce(c.Name(), func() error { + close(c.stopCh) + c.wg.Wait() + c.lggr.Info("TargetClient closed") + return nil + }) +} + func (c *client) Info(ctx context.Context) (commoncap.CapabilityInfo, error) { return c.remoteCapabilityInfo, nil } @@ -101,7 +121,8 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest return nil, fmt.Errorf("request for message ID %s already exists", messageID) } - req, err := request.NewClientRequest(ctx, c.lggr, capReq, messageID, c.remoteCapabilityInfo, c.localDONInfo, c.dispatcher, + cCtx, _ := c.stopCh.NewCtx() + req, err := request.NewClientRequest(cCtx, c.lggr, capReq, messageID, c.remoteCapabilityInfo, c.localDONInfo, c.dispatcher, c.requestTimeout) if err != nil { return nil, fmt.Errorf("failed to create client request: %w", err) @@ -115,8 +136,7 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest func (c *client) Receive(msg *types.MessageBody) { c.mutex.Lock() defer c.mutex.Unlock() - // TODO should the dispatcher be passing in a context? - ctx := context.Background() + ctx, _ := c.stopCh.NewCtx() messageID := GetMessageID(msg) @@ -140,3 +160,15 @@ func GetMessageIDForRequest(req commoncap.CapabilityRequest) (string, error) { return req.Metadata.WorkflowID + req.Metadata.WorkflowExecutionID, nil } + +func (c *client) Ready() error { + return nil +} + +func (c *client) HealthReport() map[string]error { + return nil +} + +func (c *client) Name() string { + return "TargetClient" +} diff --git a/core/capabilities/remote/target/client_test.go b/core/capabilities/remote/target/client_test.go index 5bfbb0c7a0c..8665ffe7544 100644 --- a/core/capabilities/remote/target/client_test.go +++ b/core/capabilities/remote/target/client_test.go @@ -11,6 +11,7 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -138,10 +139,9 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo } capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1.0.0", CapabilityType: commoncap.CapabilityTypeTarget, Description: "Remote Target", - Version: "0.0.1", DON: &capDonInfo, } @@ -166,11 +166,14 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo } callers := make([]commoncap.TargetCapability, numWorkflowPeers) + srvcs := make([]services.Service, numWorkflowPeers) for i := 0; i < numWorkflowPeers; i++ { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) - caller := target.NewClient(ctx, lggr, capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeResponseTimeout) + caller := target.NewClient(capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeResponseTimeout, lggr) + require.NoError(t, caller.Start(ctx)) broker.RegisterReceiverNode(workflowPeers[i], caller) callers[i] = caller + srvcs[i] = caller } executeInputs, err := values.NewMap( @@ -203,6 +206,9 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo } wg.Wait() + for i := 0; i < numWorkflowPeers; i++ { + require.NoError(t, srvcs[i].Close()) + } } // Simple client that only responds once it has received a message from each workflow peer @@ -257,7 +263,7 @@ func (t *clientTestServer) Receive(msg *remotetypes.MessageBody) { for receiver := range t.messageIDToSenders[messageID] { var responseMsg = &remotetypes.MessageBody{ - CapabilityId: "cap_id", + CapabilityId: "cap_id@1.0.0", CapabilityDonId: "capability-don", CallerDonId: t.workflowDonInfo.ID, Method: remotetypes.MethodExecute, diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index 998c9532871..a5379250e5e 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -200,10 +201,9 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta } capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1.0.0", CapabilityType: commoncap.CapabilityTypeTarget, Description: "Remote Target", - Version: "0.0.1", DON: &capDonInfo, } @@ -226,22 +226,27 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta workflowDonInfo.ID: workflowDonInfo, } + srvcs := []services.Service{} capabilityNodes := make([]remotetypes.Receiver, numCapabilityPeers) for i := 0; i < numCapabilityPeers; i++ { capabilityPeer := capabilityPeers[i] capabilityDispatcher := broker.NewDispatcherForNode(capabilityPeer) - capabilityNode := target.NewReceiver(ctx, lggr, capabilityPeer, underlying, capInfo, capDonInfo, workflowDONs, capabilityDispatcher, - capabilityNodeResponseTimeout) + capabilityNode := target.NewServer(capabilityPeer, underlying, capInfo, capDonInfo, workflowDONs, capabilityDispatcher, + capabilityNodeResponseTimeout, lggr) + require.NoError(t, capabilityNode.Start(ctx)) broker.RegisterReceiverNode(capabilityPeer, capabilityNode) capabilityNodes[i] = capabilityNode + srvcs = append(srvcs, capabilityNode) } workflowNodes := make([]commoncap.TargetCapability, numWorkflowPeers) for i := 0; i < numWorkflowPeers; i++ { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) - workflowNode := target.NewClient(ctx, lggr, capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeTimeout) + workflowNode := target.NewClient(capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeTimeout, lggr) + require.NoError(t, workflowNode.Start(ctx)) broker.RegisterReceiverNode(workflowPeers[i], workflowNode) workflowNodes[i] = workflowNode + srvcs = append(srvcs, workflowNode) } executeInputs, err := values.NewMap( @@ -273,6 +278,9 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta } wg.Wait() + for _, srv := range srvcs { + require.NoError(t, srv.Close()) + } } type testMessageBroker struct { diff --git a/core/capabilities/remote/target/request/client_request.go b/core/capabilities/remote/target/request/client_request.go index 1355932c833..5f49040e0fb 100644 --- a/core/capabilities/remote/target/request/client_request.go +++ b/core/capabilities/remote/target/request/client_request.go @@ -59,6 +59,8 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap return nil, fmt.Errorf("failed to get peer ID to transmission delay: %w", err) } + lggr.Debugw("sending request to peers", "execID", req.Metadata.WorkflowExecutionID, "schedule", peerIDToTransmissionDelay) + responseReceived := make(map[p2ptypes.PeerID]bool) for peerID, delay := range peerIDToTransmissionDelay { responseReceived[peerID] = false @@ -74,8 +76,10 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap select { case <-ctx.Done(): + lggr.Debugw("context done, not sending request to peer", "execID", req.Metadata.WorkflowExecutionID, "peerID", peerID) return case <-time.After(delay): + lggr.Debugw("sending request to peer", "execID", req.Metadata.WorkflowExecutionID, "peerID", peerID) err := dispatcher.Send(peerID, message) if err != nil { lggr.Errorw("failed to send message", "peerID", peerID, "err", err) diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index 930ba595625..e4b0d9da88e 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -35,10 +35,9 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { } capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1.0.0", CapabilityType: commoncap.CapabilityTypeTarget, Description: "Remote Target", - Version: "0.0.1", DON: &capDonInfo, } diff --git a/core/capabilities/remote/target/request/server_request.go b/core/capabilities/remote/target/request/server_request.go index 84968de9f11..bb84fda4ac0 100644 --- a/core/capabilities/remote/target/request/server_request.go +++ b/core/capabilities/remote/target/request/server_request.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" @@ -42,12 +43,13 @@ type ServerRequest struct { requestMessageID string requestTimeout time.Duration - mux sync.Mutex + mux sync.Mutex + lggr logger.Logger } func NewServerRequest(capability capabilities.TargetCapability, capabilityID string, capabilityDonID string, capabilityPeerId p2ptypes.PeerID, callingDon commoncap.DON, requestMessageID string, - dispatcher types.Dispatcher, requestTimeout time.Duration) *ServerRequest { + dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *ServerRequest { return &ServerRequest{ capability: capability, createdTime: time.Now(), @@ -60,6 +62,7 @@ func NewServerRequest(capability capabilities.TargetCapability, capabilityID str callingDon: callingDon, requestMessageID: requestMessageID, requestTimeout: requestTimeout, + lggr: lggr, } } @@ -118,21 +121,22 @@ func (e *ServerRequest) executeRequest(ctx context.Context, payload []byte) erro return fmt.Errorf("failed to unmarshal capability request: %w", err) } + e.lggr.Debugw("executing capability", "metadata", capabilityRequest.Metadata) capResponseCh, err := e.capability.Execute(ctxWithTimeout, capabilityRequest) if err != nil { return fmt.Errorf("failed to execute capability: %w", err) } - // TODO working on the assumption that the capability will only ever return one response from its channel (for now at least) + // NOTE working on the assumption that the capability will only ever return one response from its channel capResponse := <-capResponseCh responsePayload, err := pb.MarshalCapabilityResponse(capResponse) if err != nil { return fmt.Errorf("failed to marshal capability response: %w", err) } + e.lggr.Debugw("received execution results", "metadata", capabilityRequest.Metadata, "error", capResponse.Err) e.setResult(responsePayload) - return nil } @@ -212,6 +216,7 @@ func (e *ServerRequest) sendResponse(requester p2ptypes.PeerID) error { responseMsg.Payload = e.response.response } + e.lggr.Debugw("Sending response", "receiver", requester) if err := e.dispatcher.Send(requester, &responseMsg); err != nil { return fmt.Errorf("failed to send response to dispatcher: %w", err) } diff --git a/core/capabilities/remote/target/request/server_request_test.go b/core/capabilities/remote/target/request/server_request_test.go index 0529a1e9004..fe3fdd713b5 100644 --- a/core/capabilities/remote/target/request/server_request_test.go +++ b/core/capabilities/remote/target/request/server_request_test.go @@ -16,10 +16,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target/request" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) func Test_ServerRequest_MessageValidation(t *testing.T) { + lggr := logger.TestLogger(t) capability := TestCapability{} capabilityPeerID := NewP2PPeerID(t) @@ -57,7 +59,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send duplicate message", func(t *testing.T) { req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute) + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) require.NoError(t, err) @@ -67,7 +69,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send message with non calling don peer", func(t *testing.T) { req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute) + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) require.NoError(t, err) @@ -90,7 +92,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send message invalid payload", func(t *testing.T) { req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute) + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) require.NoError(t, err) @@ -115,7 +117,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send second valid request when capability errors", func(t *testing.T) { dispatcher := &testDispatcher{} req := request.NewServerRequest(TestErrorCapability{}, "capabilityID", "capabilityDonID", - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute) + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) require.NoError(t, err) @@ -142,7 +144,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send second valid request", func(t *testing.T) { dispatcher := &testDispatcher{} request := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", - capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute) + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) require.NoError(t, err) diff --git a/core/capabilities/remote/target/server.go b/core/capabilities/remote/target/server.go index bb3bc6e4edc..8ccbecf530e 100644 --- a/core/capabilities/remote/target/server.go +++ b/core/capabilities/remote/target/server.go @@ -8,11 +8,11 @@ import ( "time" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target/request" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -23,11 +23,12 @@ import ( // // server communicates with corresponding client on remote nodes. type server struct { + services.StateMachine lggr logger.Logger peerID p2ptypes.PeerID underlying commoncap.TargetCapability capInfo commoncap.CapabilityInfo - localDonInfo capabilities.DON + localDonInfo commoncap.DON workflowDONs map[string]commoncap.DON dispatcher types.Dispatcher @@ -35,13 +36,16 @@ type server struct { requestTimeout time.Duration receiveLock sync.Mutex + stopCh services.StopChan + wg sync.WaitGroup } var _ types.Receiver = &server{} +var _ services.Service = &server{} -func NewReceiver(ctx context.Context, lggr logger.Logger, peerID p2ptypes.PeerID, underlying commoncap.TargetCapability, capInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, - workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration) *server { - r := &server{ +func NewServer(peerID p2ptypes.PeerID, underlying commoncap.TargetCapability, capInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, + workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *server { + return &server{ underlying: underlying, peerID: peerID, capInfo: capInfo, @@ -52,23 +56,39 @@ func NewReceiver(ctx context.Context, lggr logger.Logger, peerID p2ptypes.PeerID requestIDToRequest: map[string]*request.ServerRequest{}, requestTimeout: requestTimeout, - lggr: lggr, + lggr: lggr, + stopCh: make(services.StopChan), } +} - go func() { - ticker := time.NewTicker(requestTimeout) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - r.expireRequests() +func (r *server) Start(ctx context.Context) error { + return r.StartOnce(r.Name(), func() error { + r.wg.Add(1) + go func() { + defer r.wg.Done() + ticker := time.NewTicker(r.requestTimeout) + defer ticker.Stop() + r.lggr.Info("TargetServer started") + for { + select { + case <-r.stopCh: + return + case <-ticker.C: + r.expireRequests() + } } - } - }() + }() + return nil + }) +} - return r +func (r *server) Close() error { + return r.StopOnce(r.Name(), func() error { + close(r.stopCh) + r.wg.Wait() + r.lggr.Info("TargetServer closed") + return nil + }) } func (r *server) expireRequests() { @@ -91,8 +111,7 @@ func (r *server) expireRequests() { func (r *server) Receive(msg *types.MessageBody) { r.receiveLock.Lock() defer r.receiveLock.Unlock() - // TODO should the dispatcher be passing in a context? - ctx := context.Background() + ctx, _ := r.stopCh.NewCtx() if msg.Method != types.MethodExecute { r.lggr.Errorw("received request for unsupported method type", "method", msg.Method) @@ -113,7 +132,7 @@ func (r *server) Receive(msg *types.MessageBody) { } r.requestIDToRequest[requestID] = request.NewServerRequest(r.underlying, r.capInfo.ID, r.localDonInfo.ID, r.peerID, - callingDon, messageId, r.dispatcher, r.requestTimeout) + callingDon, messageId, r.dispatcher, r.requestTimeout, r.lggr) } req := r.requestIDToRequest[requestID] @@ -129,3 +148,15 @@ func (r *server) Receive(msg *types.MessageBody) { func GetMessageID(msg *types.MessageBody) string { return string(msg.MessageId) } + +func (r *server) Ready() error { + return nil +} + +func (r *server) HealthReport() map[string]error { + return nil +} + +func (r *server) Name() string { + return "TargetServer" +} diff --git a/core/capabilities/remote/target/server_test.go b/core/capabilities/remote/target/server_test.go index ed80e760951..e6d85ebff25 100644 --- a/core/capabilities/remote/target/server_test.go +++ b/core/capabilities/remote/target/server_test.go @@ -10,6 +10,7 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -23,7 +24,7 @@ func Test_Server_RespondsAfterSufficientRequests(t *testing.T) { numCapabilityPeers := 4 - callers := testRemoteTargetServer(ctx, t, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) + callers, srvcs := testRemoteTargetServer(ctx, t, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) for _, caller := range callers { _, err := caller.Execute(context.Background(), @@ -42,6 +43,7 @@ func Test_Server_RespondsAfterSufficientRequests(t *testing.T) { assert.Equal(t, remotetypes.Error_OK, msg.Error) } } + closeServices(t, srvcs) } func Test_Server_InsufficientCallers(t *testing.T) { @@ -50,7 +52,7 @@ func Test_Server_InsufficientCallers(t *testing.T) { numCapabilityPeers := 4 - callers := testRemoteTargetServer(ctx, t, &TestCapability{}, 10, 10, numCapabilityPeers, 3, 100*time.Millisecond) + callers, srvcs := testRemoteTargetServer(ctx, t, &TestCapability{}, 10, 10, numCapabilityPeers, 3, 100*time.Millisecond) for _, caller := range callers { _, err := caller.Execute(context.Background(), @@ -69,6 +71,7 @@ func Test_Server_InsufficientCallers(t *testing.T) { assert.Equal(t, remotetypes.Error_TIMEOUT, msg.Error) } } + closeServices(t, srvcs) } func Test_Server_CapabilityError(t *testing.T) { @@ -77,7 +80,7 @@ func Test_Server_CapabilityError(t *testing.T) { numCapabilityPeers := 4 - callers := testRemoteTargetServer(ctx, t, &TestErrorCapability{}, 10, 9, numCapabilityPeers, 3, 100*time.Millisecond) + callers, srvcs := testRemoteTargetServer(ctx, t, &TestErrorCapability{}, 10, 9, numCapabilityPeers, 3, 100*time.Millisecond) for _, caller := range callers { _, err := caller.Execute(context.Background(), @@ -96,12 +99,13 @@ func Test_Server_CapabilityError(t *testing.T) { assert.Equal(t, remotetypes.Error_INTERNAL_ERROR, msg.Error) } } + closeServices(t, srvcs) } func testRemoteTargetServer(ctx context.Context, t *testing.T, underlying commoncap.TargetCapability, numWorkflowPeers int, workflowDonF uint8, - numCapabilityPeers int, capabilityDonF uint8, capabilityNodeResponseTimeout time.Duration) []*serverTestClient { + numCapabilityPeers int, capabilityDonF uint8, capabilityNodeResponseTimeout time.Duration) ([]*serverTestClient, []services.Service) { lggr := logger.TestLogger(t) capabilityPeers := make([]p2ptypes.PeerID, numCapabilityPeers) @@ -117,10 +121,9 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, } capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1.0.0", CapabilityType: commoncap.CapabilityTypeTarget, Description: "Remote Target", - Version: "0.0.1", DON: &capDonInfo, } @@ -142,13 +145,16 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, } capabilityNodes := make([]remotetypes.Receiver, numCapabilityPeers) + srvcs := make([]services.Service, numCapabilityPeers) for i := 0; i < numCapabilityPeers; i++ { capabilityPeer := capabilityPeers[i] capabilityDispatcher := broker.NewDispatcherForNode(capabilityPeer) - capabilityNode := target.NewReceiver(ctx, lggr, capabilityPeer, underlying, capInfo, capDonInfo, workflowDONs, capabilityDispatcher, - capabilityNodeResponseTimeout) + capabilityNode := target.NewServer(capabilityPeer, underlying, capInfo, capDonInfo, workflowDONs, capabilityDispatcher, + capabilityNodeResponseTimeout, lggr) + require.NoError(t, capabilityNode.Start(ctx)) broker.RegisterReceiverNode(capabilityPeer, capabilityNode) capabilityNodes[i] = capabilityNode + srvcs[i] = capabilityNode } workflowNodes := make([]*serverTestClient, numWorkflowPeers) @@ -159,7 +165,13 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, workflowNodes[i] = workflowNode } - return workflowNodes + return workflowNodes, srvcs +} + +func closeServices(t *testing.T, srvcs []services.Service) { + for _, srv := range srvcs { + require.NoError(t, srv.Close()) + } } type serverTestClient struct { diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index 71a5174c07f..15bdd39b55f 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -20,10 +20,9 @@ func TestTriggerPublisher_Register(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1", CapabilityType: commoncap.CapabilityTypeTrigger, Description: "Remote Trigger", - Version: "0.0.1", } p1 := p2ptypes.PeerID{} require.NoError(t, p1.UnmarshalText([]byte(peerID1))) diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index 1ad360418fb..e50f570bb7b 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -29,10 +29,9 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) capInfo := commoncap.CapabilityInfo{ - ID: "cap_id", + ID: "cap_id@1", CapabilityType: commoncap.CapabilityTypeTrigger, Description: "Remote Trigger", - Version: "0.0.1", } p1 := p2ptypes.PeerID{} require.NoError(t, p1.UnmarshalText([]byte(peerID1))) diff --git a/core/capabilities/syncer.go b/core/capabilities/syncer.go index 1c3bbab8fe8..3b400646678 100644 --- a/core/capabilities/syncer.go +++ b/core/capabilities/syncer.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" "github.com/smartcontractkit/libocr/ragep2p" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -68,7 +69,7 @@ func NewRegistrySyncer(peerWrapper p2ptypes.PeerWrapper, registry core.Capabilit func (s *registrySyncer) Start(ctx context.Context) error { s.wg.Add(1) - go s.launch(ctx) + go s.launch(context.Background()) return nil } @@ -76,12 +77,11 @@ func (s *registrySyncer) Start(ctx context.Context) error { // that reads the configuration from chain (KS-117). func (s *registrySyncer) launch(ctx context.Context) { defer s.wg.Done() - capId := "streams-trigger" + capId := "streams-trigger@1.0.0" triggerInfo, err := capabilities.NewRemoteCapabilityInfo( capId, capabilities.CapabilityTypeTrigger, "Remote Trigger", - "v0.0.1", &s.networkSetup.TriggerCapabilityDonInfo, ) if err != nil { @@ -89,6 +89,18 @@ func (s *registrySyncer) launch(ctx context.Context) { return } + targetCapId := "write_ethereum-testnet-sepolia@1.0.0" + targetInfo, err := capabilities.NewRemoteCapabilityInfo( + targetCapId, + capabilities.CapabilityTypeTarget, + "Remote Target", + &s.networkSetup.TargetCapabilityDonInfo, + ) + if err != nil { + s.lggr.Errorw("failed to create capability info for write_ethereum-testnet-sepolia", "error", err) + return + } + myId := s.peerWrapper.GetPeer().ID() config := remotetypes.RemoteTriggerConfig{ RegistrationRefreshMs: 20000, @@ -107,15 +119,29 @@ func (s *registrySyncer) launch(ctx context.Context) { triggerCap := remote.NewTriggerSubscriber(config, triggerInfo, s.networkSetup.TriggerCapabilityDonInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, aggregator, s.lggr) err = s.registry.Add(ctx, triggerCap) if err != nil { - s.lggr.Errorw("failed to add remote target capability to registry", "error", err) + s.lggr.Errorw("failed to add remote trigger capability to registry", "error", err) return } err = s.dispatcher.SetReceiver(capId, s.networkSetup.TriggerCapabilityDonInfo.ID, triggerCap) if err != nil { - s.lggr.Errorw("workflow DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) + s.lggr.Errorw("workflow DON failed to set receiver for trigger", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) return } s.subServices = append(s.subServices, triggerCap) + + s.lggr.Info("member of a workflow DON - starting remote targets") + targetCap := target.NewClient(targetInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, 60*time.Second, s.lggr) + err = s.registry.Add(ctx, targetCap) + if err != nil { + s.lggr.Errorw("failed to add remote target capability to registry", "error", err) + return + } + err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) + if err != nil { + s.lggr.Errorw("workflow DON failed to set receiver for target", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) + return + } + s.subServices = append(s.subServices, targetCap) } if s.networkSetup.IsTriggerDon(myId) { s.lggr.Info("member of a capability DON - starting remote publishers") @@ -163,6 +189,24 @@ func (s *registrySyncer) launch(ctx context.Context) { break } } + if s.networkSetup.IsTargetDon(myId) { + s.lggr.Info("member of a target DON - starting remote shims") + underlying, err2 := s.registry.GetTarget(ctx, targetCapId) + if err2 != nil { + s.lggr.Errorw("target not found yet", "capabilityId", targetCapId, "error", err2) + return + } + workflowDONs := map[string]capabilities.DON{ + s.networkSetup.WorkflowsDonInfo.ID: s.networkSetup.WorkflowsDonInfo, + } + targetCap := target.NewServer(myId, underlying, targetInfo, *targetInfo.DON, workflowDONs, s.dispatcher, 60*time.Second, s.lggr) + err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) + if err != nil { + s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) + return + } + s.subServices = append(s.subServices, targetCap) + } // NOTE: temporary service start - should be managed by capability creation for _, srv := range s.subServices { err = srv.Start(ctx) @@ -201,11 +245,13 @@ func (s *registrySyncer) Name() string { type HardcodedDonNetworkSetup struct { workflowDonPeers []string triggerDonPeers []string + targetDonPeers []string triggerDonSigners []string allPeers map[ragetypes.PeerID]p2ptypes.StreamConfig WorkflowsDonInfo capabilities.DON TriggerCapabilityDonInfo capabilities.DON + TargetCapabilityDonInfo capabilities.DON } func NewHardcodedDonNetworkSetup() (HardcodedDonNetworkSetup, error) { @@ -235,6 +281,12 @@ func NewHardcodedDonNetworkSetup() (HardcodedDonNetworkSetup, error) { "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", "0x91d9b0062265514f012Eb8fABA59372fD9520f56", } + result.targetDonPeers = []string{ // "cap-one" + "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", + "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", + "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", + "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", + } result.allPeers = make(map[ragetypes.PeerID]p2ptypes.StreamConfig) addPeersToDONInfo := func(peers []string, donInfo *capabilities.DON) error { @@ -258,6 +310,11 @@ func NewHardcodedDonNetworkSetup() (HardcodedDonNetworkSetup, error) { return HardcodedDonNetworkSetup{}, fmt.Errorf("failed to add peers to trigger DON info: %w", err) } + result.TargetCapabilityDonInfo = capabilities.DON{ID: "targetDon1", F: 1} + if err := addPeersToDONInfo(result.targetDonPeers, &result.TargetCapabilityDonInfo); err != nil { + return HardcodedDonNetworkSetup{}, fmt.Errorf("failed to add peers to target DON info: %w", err) + } + return result, nil } @@ -269,6 +326,10 @@ func (h HardcodedDonNetworkSetup) IsTriggerDon(id p2ptypes.PeerID) bool { return slices.Contains(h.triggerDonPeers, id.String()) } +func (h HardcodedDonNetworkSetup) IsTargetDon(id p2ptypes.PeerID) bool { + return slices.Contains(h.targetDonPeers, id.String()) +} + type mockMercuryDataProducer struct { trigger *triggers.MercuryTriggerService wg sync.WaitGroup diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 97b88330ba3..6f377c0f84d 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -31,12 +31,11 @@ type WriteTarget struct { lggr logger.Logger } -func NewWriteTarget(lggr logger.Logger, name string, cr commontypes.ContractReader, cw commontypes.ChainWriter, forwarderAddress string) *WriteTarget { +func NewWriteTarget(lggr logger.Logger, id string, cr commontypes.ContractReader, cw commontypes.ChainWriter, forwarderAddress string) *WriteTarget { info := capabilities.MustNewCapabilityInfo( - name, + id, capabilities.CapabilityTypeTarget, "Write target.", - "v1.0.0", ) logger := lggr.Named("WriteTarget") @@ -132,10 +131,10 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi // `nil` values, including for slices. Until the bug is fixed we need to ensure that there are no // `nil` values passed in the request. req := struct { - ReceiverAddress string - RawReport []byte - ReportContext []byte - Signatures [][]byte + Receiver string + RawReport []byte + ReportContext []byte + Signatures [][]byte }{reqConfig.Address, inputs.Report, inputs.Context, inputs.Signatures} if req.RawReport == nil { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index 5d77535bdcb..9f243389f27 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -31,7 +31,7 @@ func TestWriteTarget(t *testing.T) { forwarderA := testutils.NewAddress() forwarderAddr := forwarderA.Hex() - writeTarget := targets.NewWriteTarget(lggr, "Test", cr, cw, forwarderAddr) + writeTarget := targets.NewWriteTarget(lggr, "test-write-target@1.0.0", cr, cw, forwarderAddr) require.NotNil(t, writeTarget) config, err := values.NewMap(map[string]any{ diff --git a/core/capabilities/transmission/local_target_capability_test.go b/core/capabilities/transmission/local_target_capability_test.go index 19d51b492ff..6b4d040f0fa 100644 --- a/core/capabilities/transmission/local_target_capability_test.go +++ b/core/capabilities/transmission/local_target_capability_test.go @@ -33,10 +33,9 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { // schedule. mt := newMockCapability( capabilities.MustNewCapabilityInfo( - "write_polygon-testnet-mumbai", + "write_polygon-testnet-mumbai@1.0.0", capabilities.CapabilityTypeTarget, "a write capability targeting polygon mumbai testnet", - "v1.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { gotTime = time.Now() diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 53e54623c55..b16b7df1002 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -12,10 +12,11 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/logger" + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -117,7 +118,7 @@ type chainClient struct { rpc.BatchElem, ] logger logger.SugaredLogger - chainType config.ChainType + chainType chaintype.ChainType clientErrors evmconfig.ClientErrors } @@ -129,7 +130,7 @@ func NewChainClient( nodes []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient], sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient], chainID *big.Int, - chainType config.ChainType, + chainType chaintype.ChainType, clientErrors evmconfig.ClientErrors, ) Client { multiNode := commonclient.NewMultiNode( @@ -140,7 +141,6 @@ func NewChainClient( nodes, sendonlys, chainID, - chainType, "EVM", func(tx *types.Transaction, err error) commonclient.SendTxReturnCode { return ClassifySendError(err, clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, chainType.IsL2()) @@ -254,7 +254,7 @@ func (c *chainClient) HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.H } func (c *chainClient) IsL2() bool { - return c.multiNode.IsL2() + return c.chainType.IsL2() } func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) { diff --git a/core/chains/evm/client/config_builder.go b/core/chains/evm/client/config_builder.go index 7bc12f62151..a88dadde090 100644 --- a/core/chains/evm/client/config_builder.go +++ b/core/chains/evm/client/config_builder.go @@ -9,10 +9,9 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/v2/common/config" - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) @@ -60,7 +59,7 @@ func NewClientConfigs( chainConfig := &evmconfig.EVMConfig{ C: &toml.EVMConfig{ Chain: toml.Chain{ - ChainType: config.NewChainTypeConfig(chainType), + ChainType: chaintype.NewChainTypeConfig(chainType), FinalityDepth: finalityDepth, FinalityTagEnabled: finalityTagEnabled, NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold), diff --git a/core/chains/evm/client/config_builder_test.go b/core/chains/evm/client/config_builder_test.go index d40e2c1b02f..c488511c839 100644 --- a/core/chains/evm/client/config_builder_test.go +++ b/core/chains/evm/client/config_builder_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) func TestClientConfigBuilder(t *testing.T) { @@ -54,14 +55,13 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, *nodeConfigs[0].HTTPURL, (*nodes[0].HTTPURL).String()) // Validate chain config - require.Equal(t, chainTypeStr, string(chainCfg.ChainType())) require.Equal(t, noNewHeadsThreshold, chainCfg.NodeNoNewHeadsThreshold()) require.Equal(t, *finalityDepth, chainCfg.FinalityDepth()) require.Equal(t, *finalityTagEnabled, chainCfg.FinalityTagEnabled()) require.Equal(t, *finalizedBlockOffset, chainCfg.FinalizedBlockOffset()) // let combiler tell us, when we do not have sufficient data to create evm client - _ = client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), big.NewInt(10), nodes) + _ = client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), big.NewInt(10), nodes, chaintype.ChainType(chainTypeStr)) } func TestNodeConfigs(t *testing.T) { diff --git a/core/chains/evm/client/evm_client.go b/core/chains/evm/client/evm_client.go index 98f7c99bf40..4d309440590 100644 --- a/core/chains/evm/client/evm_client.go +++ b/core/chains/evm/client/evm_client.go @@ -8,11 +8,12 @@ import ( commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) -func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, clientErrors evmconfig.ClientErrors, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node) Client { +func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, clientErrors evmconfig.ClientErrors, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node, chainType chaintype.ChainType) Client { var empty url.URL var primaries []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient] var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient] @@ -34,5 +35,5 @@ func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, cli } return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), chainCfg.NodeNoNewHeadsThreshold(), - primaries, sendonlys, chainID, chainCfg.ChainType(), clientErrors) + primaries, sendonlys, chainID, chainType, clientErrors) } diff --git a/core/chains/evm/client/evm_client_test.go b/core/chains/evm/client/evm_client_test.go index 3b43f0ee7e9..9c8f9d66619 100644 --- a/core/chains/evm/client/evm_client_test.go +++ b/core/chains/evm/client/evm_client_test.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" ) @@ -39,6 +40,6 @@ func TestNewEvmClient(t *testing.T) { finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead) require.NoError(t, err) - client := client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), testutils.FixtureChainID, nodes) + client := client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), testutils.FixtureChainID, nodes, chaintype.ChainType(chainTypeStr)) require.NotNil(t, client) } diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index b8a9b206935..39c66271a31 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -13,8 +13,8 @@ import ( commonclient "github.com/smartcontractkit/chainlink/v2/common/client" clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -153,7 +153,7 @@ func NewChainClientWithTestNode( sendonlys = append(sendonlys, s) } - var chainType commonconfig.ChainType + var chainType chaintype.ChainType clientErrors := NewTestClientErrors() c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, noNewHeadsThreshold, primaries, sendonlys, chainID, chainType, &clientErrors) t.Cleanup(c.Close) @@ -169,7 +169,7 @@ func NewChainClientWithEmptyNode( ) Client { lggr := logger.Test(t) - var chainType commonconfig.ChainType + var chainType chaintype.ChainType c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, nil, nil, chainID, chainType, nil) t.Cleanup(c.Close) return c @@ -185,7 +185,7 @@ func NewChainClientWithMockedRpc( ) Client { lggr := logger.Test(t) - var chainType commonconfig.ChainType + var chainType chaintype.ChainType cfg := TestNodePoolConfig{ NodeSelectionMode: commonclient.NodeSelectionModeRoundRobin, diff --git a/core/chains/evm/client/tx_simulator.go b/core/chains/evm/client/tx_simulator.go index 65e108bd227..9bd22cebac0 100644 --- a/core/chains/evm/client/tx_simulator.go +++ b/core/chains/evm/client/tx_simulator.go @@ -7,7 +7,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/common/config" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) type simulatorClient interface { @@ -17,7 +18,7 @@ type simulatorClient interface { // ZK chains can return an out-of-counters error // This method allows a caller to determine if a tx would fail due to OOC error by simulating the transaction // Used as an entry point in case custom simulation is required across different chains -func SimulateTransaction(ctx context.Context, client simulatorClient, lggr logger.SugaredLogger, chainType config.ChainType, msg ethereum.CallMsg) *SendError { +func SimulateTransaction(ctx context.Context, client simulatorClient, lggr logger.SugaredLogger, chainType chaintype.ChainType, msg ethereum.CallMsg) *SendError { err := simulateTransactionDefault(ctx, client, msg) return NewSendError(err) } diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go index 085532dd9d8..db598e3e82b 100644 --- a/core/chains/evm/config/chain_scoped.go +++ b/core/chains/evm/config/chain_scoped.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/logger" - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) @@ -124,7 +124,7 @@ func (e *EVMConfig) BlockEmissionIdleWarningThreshold() time.Duration { return e.C.NoNewHeadsThreshold.Duration() } -func (e *EVMConfig) ChainType() commonconfig.ChainType { +func (e *EVMConfig) ChainType() chaintype.ChainType { if e.C.ChainType == nil { return "" } diff --git a/common/config/chaintype.go b/core/chains/evm/config/chaintype/chaintype.go similarity index 99% rename from common/config/chaintype.go rename to core/chains/evm/config/chaintype/chaintype.go index 8c89aeb4ecd..9b845969e4b 100644 --- a/common/config/chaintype.go +++ b/core/chains/evm/config/chaintype/chaintype.go @@ -1,4 +1,4 @@ -package config +package chaintype import ( "fmt" diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index b1f2a3f6713..f0287e65431 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -9,8 +9,8 @@ import ( 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/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -29,7 +29,7 @@ type EVM interface { BlockBackfillSkip() bool BlockEmissionIdleWarningThreshold() time.Duration ChainID() *big.Int - ChainType() commonconfig.ChainType + ChainType() chaintype.ChainType FinalityDepth() uint32 FinalityTagEnabled() bool FlagsContractAddress() string diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 6f90a453bfd..b16b3e469ac 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -17,8 +17,8 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "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/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -341,7 +341,7 @@ type Chain struct { AutoCreateKey *bool BlockBackfillDepth *uint32 BlockBackfillSkip *bool - ChainType *config.ChainTypeConfig + ChainType *chaintype.ChainTypeConfig FinalityDepth *uint32 FinalityTagEnabled *bool FlagsContractAddress *types.EIP55Address @@ -374,7 +374,7 @@ type Chain struct { func (c *Chain) ValidateConfig() (err error) { if !c.ChainType.ChainType().IsValid() { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: c.ChainType.ChainType(), - Msg: config.ErrInvalidChainType.Error()}) + Msg: chaintype.ErrInvalidChainType.Error()}) } if c.GasEstimator.BumpTxDepth != nil && *c.GasEstimator.BumpTxDepth > *c.Transactions.MaxInFlight { @@ -398,7 +398,7 @@ func (c *Chain) ValidateConfig() (err error) { if c.Transactions.AutoPurge.Enabled != nil && *c.Transactions.AutoPurge.Enabled { chainType := c.ChainType.ChainType() switch chainType { - case config.ChainScroll: + case chaintype.ChainScroll: if c.Transactions.AutoPurge.DetectionApiUrl == nil { err = multierr.Append(err, commonconfig.ErrMissing{Name: "Transactions.AutoPurge.DetectionApiUrl", Msg: fmt.Sprintf("must be set for %s", chainType)}) } else if c.Transactions.AutoPurge.DetectionApiUrl.IsZero() { @@ -410,7 +410,7 @@ func (c *Chain) ValidateConfig() (err error) { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "Transactions.AutoPurge.DetectionApiUrl", Value: c.Transactions.AutoPurge.DetectionApiUrl.Scheme, Msg: "must be http or https"}) } } - case config.ChainZkEvm: + case chaintype.ChainZkEvm: // No other configs are needed default: // Bump Threshold is required because the stuck tx heuristic relies on a minimum number of bump attempts to exist diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index 942bd883c45..38eef40bf76 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -10,7 +10,7 @@ import ( cconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -91,7 +91,7 @@ func Defaults(chainID *big.Big, with ...*Chain) Chain { return c } -func ChainTypeForID(chainID *big.Big) (config.ChainType, bool) { +func ChainTypeForID(chainID *big.Big) (chaintype.ChainType, bool) { s := chainID.String() if d, ok := defaults[s]; ok { return d.ChainType.ChainType(), true diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index f6d15f7aff7..12ccedb4b3b 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -20,10 +20,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" - "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/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -80,7 +80,7 @@ const BumpingHaltedLabel = "Tx gas bumping halted since price exceeds current bl var _ EvmEstimator = &BlockHistoryEstimator{} type chainConfig interface { - ChainType() config.ChainType + ChainType() chaintype.ChainType } type estimatorGasEstimatorConfig interface { @@ -843,7 +843,7 @@ func (b *BlockHistoryEstimator) setPercentileGasPrice(gasPrice *assets.Wei) { // isUsable returns true if the tx is usable both generally and specifically for // this Config. -func (b *BlockHistoryEstimator) IsUsable(tx evmtypes.Transaction, block evmtypes.Block, chainType config.ChainType, minGasPrice *assets.Wei, lggr logger.Logger) bool { +func (b *BlockHistoryEstimator) IsUsable(tx evmtypes.Transaction, block evmtypes.Block, chainType chaintype.ChainType, minGasPrice *assets.Wei, lggr logger.Logger) bool { // GasLimit 0 is impossible on Ethereum official, but IS possible // on forks/clones such as RSK. We should ignore these transactions // if they come up on any chain since they are not normal. diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index b38cd069c69..4f3fddd562f 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -21,11 +21,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/common/config" commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" @@ -990,12 +990,12 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { require.Equal(t, assets.NewWeiI(11), gas.GetGasPrice(bhe)) // Set chainType to Gnosis - GasEstimator should now ignore zero priced transactions - cfg.ChainTypeF = string(config.ChainGnosis) + cfg.ChainTypeF = string(chaintype.ChainGnosis) bhe.Recalculate(testutils.Head(0)) require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) // And for X Layer - cfg.ChainTypeF = string(config.ChainXLayer) + cfg.ChainTypeF = string(chaintype.ChainXLayer) bhe.Recalculate(testutils.Head(0)) require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) }) @@ -1413,7 +1413,7 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.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) + cfg.ChainTypeF = string(chaintype.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.Test(t))) diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go index f9985a6fafc..fba2eda66a0 100644 --- a/core/chains/evm/gas/chain_specific.go +++ b/core/chains/evm/gas/chain_specific.go @@ -1,15 +1,15 @@ package gas import ( - "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/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) // chainSpecificIsUsable allows for additional logic specific to a particular // Config that determines whether a transaction should be used for gas estimation -func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainType config.ChainType, minGasPriceWei *assets.Wei) bool { - if chainType == config.ChainGnosis || chainType == config.ChainXLayer { +func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainType chaintype.ChainType, minGasPriceWei *assets.Wei) bool { + if chainType == chaintype.ChainGnosis || chainType == chaintype.ChainXLayer { // GasPrice 0 on most chains is great since it indicates cheap/free transactions. // However, Gnosis and XLayer reserve a special type of "bridge" transaction with 0 gas // price that is always processed at top priority. Ordinary transactions @@ -19,7 +19,7 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy return false } } - if chainType == config.ChainOptimismBedrock || chainType == config.ChainKroma { + if chainType == chaintype.ChainOptimismBedrock || chainType == chaintype.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 @@ -29,7 +29,7 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy return false } } - if chainType == config.ChainCelo { + if chainType == chaintype.ChainCelo { // Celo specific transaction types that utilize the feeCurrency field. if tx.Type == 0x7c || tx.Type == 0x7b { return false @@ -42,14 +42,14 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy return false } } - if chainType == config.ChainWeMix { + if chainType == chaintype.ChainWeMix { // WeMix specific transaction types that enables fee delegation. // https://docs.wemix.com/v/en/design/fee-delegation if tx.Type == 0x16 { return false } } - if chainType == config.ChainZkSync { + if chainType == chaintype.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 { diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index 420c5060a90..e64b6ad4779 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" - "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/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -119,8 +119,8 @@ func NewMockConfig() *MockConfig { return &MockConfig{} } -func (m *MockConfig) ChainType() config.ChainType { - return config.ChainType(m.ChainTypeF) +func (m *MockConfig) ChainType() chaintype.ChainType { + return chaintype.ChainType(m.ChainTypeF) } func (m *MockConfig) FinalityDepth() uint32 { diff --git a/core/chains/evm/gas/mocks/config.go b/core/chains/evm/gas/mocks/config.go index a3b6b8ee491..5daac211762 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/common/config" + chaintype "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" mock "github.com/stretchr/testify/mock" ) @@ -14,18 +14,18 @@ type Config struct { } // ChainType provides a mock function with given fields: -func (_m *Config) ChainType() config.ChainType { +func (_m *Config) ChainType() chaintype.ChainType { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for ChainType") } - var r0 config.ChainType - if rf, ok := ret.Get(0).(func() config.ChainType); ok { + var r0 chaintype.ChainType + if rf, ok := ret.Get(0).(func() chaintype.ChainType); ok { r0 = rf() } else { - r0 = ret.Get(0).(config.ChainType) + r0 = ret.Get(0).(chaintype.ChainType) } return r0 diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 68fc7378d31..320834cabab 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -15,12 +15,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - "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/common/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "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" @@ -338,7 +338,7 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi // //go:generate mockery --quiet --name Config --output ./mocks/ --case=underscore type Config interface { - ChainType() config.ChainType + ChainType() chaintype.ChainType FinalityDepth() uint32 FinalityTagEnabled() bool } diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index f4366912632..059d0ed3d05 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -12,8 +12,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "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/chaintype" "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/chains/evm/gas/rollups" @@ -65,7 +65,7 @@ func TestWrappedEvmEstimator(t *testing.T) { assert.Nil(t, l1Oracle) // expect l1Oracle - oracle := rollups.NewL1GasOracle(lggr, nil, config.ChainOptimismBedrock) + oracle := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock) // cast oracle to L1Oracle interface estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go index d0b4c5808ad..9e15cfe4c93 100644 --- a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -20,9 +20,9 @@ import ( gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/smartcontractkit/chainlink/v2/common/client" - "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/chains/evm/config/chaintype" ) type ArbL1GasOracle interface { @@ -36,7 +36,7 @@ type arbitrumL1Oracle struct { client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger - chainType config.ChainType + chainType chaintype.ChainType l1GasPriceAddress string gasPriceMethod string @@ -94,7 +94,7 @@ func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *arbit client: ethClient, pollPeriod: PollPeriod, logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(arbitrum)")), - chainType: config.ChainArbitrum, + chainType: chaintype.ChainArbitrum, l1GasPriceAddress: l1GasPriceAddress, gasPriceMethod: gasPriceMethod, diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index 05ceb720ab2..aa152e84e44 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -15,8 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" - "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/chaintype" ) // L1Oracle provides interface for fetching L1-specific fee components if the chain is an L2. @@ -46,21 +46,21 @@ const ( PollPeriod = 6 * time.Second ) -var supportedChainTypes = []config.ChainType{config.ChainArbitrum, config.ChainOptimismBedrock, config.ChainKroma, config.ChainScroll} +var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll} -func IsRollupWithL1Support(chainType config.ChainType) bool { +func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) } -func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType) L1Oracle { +func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) L1Oracle { if !IsRollupWithL1Support(chainType) { return nil } var l1Oracle L1Oracle switch chainType { - case config.ChainOptimismBedrock, config.ChainKroma, config.ChainScroll: + case chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll: l1Oracle = NewOpStackL1GasOracle(lggr, ethClient, chainType) - case config.ChainArbitrum: + case chaintype.ChainArbitrum: l1Oracle = NewArbitrumL1GasOracle(lggr, ethClient) default: panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index b49f92909d6..1e35f6e6d38 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -18,8 +18,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "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/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) @@ -30,7 +30,7 @@ func TestL1Oracle(t *testing.T) { t.Run("Unsupported ChainType returns nil", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - assert.Nil(t, NewL1GasOracle(logger.Test(t), ethClient, config.ChainCelo)) + assert.Nil(t, NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo)) }) } @@ -40,7 +40,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Run("Calling GasPrice on unstarted L1Oracle returns error", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) _, err := oracle.GasPrice(tests.Context(t)) assert.EqualError(t, err, "L1GasOracle is not started; cannot estimate gas") @@ -62,7 +62,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainArbitrum) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -101,7 +101,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainKroma, KromaGasOracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma, KromaGasOracleAddress) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -140,7 +140,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, OPGasOracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, OPGasOracleAddress) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -178,7 +178,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainScroll) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) require.NoError(t, oracle.Start(tests.Context(t))) t.Cleanup(func() { assert.NoError(t, oracle.Close()) }) @@ -222,7 +222,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(result, nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainArbitrum) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) @@ -234,7 +234,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { tx := types.NewTx(&types.LegacyTx{}) ethClient := mocks.NewL1OracleClient(t) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainKroma) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) _, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.Error(t, err, "L1 gas cost not supported for this chain: kroma") @@ -268,7 +268,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(common.BigToHash(l1GasCost).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) @@ -303,7 +303,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(common.BigToHash(l1GasCost).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainScroll) + oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index e180777fb61..1c4db432cea 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -21,9 +21,9 @@ import ( gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/smartcontractkit/chainlink/v2/common/client" - "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/chains/evm/config/chaintype" ) // Reads L2-specific precompiles and caches the l1GasPrice set by the L2. @@ -32,7 +32,7 @@ type OptimismL1Oracle struct { client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger - chainType config.ChainType + chainType chaintype.ChainType l1OracleAddress string gasPriceMethod string @@ -84,14 +84,14 @@ const ( ScrollGasOracleAddress = "0x5300000000000000000000000000000000000002" ) -func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType) *OptimismL1Oracle { +func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) *OptimismL1Oracle { var precompileAddress string switch chainType { - case config.ChainOptimismBedrock: + case chaintype.ChainOptimismBedrock: precompileAddress = OPGasOracleAddress - case config.ChainKroma: + case chaintype.ChainKroma: precompileAddress = KromaGasOracleAddress - case config.ChainScroll: + case chaintype.ChainScroll: precompileAddress = ScrollGasOracleAddress default: panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) @@ -99,7 +99,7 @@ func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy return newOpStackL1GasOracle(lggr, ethClient, chainType, precompileAddress) } -func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType, precompileAddress string) *OptimismL1Oracle { +func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, precompileAddress string) *OptimismL1Oracle { var l1OracleAddress, gasPriceMethod, gasCostMethod string var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI var gasPriceErr, gasCostErr error @@ -274,7 +274,7 @@ func (o *OptimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transac defer cancel() var callData, b []byte var err error - if o.chainType == config.ChainKroma { + if o.chainType == chaintype.ChainKroma { return nil, fmt.Errorf("L1 gas cost not supported for this chain: %s", o.chainType) } // Append rlp-encoded tx diff --git a/core/chains/evm/gas/rollups/op_l1_oracle_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go index 2ed8a049653..86fdbe0a62d 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" ) @@ -87,7 +87,7 @@ func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() } - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) if tc.returnBadData { @@ -155,7 +155,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &res2 }).Return(nil).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) require.NoError(t, err) assert.Equal(t, l1BaseFee, gasPrice) @@ -170,7 +170,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &badData }).Return(nil).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) @@ -179,7 +179,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { ethClient := setupIsEcotone(t, oracleAddress) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) @@ -193,7 +193,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Error = fmt.Errorf("revert") }).Return(nil).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) diff --git a/core/chains/evm/testutils/evmtypes.go b/core/chains/evm/testutils/evmtypes.go index eda284284ba..fedcd52ea2f 100644 --- a/core/chains/evm/testutils/evmtypes.go +++ b/core/chains/evm/testutils/evmtypes.go @@ -84,3 +84,8 @@ func NewLegacyTransaction(nonce uint64, to common.Address, value *big.Int, gasLi } return types.NewTx(&tx) } + +func NewAddressPtr() *common.Address { + a := common.BytesToAddress(randomBytes(20)) + return &a +} diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go index 52340ce51a5..6be8cd7067b 100644 --- a/core/chains/evm/txmgr/attempts_test.go +++ b/core/chains/evm/txmgr/attempts_test.go @@ -15,16 +15,16 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "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" gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "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/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) func NewEvmAddress() gethcommon.Address { @@ -72,7 +72,7 @@ func TestTxm_SignTx(t *testing.T) { kst := ksmocks.NewEth(t) kst.On("SignTx", mock.Anything, to, tx, chainID).Return(tx, nil).Once() cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) - hash, rawBytes, err := cks.SignTx(testutils.Context(t), addr, tx) + hash, rawBytes, err := cks.SignTx(tests.Context(t), addr, tx) require.NoError(t, err) require.NotNil(t, rawBytes) require.Equal(t, "0xdd68f554373fdea7ec6713a6e437e7646465d553a6aa0b43233093366cc87ef0", hash.String()) @@ -83,7 +83,7 @@ func TestTxm_SignTx(t *testing.T) { kst := ksmocks.NewEth(t) kst.On("SignTx", mock.Anything, to, tx, chainID).Return(tx, nil).Once() cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) - hash, rawBytes, err := cks.SignTx(testutils.Context(t), addr, tx) + hash, rawBytes, err := cks.SignTx(tests.Context(t), addr, tx) require.NoError(t, err) require.NotNil(t, rawBytes) require.Equal(t, "0xdd68f554373fdea7ec6713a6e437e7646465d553a6aa0b43233093366cc87ef0", hash.String()) @@ -94,7 +94,7 @@ func TestTxm_SignTx(t *testing.T) { kst.On("SignTx", mock.Anything, to, tx, chainID).Return(tx, nil).Once() cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) - _, rawBytes, err := cks.SignTx(testutils.Context(t), addr, tx) + _, rawBytes, err := cks.SignTx(tests.Context(t), addr, tx) require.NoError(t, err) require.NotNil(t, rawBytes) require.Equal(t, "0xe42a82015681f294b921f7763960b296b9cbad586ff066a18d749724818e83010203808080", hexutil.Encode(rawBytes)) @@ -116,7 +116,7 @@ func TestTxm_SignTx(t *testing.T) { }) kst.On("SignTx", mock.Anything, to, typedTx, chainID).Return(typedTx, nil).Once() cks := txmgr.NewEvmTxAttemptBuilder(*chainID, newFeeConfig(), kst, nil) - _, rawBytes, err := cks.SignTx(testutils.Context(t), addr, typedTx) + _, rawBytes, err := cks.SignTx(tests.Context(t), addr, typedTx) require.NoError(t, err) require.NotNil(t, rawBytes) require.Equal(t, "0xa702e5802a808081f294b921f7763960b296b9cbad586ff066a18d749724818e83010203c0808080", hexutil.Encode(rawBytes)) @@ -141,7 +141,7 @@ func TestTxm_NewDynamicFeeTx(t *testing.T) { feeCfg.priceMax = assets.GWei(200) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), feeCfg, kst, nil) dynamicFee := gas.DynamicFee{TipCap: assets.GWei(100), FeeCap: assets.GWei(200)} - a, _, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ + a, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ DynamicTipCap: dynamicFee.TipCap, DynamicFeeCap: dynamicFee.FeeCap, }, 100, 0x2, lggr) @@ -155,35 +155,34 @@ func TestTxm_NewDynamicFeeTx(t *testing.T) { }) t.Run("verifies gas tip and fees", func(t *testing.T) { - tests := []struct { + cases := []struct { name string tipcap *assets.Wei feecap *assets.Wei - setCfg func(*chainlink.Config, *chainlink.Secrets) + setCfg func(c *toml.EVMConfig) expectError string }{ {"gas tip = fee cap", assets.GWei(5), assets.GWei(5), nil, ""}, {"gas tip < fee cap", assets.GWei(4), assets.GWei(5), nil, ""}, {"gas tip > fee cap", assets.GWei(6), assets.GWei(5), nil, "gas fee cap must be greater than or equal to gas tip cap (fee cap: 5 gwei, tip cap: 6 gwei)"}, - {"fee cap exceeds max allowed", assets.GWei(5), assets.GWei(5), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMax = assets.GWei(4) + {"fee cap exceeds max allowed", assets.GWei(5), assets.GWei(5), func(c *toml.EVMConfig) { + c.GasEstimator.PriceMax = assets.GWei(4) }, "specified gas fee cap of 5 gwei would exceed max configured gas price of 4 gwei"}, - {"ignores global min gas price", assets.GWei(5), assets.GWei(5), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMin = assets.GWei(6) + {"ignores global min gas price", assets.GWei(5), assets.GWei(5), func(c *toml.EVMConfig) { + c.GasEstimator.PriceMin = assets.GWei(6) }, ""}, - {"tip cap below min allowed", assets.GWei(5), assets.GWei(5), func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.TipCapMin = assets.GWei(6) + {"tip cap below min allowed", assets.GWei(5), assets.GWei(5), func(c *toml.EVMConfig) { + c.GasEstimator.TipCapMin = assets.GWei(6) }, "specified gas tip cap of 5 gwei is below min configured gas tip of 6 gwei"}, } - for _, tt := range tests { + for _, tt := range cases { test := tt t.Run(test.name, func(t *testing.T) { - gcfg := configtest.NewGeneralConfig(t, test.setCfg) - cfg := evmtest.NewChainScopedConfig(t, gcfg) + cfg := testutils.NewTestChainScopedConfig(t, test.setCfg) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), cfg.EVM().GasEstimator(), kst, nil) dynamicFee := gas.DynamicFee{TipCap: test.tipcap, FeeCap: test.feecap} - _, _, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ + _, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ DynamicTipCap: dynamicFee.TipCap, DynamicFeeCap: dynamicFee.FeeCap, }, 100, 0x2, lggr) @@ -210,7 +209,7 @@ func TestTxm_NewLegacyAttempt(t *testing.T) { t.Run("creates attempt with fields", func(t *testing.T) { var n evmtypes.Nonce - a, _, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(25)}, 100, 0x0, lggr) + a, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(25)}, 100, 0x0, lggr) require.NoError(t, err) assert.Equal(t, 100, int(a.ChainSpecificFeeLimit)) assert.NotNil(t, a.TxFee.Legacy) @@ -220,7 +219,7 @@ func TestTxm_NewLegacyAttempt(t *testing.T) { }) t.Run("verifies max gas price", func(t *testing.T) { - _, _, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(100)}, 100, 0x0, lggr) + _, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(100)}, 100, 0x0, lggr) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("specified gas price of 100 wei would exceed max configured gas price of 50 wei for key %s", addr.String())) }) @@ -243,7 +242,7 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { est.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bumpedFee, uint64(10_000), nil) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), gc, kst, est) lggr := logger.Test(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("creates legacy purge attempt with fields if previous attempt is legacy", func(t *testing.T) { n := evmtypes.Nonce(0) @@ -318,7 +317,7 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { legacyFee := assets.NewWeiI(100) t.Run("dynamic fee with legacy tx type", func(t *testing.T) { - _, retryable, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{}, gas.EvmFee{ + _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{ DynamicTipCap: dynamicFee.TipCap, DynamicFeeCap: dynamicFee.FeeCap, }, 100, 0x0, lggr) @@ -326,13 +325,13 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { assert.False(t, retryable) }) t.Run("legacy fee with dynamic tx type", func(t *testing.T) { - _, retryable, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{}, gas.EvmFee{Legacy: legacyFee}, 100, 0x2, lggr) + _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{Legacy: legacyFee}, 100, 0x2, lggr) require.Error(t, err) assert.False(t, retryable) }) t.Run("invalid type", func(t *testing.T) { - _, retryable, err := cks.NewCustomTxAttempt(testutils.Context(t), txmgr.Tx{}, gas.EvmFee{}, 100, 0xA, lggr) + _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{}, 100, 0xA, lggr) require.Error(t, err) assert.False(t, retryable) }) @@ -345,7 +344,7 @@ func TestTxm_EvmTxAttemptBuilder_RetryableEstimatorError(t *testing.T) { kst := ksmocks.NewEth(t) lggr := logger.Test(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), &feeConfig{eip1559DynamicFees: true}, kst, est) t.Run("NewAttempt", func(t *testing.T) { diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index c80ae781034..3559c329dee 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -37,11 +38,11 @@ import ( gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "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" "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" @@ -81,7 +82,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { cfg, db := heavyweight.FullTestDBV2(t, nil) txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) @@ -105,7 +106,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { // Can't close an unstarted instance err := eb.Close() require.Error(t, err) - ctx := testutils.Context(t) + ctx := tests.Context(t) // Can start a new instance err = eb.Start(ctx) @@ -139,7 +140,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) @@ -161,7 +162,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) ) // Instance starts without error even if loading next sequence map fails - err := eb.Start(testutils.Context(t)) + err := eb.Start(tests.Context(t)) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, eb.Close()) }) } @@ -169,13 +170,13 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) checkerFactory := &txmgr.CheckerFactory{Client: ethClient} @@ -195,14 +196,14 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { } t.Run("no eth_txes at all", func(t *testing.T) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) }) t.Run("eth_txes exist for a different from address", func(t *testing.T) { - mustCreateUnstartedTx(t, txStore, otherAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + mustCreateUnstartedTx(t, txStore, otherAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) }) @@ -237,7 +238,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { require.NoError(t, txStore.InsertTx(ctx, &etxUnconfirmed)) require.NoError(t, txStore.InsertTx(ctx, &etxWithError)) - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) }) @@ -314,7 +315,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { require.NoError(t, txStore.InsertTx(ctx, &earlierEthTx)) // Do the thing - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) @@ -390,10 +391,10 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { return tx.Nonce() == uint64(343) && tx.Value().Cmp(big.NewInt(242)) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, []byte{42, 42, 0}, gasLimit, big.Int(assets.NewEthValue(242)), &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, []byte{42, 42, 0}, gasLimit, big.Int(assets.NewEthValue(242)), testutils.FixtureChainID) // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -455,10 +456,10 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { return false }), "latest").Return(nil).Once() - ethTx := mustCreateUnstartedTxFromEvmTxRequest(t, txStore, txRequest, &cltest.FixtureChainID) + ethTx := mustCreateUnstartedTxFromEvmTxRequest(t, txStore, txRequest, testutils.FixtureChainID) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -477,12 +478,12 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { return fmt.Sprintf("%s", callarg["value"]) == "0x21e" // 542 }), "latest").Return(errors.New("this is not a revert, something unexpected went wrong")).Once() - ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, + ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithChecker(checker), txRequestWithValue(big.Int(assets.NewEthValue(542)))) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -502,11 +503,11 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { return fmt.Sprintf("%s", callarg["value"]) == "0x282" // 642 }), "latest").Return(&jerr).Once() - ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, + ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithChecker(checker), txRequestWithValue(big.Int(assets.NewEthValue(642)))) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -523,12 +524,12 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { func TestEthBroadcaster_TransmitChecking(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) checkerFactory := &testCheckerFactory{} ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() @@ -546,11 +547,11 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { return tx.Nonce() == 0 && tx.Value().Cmp(big.NewInt(442)) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, + ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithValue(big.Int(assets.NewEthValue(442))), txRequestWithChecker(checker)) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -569,11 +570,11 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { return tx.Nonce() == 1 && tx.Value().Cmp(big.NewInt(442)) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, + ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithValue(big.Int(assets.NewEthValue(442))), txRequestWithChecker(checker)) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -588,9 +589,9 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { // Checker will return a fatal error checkerFactory.err = errors.New("fatal checker error") - ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, txRequestWithChecker(checker)) + ethTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithChecker(checker)) { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -610,7 +611,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi txStore := cltest.NewTestTxStore(t, db) ccfg := evmtest.NewChainScopedConfig(t, cfg) evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM()) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) @@ -643,7 +644,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi // Start instance of broadcaster servicetest.Run(t, eb) - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) go func() { select { @@ -659,7 +660,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi }() { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -679,7 +680,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -697,11 +698,11 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing FeeLimit: 1231, Strategy: txmgrcommon.NewSendEveryStrategy(), } - mustCreateUnstartedTxFromEvmTxRequest(t, txStore, txRequest, &cltest.FixtureChainID) + mustCreateUnstartedTxFromEvmTxRequest(t, txStore, txRequest, testutils.FixtureChainID) // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -717,7 +718,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { secondNonce := nextNonce + 1 cfg := configtest.NewGeneralConfig(t, nil) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("cannot be more than one transaction per address in an unfinished state", func(t *testing.T) { db := pgtest.NewSqlxDB(t) @@ -761,7 +762,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -777,7 +778,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -800,7 +801,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -814,7 +815,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -837,7 +838,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -851,7 +852,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -873,7 +874,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -887,7 +888,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -911,7 +912,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -924,7 +925,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { }), fromAddress).Return(commonclient.Retryable, failedToReachNodeError).Once() // Do the thing - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) require.Error(t, err) assert.Contains(t, err.Error(), failedToReachNodeError.Error()) assert.True(t, retryable) @@ -953,7 +954,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { }) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -972,7 +973,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { // Do the thing { - retryable, err := eb.ProcessUnstartedTxs(testutils.Context(t), fromAddress) + retryable, err := eb.ProcessUnstartedTxs(tests.Context(t), fromAddress) assert.NoError(t, err) assert.False(t, retryable) } @@ -994,7 +995,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { } func getLocalNextNonce(t *testing.T, nonceTracker txmgr.NonceTracker, fromAddress gethCommon.Address) uint64 { - n, err := nonceTracker.GetNextSequence(testutils.Context(t), fromAddress) + n, err := nonceTracker.GetNextSequence(tests.Context(t), fromAddress) require.NoError(t, err) require.NotNil(t, n) return uint64(n) @@ -1017,19 +1018,19 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() lggr := logger.Test(t) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) - ctx := testutils.Context(t) + ctx := tests.Context(t) require.NoError(t, commonutils.JustError(db.Exec(`SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`))) require.NoError(t, commonutils.JustError(db.Exec(`SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`))) t.Run("if external wallet sent a transaction from the account and now the nonce is one higher than it should be and we got replacement underpriced then we assume a previous transaction of ours was the one that succeeded, and hand off to EthConfirmer", func(t *testing.T) { - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) // First send, replacement underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == uint64(0) @@ -1067,7 +1068,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) t.Run("without callback", func(t *testing.T) { - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.Fatal, errors.New(fatalErrorExample)).Once() @@ -1111,7 +1112,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { } t.Run("with erroring callback bails out", func(t *testing.T) { - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) + require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) fn := func(ctx context.Context, id uuid.UUID, result interface{}, err error) error { return errors.New("something exploded in the callback") } @@ -1171,7 +1172,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { TxFeeExceedsCapError := "tx fee (1.10 ether) exceeds the configured cap (1.00 ether)" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New(TxFeeExceedsCapError)).Twice() @@ -1229,7 +1230,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("eth Client call fails with an unexpected random error, and transaction was not accepted into mempool", func(t *testing.T) { retryableErrorExample := "some unknown error" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() @@ -1281,7 +1282,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("eth client call fails with an unexpected random error, and the nonce check also subsequently fails", func(t *testing.T) { retryableErrorExample := "some unknown error" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() @@ -1333,7 +1334,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("eth Client call fails with an unexpected random error, and transaction was accepted into mempool", func(t *testing.T) { retryableErrorExample := "some strange RPC returns an unexpected thing" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.Unknown, errors.New(retryableErrorExample)).Once() @@ -1365,7 +1366,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // This is a configuration error by the node operator, since it means they set the base gas level too low. underpricedError := "transaction underpriced" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) // First was underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { @@ -1481,7 +1482,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { c.EVM[0].GasEstimator.BumpPercent = ptr[uint16](0) })) eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) // First was underpriced ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { @@ -1501,7 +1502,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("eth tx is left in progress if eth node returns insufficient eth", func(t *testing.T) { insufficientEthError := "insufficient funds for transfer" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.InsufficientFunds, errors.New(insufficientEthError)).Once() @@ -1531,7 +1532,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("eth tx is left in progress if nonce is too high", func(t *testing.T) { localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) nonceGapError := "NonceGap, Future nonce. Expected nonce: " + strconv.FormatUint(localNextNonce, 10) - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNextNonce }), fromAddress).Return(commonclient.Retryable, errors.New(nonceGapError)).Once() @@ -1573,7 +1574,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) underpricedError := "transaction underpriced" localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { @@ -1595,7 +1596,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // This is a configuration error by the node operator, since it means they set the base gas level too low. underpricedError := "transaction underpriced" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) // Check gas tip cap verification evmcfg2 := evmtest.NewChainScopedConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1657,21 +1658,21 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, realKeystore.Eth()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) kst := ksmocks.NewEth(t) addresses := []gethCommon.Address{fromAddress} - kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Once() + kst.On("EnabledAddressesForChain", mock.Anything, testutils.FixtureChainID).Return(addresses, nil).Once() ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() lggr := logger.Test(t) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) - ctx := testutils.Context(t) + ctx := tests.Context(t) _, err := nonceTracker.GetNextSequence(ctx, fromAddress) require.NoError(t, err) t.Run("tx signing fails", func(t *testing.T) { - etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, &cltest.FixtureChainID) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) tx := *gethTypes.NewTx(&gethTypes.LegacyTx{}) kst.On("SignTx", mock.Anything, fromAddress, @@ -1711,7 +1712,7 @@ func TestEthBroadcaster_Trigger(t *testing.T) { txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) lggr := logger.Test(t) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -1723,7 +1724,7 @@ func TestEthBroadcaster_Trigger(t *testing.T) { func TestEthBroadcaster_SyncNonce(t *testing.T) { db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) lggr, observed := logger.TestObserved(t, zapcore.DebugLevel) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1744,12 +1745,12 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { ge := evmcfg.EVM().GasEstimator() t.Run("does nothing if nonce sync is disabled", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, estimator) kst := ksmocks.NewEth(t) addresses := []gethCommon.Address{fromAddress} - kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Once() + kst.On("EnabledAddressesForChain", mock.Anything, testutils.FixtureChainID).Return(addresses, nil).Once() ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() txmClient := txmgr.NewEvmTxmClient(ethClient, nil) eb := txmgr.NewEvmBroadcaster(txStore, txmClient, evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, lggr, checkerFactory, false) @@ -1758,7 +1759,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { defer func() { assert.NoError(t, eb.Close()) }() - testutils.WaitForLogMessage(t, observed, "Skipping sequence auto-sync") + tests.AssertLogEventually(t, observed, "Skipping sequence auto-sync") }) } @@ -1771,11 +1772,11 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) checkerFactory := &txmgr.CheckerFactory{Client: ethClient} lggr := logger.Test(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("maintains the proper nonce if there is an in-progress tx during startup", func(t *testing.T) { inProgressTxNonce := uint64(0) diff --git a/core/chains/evm/txmgr/config.go b/core/chains/evm/txmgr/config.go index b41753a070b..c34de17369e 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/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) // 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() config.ChainType + ChainType() chaintype.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 2ce34505234..a3ae0a0a5db 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" @@ -35,11 +36,11 @@ import ( gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -62,7 +63,7 @@ func newBroadcastLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int64 } func mustTxBeInState(t *testing.T, txStore txmgr.TestEvmTxStore, tx txmgr.Tx, expectedState txmgrtypes.TxState) { - etx, err := txStore.FindTxWithAttempts(testutils.Context(t), tx.ID) + etx, err := txStore.FindTxWithAttempts(tests.Context(t), tx.ID) require.NoError(t, err) require.Equal(t, expectedState, etx.State) } @@ -70,7 +71,7 @@ func mustTxBeInState(t *testing.T, txStore txmgr.TestEvmTxStore, tx txmgr.Tx, ex func newTxReceipt(hash gethCommon.Hash, blockNumber int, txIndex uint) evmtypes.Receipt { return evmtypes.Receipt{ TxHash: hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(int64(blockNumber)), TransactionIndex: txIndex, Status: uint64(1), @@ -92,7 +93,7 @@ func mustInsertInProgressEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce etx.State = txmgrcommon.TxInProgress n := evmtypes.Nonce(nonce) etx.Sequence = &n - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) + require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) return etx } @@ -105,7 +106,7 @@ func mustInsertConfirmedEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce now := time.Now() etx.BroadcastAt = &now etx.InitialBroadcastAt = &now - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) + require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) return etx } @@ -117,7 +118,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { gconfig, config := newTestChainScopedConfig(t) txStore := newTxStore(t, db) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() // Add some fromAddresses @@ -131,7 +132,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector) - ctx := testutils.Context(t) + ctx := tests.Context(t) // Can't close unstarted instance err := ec.Close() @@ -145,14 +146,14 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { err = ec.Start(ctx) require.Error(t, err) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 10, Parent: &evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 9, Parent: &evmtypes.Head{ Number: 8, - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Parent: nil, }, }, @@ -188,7 +189,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { gconfig, config := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -196,7 +197,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) nonce := int64(0) - ctx := testutils.Context(t) + ctx := tests.Context(t) blockNum := int64(0) t.Run("only finds eth_txes in unconfirmed state with at least one broadcast attempt", func(t *testing.T) { @@ -244,8 +245,8 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("saves nothing if returned receipt does not match the attempt", func(t *testing.T) { txmReceipt := evmtypes.Receipt{ - TxHash: utils.NewHash(), - BlockHash: utils.NewHash(), + TxHash: testutils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), } @@ -272,7 +273,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("saves nothing if query returns error", func(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt1_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), } @@ -305,7 +306,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("saves eth_receipt and marks eth_tx as confirmed when geth client returns valid receipt", func(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt1_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), @@ -364,7 +365,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt2_2.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), @@ -431,7 +432,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { // NOTE: This should never happen, but we shouldn't panic regardless receipt := evmtypes.Receipt{ TxHash: attempt3_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), Status: uint64(1), } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { @@ -454,7 +455,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { require.Len(t, attempt3_1.Receipts, 0) }) t.Run("handles case where eth_receipt already exists somehow", func(t *testing.T) { - ethReceipt := mustInsertEthReceipt(t, txStore, 42, utils.NewHash(), attempt3_1.Hash) + ethReceipt := mustInsertEthReceipt(t, txStore, 42, testutils.NewHash(), attempt3_1.Hash) txmReceipt := evmtypes.Receipt{ TxHash: attempt3_1.Hash, BlockHash: ethReceipt.BlockHash, @@ -502,7 +503,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt4_2.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), @@ -550,7 +551,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("simulate on revert", func(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt5_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(0), @@ -604,12 +605,12 @@ func TestEthConfirmer_CheckForReceipts_batching(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) var attempts []txmgr.TxAttempt @@ -664,12 +665,12 @@ func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t * txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // tx is not forwarded and doesn't have meta set. EthConfirmer should handle nil meta values etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) @@ -681,7 +682,7 @@ func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t * txmReceipt := evmtypes.Receipt{ TxHash: attempt.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), @@ -717,12 +718,12 @@ func TestEthConfirmer_CheckForReceipts_only_likely_confirmed(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) var attempts []txmgr.TxAttempt // inserting in DESC nonce order to test DB ASC ordering @@ -773,10 +774,10 @@ func TestEthConfirmer_CheckForReceipts_should_not_check_for_likely_unconfirmed(t _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) for i := 0; i < 4; i++ { @@ -802,12 +803,12 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt_scoped_to_key(t _, fromAddress1_2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) _, fromAddress2_1 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(20), nil) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // STATE // key 1, tx with nonce 0 is unconfirmed @@ -869,12 +870,12 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // STATE // eth_txes with nonce 0 has two attempts (broadcast before block 21 and 41) the first of which will get a receipt @@ -911,14 +912,14 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { t.Run("marks buried eth_txes as 'confirmed_missing_receipt'", func(t *testing.T) { txmReceipt0 := evmtypes.Receipt{ TxHash: attempt0_2.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), } txmReceipt3 := evmtypes.Receipt{ TxHash: attempt3_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), Status: uint64(1), @@ -986,7 +987,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { t.Run("marks eth_txes with state 'confirmed_missing_receipt' as 'confirmed' if a receipt finally shows up", func(t *testing.T) { txmReceipt := evmtypes.Receipt{ TxHash: attempt2_1.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(43), TransactionIndex: uint(1), Status: uint64(1), @@ -1125,12 +1126,13 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // STATE // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees @@ -1204,12 +1206,13 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_batchSendTransactions_fails(t _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // STATE // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees @@ -1268,12 +1271,13 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_smallEvmRPCBatchSize_middleBa _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - ctx := testutils.Context(t) + ctx := tests.Context(t) // STATE // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees @@ -1330,9 +1334,9 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1358,7 +1362,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) t.Run("returns nothing when there are no transactions", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1368,7 +1372,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { nonce++ t.Run("returns nothing when the transaction is in_progress", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1379,7 +1383,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { nonce++ t.Run("ignores unconfirmed transactions with nil BroadcastBeforeBlockNum", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1397,7 +1401,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) t.Run("returns nothing when the transaction is unconfirmed with an attempt that is recent", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1411,7 +1415,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, tooNew, attempt2_1.ID)) t.Run("returns nothing when the transaction has attempts that are too new", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1430,14 +1434,14 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { nonce++ t.Run("does nothing if the transaction is from a different address than the one given", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmOtherAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmOtherAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 0) }) t.Run("returns the transaction if it is unconfirmed and has no attempts (note that this is an invariant violation, but we handle it anyway)", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 1) @@ -1445,7 +1449,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { }) t.Run("returns nothing for different chain id", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, big.NewInt(42)) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, big.NewInt(42)) require.NoError(t, err) require.Len(t, etxs, 0) @@ -1466,7 +1470,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attemptOther1.ID)) t.Run("returns the transaction if it is unconfirmed with an attempt that is older than gasBumpThreshold blocks", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -1475,7 +1479,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { }) t.Run("returns nothing if threshold is zero", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, 0, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, 0, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 0) @@ -1489,13 +1493,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { // etxWithoutAttempts (nonce 5) // etx3 (nonce 6) - ready for bump // etx4 (nonce 7) - ready for bump - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 4, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 4, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 1) // returns etxWithoutAttempts only - eligible for gas bumping because it technically doesn't have any attempts within gasBumpThreshold blocks assert.Equal(t, etxWithoutAttempts.ID, etxs[0].ID) - etxs, err = ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 5, 0, &cltest.FixtureChainID) + etxs, err = ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 5, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) // includes etxWithoutAttempts, etx3 and etx4 @@ -1503,7 +1507,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { assert.Equal(t, etx3.ID, etxs[1].ID) // Zero limit disables it - etxs, err = ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 0, 0, &cltest.FixtureChainID) + etxs, err = ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 0, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) // includes etxWithoutAttempts, etx3 and etx4 @@ -1524,7 +1528,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { dbAttempt.FromTxAttempt(&aOther) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, aOther.ID)) - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 6, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 6, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 3) // includes etxWithoutAttempts, etx3 and etx4 @@ -1539,7 +1543,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) t.Run("returns the transaction if it is unconfirmed with two attempts that are older than gasBumpThreshold blocks", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 3) @@ -1554,7 +1558,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_3)) t.Run("does not return the transaction if it has some older but one newer attempt", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -1591,7 +1595,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt6_2)) t.Run("returns unique attempts requiring resubmission due to insufficient eth, ordered by nonce asc", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 4) @@ -1606,7 +1610,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { }) t.Run("applies limit", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(testutils.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 2, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 2, &cltest.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -1622,7 +1626,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing lggr := logger.Test(t) db := pgtest.NewSqlxDB(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) t.Run("should retry previous attempt if connectivity check failed for legacy transactions", func(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1632,7 +1636,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing }) ccfg := evmtest.NewChainScopedConfig(t, cfg) - ctx := testutils.Context(t) + ctx := tests.Context(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1664,7 +1668,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing // Send transaction and assume success. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() - err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead) + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1680,7 +1684,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing }) ccfg := evmtest.NewChainScopedConfig(t, cfg) - ctx := testutils.Context(t) + ctx := tests.Context(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1712,7 +1716,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing // Send transaction and assume success. ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() - err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead) + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1729,9 +1733,9 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { c.EVM[0].GasEstimator.PriceMax = assets.GWei(500) }) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1775,7 +1779,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { }), 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)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1797,9 +1801,9 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { c.EVM[0].GasEstimator.PriceMax = assets.GWei(500) }) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1817,7 +1821,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { nonce := int64(0) t.Run("does nothing if no transactions require bumping", func(t *testing.T) { - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) }) originalBroadcastAt := time.Unix(1616509100, 0) @@ -1836,7 +1840,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { mock.Anything).Return(nil, errors.New("signing error")).Once() // Do the thing - err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead) + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.Error(t, err) require.Contains(t, err.Error(), "signing error") @@ -1866,7 +1870,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1875,7 +1879,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }) var attempt1_2 txmgr.TxAttempt - ethClient = evmtest.NewEthClientMockWithDefaultChain(t) + ethClient = testutils.NewEthClientMockWithDefaultChain(t) ec.XXXTestSetClient(txmgr.NewEvmTxmClient(ethClient, nil)) t.Run("creates new attempt with higher gas price if transaction has an attempt older than threshold", func(t *testing.T) { @@ -1900,7 +1904,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1916,7 +1920,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("does nothing if there is an attempt without BroadcastBeforeBlockNum set", func(t *testing.T) { // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1946,7 +1950,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), 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)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1986,7 +1990,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2038,7 +2042,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Unknown, errors.New("some network error")).Once() // Do the thing - err := ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead) + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.Error(t, err) require.Contains(t, err.Error(), "some network error") @@ -2065,7 +2069,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) // Attempt marked "broadcast" etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) @@ -2105,7 +2109,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), 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)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) require.NoError(t, err) @@ -2146,7 +2150,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) @@ -2183,7 +2187,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), 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)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) @@ -2222,7 +2226,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) @@ -2251,7 +2255,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), 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)) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) @@ -2281,7 +2285,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), 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)) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) @@ -2318,7 +2322,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { 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(commonclient.Successful, nil).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) @@ -2349,7 +2353,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && attempt4_2.Hash.String() == tx.Hash().String() }), fromAddress).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec2.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) @@ -2386,7 +2390,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once() // Do it - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) @@ -2427,7 +2431,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh nonce := int64(0) t.Run("terminally underpriced transaction with in_progress attempt is retried with more gas", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil) originalBroadcastAt := time.Unix(1616509100, 0) @@ -2447,11 +2451,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh kst.On("SignTx", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( signedTx, nil, ).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) }) t.Run("multiple gas bumps with existing broadcast attempts are retried with more gas until success in legacy mode", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) @@ -2475,15 +2479,15 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh ).Run(func(args mock.Arguments) { unsignedLegacyTx := args.Get(2).(*types.Transaction) // Use the real keystore to do the actual signing - thisSignedLegacyTx, err := ethKeyStore.SignTx(testutils.Context(t), fromAddress, unsignedLegacyTx, testutils.FixtureChainID) + thisSignedLegacyTx, err := ethKeyStore.SignTx(tests.Context(t), fromAddress, unsignedLegacyTx, testutils.FixtureChainID) require.NoError(t, err) *signedLegacyTx = *thisSignedLegacyTx }).Times(4) // 3 failures 1 success - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) }) t.Run("multiple gas bumps with existing broadcast attempts are retried with more gas until success in EIP-1559 mode", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil) etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, nonce, fromAddress) @@ -2507,11 +2511,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh ).Run(func(args mock.Arguments) { unsignedDxFeeTx := args.Get(2).(*types.Transaction) // Use the real keystore to do the actual signing - thisSignedDxFeeTx, err := ethKeyStore.SignTx(testutils.Context(t), fromAddress, unsignedDxFeeTx, testutils.FixtureChainID) + thisSignedDxFeeTx, err := ethKeyStore.SignTx(tests.Context(t), fromAddress, unsignedDxFeeTx, testutils.FixtureChainID) require.NoError(t, err) *signedDxFeeTx = *thisSignedDxFeeTx }).Times(4) // 3 failures 1 success - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) }) } @@ -2519,14 +2523,14 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - _, err := ethKeyStore.EnabledKeysForChain(testutils.Context(t), testutils.FixtureChainID) + _, err := ethKeyStore.EnabledKeysForChain(tests.Context(t), testutils.FixtureChainID) require.NoError(t, err) require.NoError(t, err) // keyStates, err := ethKeyStore.GetStatesForKeys(keys) @@ -2558,7 +2562,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2584,7 +2588,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { }), fromAddress).Return(commonclient.InsufficientFunds, insufficientEthError).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2609,7 +2613,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2643,7 +2647,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { nonce++ } - require.NoError(t, ec.RebroadcastWhereNecessary(testutils.Context(t), currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var dbAttempts []txmgr.DbEthTxAttempt @@ -2657,40 +2661,40 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) gconfig, config := newTestChainScopedConfig(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 10, Parent: &evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 9, Parent: &evmtypes.Head{ Number: 8, - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Parent: nil, }, }, } t.Run("does nothing if there aren't any transactions", func(t *testing.T) { - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) }) t.Run("does nothing to unconfirmed transactions", func(t *testing.T) { etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2702,7 +2706,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2712,10 +2716,10 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { t.Run("does nothing to confirmed transactions that only have receipts older than the start of the chain", func(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) // Add receipt that is older than the lowest block of the chain - mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, utils.NewHash(), etx.TxAttempts[0].Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, testutils.NewHash(), etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2726,7 +2730,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress) attempt := etx.TxAttempts[0] // Include one within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attempt.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt.Hash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { atx, err := txmgr.GetGethSignedTx(attempt.SignedRawTx) @@ -2736,7 +2740,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2751,15 +2755,15 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { attempt := etx.TxAttempts[0] attemptHash := attempt.Hash // Add receipt that is older than the lowest block of the chain - mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, utils.NewHash(), attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, testutils.NewHash(), attemptHash) // Include one within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attemptHash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2783,9 +2787,9 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3)) // Receipt is within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attempt2.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt2.Hash) // Receipt is within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attempt3.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt3.Hash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { s, err := txmgr.GetGethSignedTx(attempt3.SignedRawTx) @@ -2794,7 +2798,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2812,9 +2816,9 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress) attempt := etx.TxAttempts[0] // Add receipt that is higher than head - mustInsertEthReceipt(t, txStore, head.Number+1, utils.NewHash(), attempt.Hash) + mustInsertEthReceipt(t, txStore, head.Number+1, testutils.NewHash(), attempt.Hash) - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(testutils.Context(t), &head)) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head)) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2845,7 +2849,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { overrideGasLimit := uint64(20000) t.Run("rebroadcasts one eth_tx if it falls within in nonce range", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { @@ -2856,11 +2860,11 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { tx.To().String() == etx1.ToAddress.String() }), mock.Anything).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit)) + require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{1}, gasPriceWei, fromAddress, overrideGasLimit)) }) t.Run("uses default gas limit if overrideGasLimit is 0", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { @@ -2871,11 +2875,11 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { tx.To().String() == etx1.ToAddress.String() }), mock.Anything).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0)) + require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(1)}, gasPriceWei, fromAddress, 0)) }) t.Run("rebroadcasts several eth_txes in nonce range", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { @@ -2885,11 +2889,11 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { return tx.Nonce() == uint64(*etx2.Sequence) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == overrideGasLimit }), mock.Anything).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit)) + require.NoError(t, ec.ForceRebroadcast(tests.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) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { @@ -2911,18 +2915,18 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { } nonces := []evmtypes.Nonce{(1), (2), (3), (4), (5)} - require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), nonces, gasPriceWei, fromAddress, overrideGasLimit)) + require.NoError(t, ec.ForceRebroadcast(tests.Context(t), nonces, gasPriceWei, fromAddress, overrideGasLimit)) }) t.Run("zero transactions use default gas limit if override wasn't specified", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == config.EVM().GasEstimator().LimitDefault() }), mock.Anything).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.ForceRebroadcast(testutils.Context(t), []evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0)) + require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0)) }) } @@ -2937,19 +2941,19 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, config) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 10, Parent: &evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 9, Parent: &evmtypes.Head{ Number: 8, - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Parent: nil, }, }, @@ -2975,7 +2979,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { // 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) + err := ec.ResumePendingTaskRuns(tests.Context(t), &head) require.NoError(t, err) }) @@ -2993,7 +2997,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - err := ec.ResumePendingTaskRuns(testutils.Context(t), &head) + err := ec.ResumePendingTaskRuns(tests.Context(t), &head) require.NoError(t, err) }) @@ -3021,12 +3025,12 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { t.Cleanup(func() { <-done }) go func() { defer close(done) - err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), &head) if !assert.NoError(t, err2) { return } // Retrieve Tx to check if callback completed flag was set to true - updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce) + updateTx, err3 := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) if assert.NoError(t, err3) { assert.Equal(t, true, updateTx.CallbackCompleted) } @@ -3075,12 +3079,12 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { t.Cleanup(func() { <-done }) go func() { defer close(done) - err2 := ec.ResumePendingTaskRuns(testutils.Context(t), &head) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), &head) if !assert.NoError(t, err2) { return } // Retrieve Tx to check if callback completed flag was set to true - updateTx, err3 := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, nonce) + updateTx, err3 := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) if assert.NoError(t, err3) { assert.Equal(t, true, updateTx.CallbackCompleted) } @@ -3094,7 +3098,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { assert.Nil(t, data.value) - case <-testutils.AfterWaitTimeout(t): + case <-time.After(tests.WaitTimeout(t)): t.Fatal("no value received") } }) @@ -3112,11 +3116,11 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { 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) + err := ec.ResumePendingTaskRuns(tests.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) + updateTx, err := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) require.NoError(t, err) require.Equal(t, false, updateTx.CallbackCompleted) }) @@ -3129,7 +3133,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return(commonclient.Successful, nil).Once() lggr := logger.Test(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) @@ -3157,7 +3161,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector) servicetest.Run(t, ec) - ctx := testutils.Context(t) + ctx := tests.Context(t) blockNum := int64(100) t.Run("detects and processes stuck transactions", func(t *testing.T) { @@ -3168,7 +3172,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, nonce, fromAddress, autoPurgeMinAttempts, blockNum-int64(autoPurgeThreshold), marketGasPrice.Add(oneGwei)) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: blockNum, } ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Once() @@ -3192,7 +3196,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { require.Equal(t, bumpedFee.Legacy, latestAttempt.TxFee.Legacy) head = evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: blockNum + 1, } ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(1), nil) @@ -3203,7 +3207,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { // First transaction confirmed *(elems[0].Result.(*evmtypes.Receipt)) = evmtypes.Receipt{ TxHash: latestAttempt.Hash, - BlockHash: utils.NewHash(), + BlockHash: testutils.NewHash(), BlockNumber: big.NewInt(blockNum + 1), TransactionIndex: uint(1), Status: uint64(1), diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 23b8a9fde33..71b1bd52851 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -16,16 +16,17 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -37,7 +38,7 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -53,7 +54,7 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) // tx 3 has no attempts - mustCreateUnstartedGeneratedTx(t, txStore, from, &cltest.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, from, testutils.FixtureChainID) var count int err := db.Get(&count, `SELECT count(*) FROM evm.txes`) @@ -82,7 +83,7 @@ func TestORM_Transactions(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -98,7 +99,7 @@ func TestORM_Transactions(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) // tx 3 has no attempts - mustCreateUnstartedGeneratedTx(t, txStore, from, &cltest.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, from, testutils.FixtureChainID) var count int err := db.Get(&count, `SELECT count(*) FROM evm.txes`) @@ -122,7 +123,7 @@ func TestORM(t *testing.T) { keyStore := cltest.NewKeyStore(t, db) orm := cltest.NewTestTxStore(t, db) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) - ctx := testutils.Context(t) + ctx := tests.Context(t) var etx txmgr.Tx t.Run("InsertTx", func(t *testing.T) { @@ -188,7 +189,7 @@ func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -208,7 +209,7 @@ func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { _, err := orm.InsertReceipt(ctx, &r.Receipt) require.NoError(t, err) // tx 3 has no attempts - mustCreateUnstartedGeneratedTx(t, orm, from, &cltest.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, orm, from, testutils.FixtureChainID) cltest.MustInsertUnconfirmedEthTx(t, orm, 3, from) // tx4 cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, orm, 4, from) // tx5 @@ -237,7 +238,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -245,7 +246,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Run("returns nothing if there are no transactions", func(t *testing.T) { olderThan := time.Now() - attempts, err := txStore.FindTxAttemptsRequiringResend(testutils.Context(t), olderThan, 10, &cltest.FixtureChainID, fromAddress) + attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 10, testutils.FixtureChainID, fromAddress) require.NoError(t, err) assert.Len(t, attempts, 0) }) @@ -288,14 +289,14 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Run("returns nothing if there are transactions from a different key", func(t *testing.T) { olderThan := time.Now() - attempts, err := txStore.FindTxAttemptsRequiringResend(testutils.Context(t), olderThan, 10, &cltest.FixtureChainID, utils.RandomAddress()) + attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 10, testutils.FixtureChainID, utils.RandomAddress()) require.NoError(t, err) assert.Len(t, attempts, 0) }) t.Run("returns the highest price attempt for each transaction that was last broadcast before or on the given time", func(t *testing.T) { olderThan := time.Unix(1616509200, 0) - attempts, err := txStore.FindTxAttemptsRequiringResend(testutils.Context(t), olderThan, 0, &cltest.FixtureChainID, fromAddress) + attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 0, testutils.FixtureChainID, fromAddress) require.NoError(t, err) assert.Len(t, attempts, 2) assert.Equal(t, attempt1_2.ID, attempts[0].ID) @@ -304,7 +305,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Run("returns the highest price attempt for EIP-1559 transactions", func(t *testing.T) { olderThan := time.Unix(1616509400, 0) - attempts, err := txStore.FindTxAttemptsRequiringResend(testutils.Context(t), olderThan, 0, &cltest.FixtureChainID, fromAddress) + attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 0, testutils.FixtureChainID, fromAddress) require.NoError(t, err) assert.Len(t, attempts, 4) assert.Equal(t, attempt4_4.ID, attempts[3].ID) @@ -312,7 +313,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Run("applies limit", func(t *testing.T) { olderThan := time.Unix(1616509200, 0) - attempts, err := txStore.FindTxAttemptsRequiringResend(testutils.Context(t), olderThan, 1, &cltest.FixtureChainID, fromAddress) + attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 1, testutils.FixtureChainID, fromAddress) require.NoError(t, err) assert.Len(t, attempts, 1) assert.Equal(t, attempt1_2.ID, attempts[0].ID) @@ -329,14 +330,14 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { t.Run("does not update when broadcast_at is NULL", func(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) - etx := mustCreateUnstartedGeneratedTx(t, orm, fromAddress, &cltest.FixtureChainID) + ctx := tests.Context(t) + etx := mustCreateUnstartedGeneratedTx(t, orm, fromAddress, testutils.FixtureChainID) var nullTime *time.Time assert.Equal(t, nullTime, etx.BroadcastAt) currTime := time.Now() - err := orm.UpdateBroadcastAts(testutils.Context(t), currTime, []int64{etx.ID}) + err := orm.UpdateBroadcastAts(tests.Context(t), currTime, []int64{etx.ID}) require.NoError(t, err) etx, err = orm.FindTxWithAttempts(ctx, etx.ID) @@ -347,7 +348,7 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { t.Run("updates when broadcast_at is non-NULL", func(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) time1 := time.Now() etx := cltest.NewEthTx(fromAddress) etx.Sequence = new(evmtypes.Nonce) @@ -378,14 +379,14 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) chainID := ethClient.ConfiguredChainID() - ctx := testutils.Context(t) + ctx := tests.Context(t) headNum := int64(9000) var err error t.Run("saves block num to unconfirmed evm.tx_attempts without one", func(t *testing.T) { // Do the thing - require.NoError(t, txStore.SetBroadcastBeforeBlockNum(testutils.Context(t), headNum, chainID)) + require.NoError(t, txStore.SetBroadcastBeforeBlockNum(tests.Context(t), headNum, chainID)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -402,7 +403,7 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) // Do the thing - require.NoError(t, txStore.SetBroadcastBeforeBlockNum(testutils.Context(t), headNum, chainID)) + require.NoError(t, txStore.SetBroadcastBeforeBlockNum(tests.Context(t), headNum, chainID)) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -413,12 +414,12 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { }) t.Run("only updates evm.tx_attempts for the current chain", func(t *testing.T) { - require.NoError(t, ethKeyStore.Add(testutils.Context(t), fromAddress, testutils.SimulatedChainID)) - require.NoError(t, ethKeyStore.Enable(testutils.Context(t), fromAddress, testutils.SimulatedChainID)) + require.NoError(t, ethKeyStore.Add(tests.Context(t), fromAddress, testutils.SimulatedChainID)) + require.NoError(t, ethKeyStore.Enable(tests.Context(t), fromAddress, testutils.SimulatedChainID)) etxThisChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, cfg.EVM().ChainID()) etxOtherChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, testutils.SimulatedChainID) - require.NoError(t, txStore.SetBroadcastBeforeBlockNum(testutils.Context(t), headNum, chainID)) + require.NoError(t, txStore.SetBroadcastBeforeBlockNum(tests.Context(t), headNum, chainID)) etxThisChain, err = txStore.FindTxWithAttempts(ctx, etxThisChain.ID) require.NoError(t, err) @@ -449,7 +450,7 @@ func TestORM_FindTxAttemptsConfirmedMissingReceipt(t *testing.T) { etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( t, txStore, 0, 1, originalBroadcastAt, fromAddress) - attempts, err := txStore.FindTxAttemptsConfirmedMissingReceipt(testutils.Context(t), ethClient.ConfiguredChainID()) + attempts, err := txStore.FindTxAttemptsConfirmedMissingReceipt(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) @@ -461,7 +462,7 @@ func TestORM_FindTxAttemptsConfirmedMissingReceipt(t *testing.T) { func TestORM_UpdateTxsUnconfirmed(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -471,7 +472,7 @@ func TestORM_UpdateTxsUnconfirmed(t *testing.T) { etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( t, txStore, 0, 1, originalBroadcastAt, fromAddress) assert.Equal(t, etx0.State, txmgrcommon.TxConfirmedMissingReceipt) - require.NoError(t, txStore.UpdateTxsUnconfirmed(testutils.Context(t), []int64{etx0.ID})) + require.NoError(t, txStore.UpdateTxsUnconfirmed(tests.Context(t), []int64{etx0.ID})) etx0, err := txStore.FindTxWithAttempts(ctx, etx0.ID) require.NoError(t, err) @@ -491,7 +492,7 @@ func TestORM_FindTxAttemptsRequiringReceiptFetch(t *testing.T) { etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( t, txStore, 0, 1, originalBroadcastAt, fromAddress) - attempts, err := txStore.FindTxAttemptsRequiringReceiptFetch(testutils.Context(t), ethClient.ConfiguredChainID()) + attempts, err := txStore.FindTxAttemptsRequiringReceiptFetch(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, attempts, 1) assert.Len(t, etx0.TxAttempts, 1) @@ -506,7 +507,7 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ctx := testutils.Context(t) + ctx := tests.Context(t) originalBroadcastAt := time.Unix(1616509100, 0) etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( @@ -521,7 +522,7 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { TransactionIndex: uint(1), } - err := txStore.SaveFetchedReceipts(testutils.Context(t), []*evmtypes.Receipt{&txmReceipt}, txmgrcommon.TxConfirmed, nil, ethClient.ConfiguredChainID()) + err := txStore.SaveFetchedReceipts(tests.Context(t), []*evmtypes.Receipt{&txmReceipt}, txmgrcommon.TxConfirmed, nil, ethClient.ConfiguredChainID()) require.NoError(t, err) etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) @@ -540,7 +541,7 @@ func TestORM_MarkAllConfirmedMissingReceipt(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) // create transaction 0 (nonce 0) that is unconfirmed (block 7) etx0_blocknum := int64(7) @@ -555,7 +556,7 @@ func TestORM_MarkAllConfirmedMissingReceipt(t *testing.T) { assert.Equal(t, etx1.State, txmgrcommon.TxConfirmed) // mark transaction 0 confirmed_missing_receipt - err := txStore.MarkAllConfirmedMissingReceipt(testutils.Context(t), ethClient.ConfiguredChainID()) + err := txStore.MarkAllConfirmedMissingReceipt(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) require.NoError(t, err) @@ -582,7 +583,7 @@ func TestORM_PreloadTxes(t *testing.T) { attempts := []txmgr.TxAttempt{unloadedAttempt} - err := txStore.PreloadTxes(testutils.Context(t), attempts) + err := txStore.PreloadTxes(tests.Context(t), attempts) require.NoError(t, err) assert.Equal(t, etx.ID, attempts[0].Tx.ID) @@ -590,7 +591,7 @@ func TestORM_PreloadTxes(t *testing.T) { t.Run("returns nil when attempts slice is empty", func(t *testing.T) { emptyAttempts := []txmgr.TxAttempt{} - err := txStore.PreloadTxes(testutils.Context(t), emptyAttempts) + err := txStore.PreloadTxes(tests.Context(t), emptyAttempts) require.NoError(t, err) }) } @@ -608,7 +609,7 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) { etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, int64(7), fromAddress, txmgrtypes.TxAttemptInProgress) // fetch attempt - attempts, err := txStore.GetInProgressTxAttempts(testutils.Context(t), fromAddress, ethClient.ConfiguredChainID()) + attempts, err := txStore.GetInProgressTxAttempts(tests.Context(t), fromAddress, ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, attempts, 1) @@ -683,7 +684,7 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { 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()) + receiptsPlus, err := txStore.FindTxesPendingCallback(tests.Context(t), head.Number, ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, receiptsPlus, 1) assert.Equal(t, tr1.ID, receiptsPlus[0].ID) @@ -699,7 +700,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { t.Run("returns nil if no results", func(t *testing.T) { idempotencyKey := "777" - etx, err := txStore.FindTxWithIdempotencyKey(testutils.Context(t), idempotencyKey, big.NewInt(0)) + etx, err := txStore.FindTxWithIdempotencyKey(tests.Context(t), idempotencyKey, big.NewInt(0)) require.NoError(t, err) assert.Nil(t, etx) }) @@ -711,7 +712,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { txRequestWithIdempotencyKey(idempotencyKey)) require.Equal(t, idempotencyKey, *etx.IdempotencyKey) - res, err := txStore.FindTxWithIdempotencyKey(testutils.Context(t), idempotencyKey, big.NewInt(0)) + res, err := txStore.FindTxWithIdempotencyKey(tests.Context(t), idempotencyKey, big.NewInt(0)) require.NoError(t, err) assert.Equal(t, etx.Sequence, res.Sequence) require.Equal(t, idempotencyKey, *res.IdempotencyKey) @@ -727,7 +728,7 @@ func TestORM_FindTxWithSequence(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("returns nil if no results", func(t *testing.T) { - etx, err := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, evmtypes.Nonce(777)) + etx, err := txStore.FindTxWithSequence(tests.Context(t), fromAddress, evmtypes.Nonce(777)) require.NoError(t, err) assert.Nil(t, etx) }) @@ -736,7 +737,7 @@ func TestORM_FindTxWithSequence(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 777, 1, fromAddress) require.Equal(t, evmtypes.Nonce(777), *etx.Sequence) - res, err := txStore.FindTxWithSequence(testutils.Context(t), fromAddress, evmtypes.Nonce(777)) + res, err := txStore.FindTxWithSequence(tests.Context(t), fromAddress, evmtypes.Nonce(777)) require.NoError(t, err) assert.Equal(t, etx.Sequence, res.Sequence) }) @@ -749,7 +750,7 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("delete all receipts for eth transaction", func(t *testing.T) { etx := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 777, 1) @@ -764,7 +765,7 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { assert.Len(t, etx.TxAttempts[0].Receipts, 1) // use exported method - err = txStore.UpdateTxForRebroadcast(testutils.Context(t), etx, attempt) + err = txStore.UpdateTxForRebroadcast(tests.Context(t), etx, attempt) require.NoError(t, err) resultTx, err := txStore.FindTxWithAttempts(ctx, etx.ID) @@ -792,7 +793,7 @@ func TestORM_IsTxFinalized(t *testing.T) { t.Run("confirmed tx not past finality_depth", func(t *testing.T) { confirmedAddr := cltest.MustGenerateRandomKey(t).Address tx := mustInsertConfirmedEthTxWithReceipt(t, txStore, confirmedAddr, 123, 1) - finalized, err := txStore.IsTxFinalized(testutils.Context(t), 2, tx.ID, ethClient.ConfiguredChainID()) + finalized, err := txStore.IsTxFinalized(tests.Context(t), 2, tx.ID, ethClient.ConfiguredChainID()) require.NoError(t, err) require.False(t, finalized) }) @@ -800,7 +801,7 @@ func TestORM_IsTxFinalized(t *testing.T) { t.Run("confirmed tx past finality_depth", func(t *testing.T) { confirmedAddr := cltest.MustGenerateRandomKey(t).Address tx := mustInsertConfirmedEthTxWithReceipt(t, txStore, confirmedAddr, 123, 1) - finalized, err := txStore.IsTxFinalized(testutils.Context(t), 10, tx.ID, ethClient.ConfiguredChainID()) + finalized, err := txStore.IsTxFinalized(tests.Context(t), 10, tx.ID, ethClient.ConfiguredChainID()) require.NoError(t, err) require.True(t, finalized) }) @@ -833,7 +834,7 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { etx_8 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 700, 8) etx_9 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 777, 9) - etxes, err := txStore.FindTransactionsConfirmedInBlockRange(testutils.Context(t), head.Number, 8, ethClient.ConfiguredChainID()) + etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), head.Number, 8, ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, etxes, 2) assert.Equal(t, etxes[0].Sequence, etx_8.Sequence) @@ -851,14 +852,14 @@ func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("no unconfirmed eth txes", func(t *testing.T) { - broadcastAt, err := txStore.FindEarliestUnconfirmedBroadcastTime(testutils.Context(t), ethClient.ConfiguredChainID()) + broadcastAt, err := txStore.FindEarliestUnconfirmedBroadcastTime(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) require.False(t, broadcastAt.Valid) }) t.Run("verify broadcast time", func(t *testing.T) { tx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 123, fromAddress) - broadcastAt, err := txStore.FindEarliestUnconfirmedBroadcastTime(testutils.Context(t), ethClient.ConfiguredChainID()) + broadcastAt, err := txStore.FindEarliestUnconfirmedBroadcastTime(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) require.True(t, broadcastAt.Ptr().Equal(*tx.BroadcastAt)) }) @@ -875,7 +876,7 @@ func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) { _, fromAddress2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("no earliest unconfirmed tx block", func(t *testing.T) { - earliestBlock, err := txStore.FindEarliestUnconfirmedTxAttemptBlock(testutils.Context(t), ethClient.ConfiguredChainID()) + earliestBlock, err := txStore.FindEarliestUnconfirmedTxAttemptBlock(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) require.False(t, earliestBlock.Valid) }) @@ -884,10 +885,10 @@ func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) { var blockNum int64 = 2 tx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 123, blockNum, time.Now(), fromAddress) _ = mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 123, blockNum, time.Now().Add(time.Minute), fromAddress2) - err := txStore.UpdateTxsUnconfirmed(testutils.Context(t), []int64{tx.ID}) + err := txStore.UpdateTxsUnconfirmed(tests.Context(t), []int64{tx.ID}) require.NoError(t, err) - earliestBlock, err := txStore.FindEarliestUnconfirmedTxAttemptBlock(testutils.Context(t), ethClient.ConfiguredChainID()) + earliestBlock, err := txStore.FindEarliestUnconfirmedTxAttemptBlock(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) require.True(t, earliestBlock.Valid) require.Equal(t, blockNum, earliestBlock.Int64) @@ -897,7 +898,7 @@ func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) { func TestORM_SaveInsufficientEthAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -909,7 +910,7 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) { etx := mustInsertInProgressEthTxWithAttempt(t, txStore, 1, fromAddress) now := time.Now() - err = txStore.SaveInsufficientFundsAttempt(testutils.Context(t), defaultDuration, &etx.TxAttempts[0], now) + err = txStore.SaveInsufficientFundsAttempt(tests.Context(t), defaultDuration, &etx.TxAttempts[0], now) require.NoError(t, err) attempt, err := txStore.FindTxAttempt(ctx, etx.TxAttempts[0].Hash) @@ -921,7 +922,7 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) { func TestORM_SaveSentAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -934,7 +935,7 @@ func TestORM_SaveSentAttempt(t *testing.T) { require.Nil(t, etx.BroadcastAt) now := time.Now() - err = txStore.SaveSentAttempt(testutils.Context(t), defaultDuration, &etx.TxAttempts[0], now) + err = txStore.SaveSentAttempt(tests.Context(t), defaultDuration, &etx.TxAttempts[0], now) require.NoError(t, err) attempt, err := txStore.FindTxAttempt(ctx, etx.TxAttempts[0].Hash) @@ -946,7 +947,7 @@ func TestORM_SaveSentAttempt(t *testing.T) { func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -958,7 +959,7 @@ func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 1, fromAddress, txmgrtypes.TxAttemptInProgress) now := time.Now() - err = txStore.SaveConfirmedMissingReceiptAttempt(testutils.Context(t), defaultDuration, &etx.TxAttempts[0], now) + err = txStore.SaveConfirmedMissingReceiptAttempt(tests.Context(t), defaultDuration, &etx.TxAttempts[0], now) require.NoError(t, err) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) @@ -971,7 +972,7 @@ func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { func TestORM_DeleteInProgressAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -981,7 +982,7 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) { etx := mustInsertInProgressEthTxWithAttempt(t, txStore, 1, fromAddress) attempt := etx.TxAttempts[0] - err := txStore.DeleteInProgressAttempt(testutils.Context(t), etx.TxAttempts[0]) + err := txStore.DeleteInProgressAttempt(tests.Context(t), etx.TxAttempts[0]) require.NoError(t, err) nilResult, err := txStore.FindTxAttempt(ctx, attempt.Hash) @@ -993,7 +994,7 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) { func TestORM_SaveInProgressAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1005,7 +1006,7 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) require.Equal(t, int64(0), attempt.ID) - err := txStore.SaveInProgressAttempt(testutils.Context(t), &attempt) + err := txStore.SaveInProgressAttempt(tests.Context(t), &attempt) require.NoError(t, err) attemptResult, err := txStore.FindTxAttempt(ctx, attempt.Hash) @@ -1021,7 +1022,7 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { attempt.BroadcastBeforeBlockNum = nil attempt.State = txmgrtypes.TxAttemptInProgress - err := txStore.SaveInProgressAttempt(testutils.Context(t), &attempt) + err := txStore.SaveInProgressAttempt(tests.Context(t), &attempt) require.NoError(t, err) attemptResult, err := txStore.FindTxAttempt(ctx, attempt.Hash) @@ -1033,7 +1034,7 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { func TestORM_FindTxsRequiringGasBump(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1044,7 +1045,7 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) { t.Run("gets txs requiring gas bump", func(t *testing.T) { etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 1, fromAddress, txmgrtypes.TxAttemptBroadcast) - err := txStore.SetBroadcastBeforeBlockNum(testutils.Context(t), currentBlockNum, ethClient.ConfiguredChainID()) + err := txStore.SetBroadcastBeforeBlockNum(tests.Context(t), currentBlockNum, ethClient.ConfiguredChainID()) require.NoError(t, err) // this tx will require gas bump @@ -1057,13 +1058,13 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) { // this tx will not require gas bump mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 2, fromAddress, txmgrtypes.TxAttemptBroadcast) - err = txStore.SetBroadcastBeforeBlockNum(testutils.Context(t), currentBlockNum+1, ethClient.ConfiguredChainID()) + err = txStore.SetBroadcastBeforeBlockNum(tests.Context(t), currentBlockNum+1, ethClient.ConfiguredChainID()) require.NoError(t, err) // any tx broadcast <= 10 will require gas bump newBlock := int64(12) gasBumpThreshold := int64(2) - etxs, err := txStore.FindTxsRequiringGasBump(testutils.Context(t), fromAddress, newBlock, gasBumpThreshold, int64(0), ethClient.ConfiguredChainID()) + etxs, err := txStore.FindTxsRequiringGasBump(tests.Context(t), fromAddress, newBlock, gasBumpThreshold, int64(0), ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, etxs, 1) assert.Equal(t, etx.ID, etxs[0].ID) @@ -1075,7 +1076,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1097,7 +1098,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, otherAddress) t.Run("returns all eth_txes with at least one attempt that is in insufficient_eth state", func(t *testing.T) { - etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(testutils.Context(t), fromAddress, &cltest.FixtureChainID) + etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 3) @@ -1111,7 +1112,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin }) t.Run("does not return eth_txes with different chain ID", func(t *testing.T) { - etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(testutils.Context(t), fromAddress, big.NewInt(42)) + etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(tests.Context(t), fromAddress, big.NewInt(42)) require.NoError(t, err) assert.Len(t, etxs, 0) @@ -1121,7 +1122,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin pgtest.MustExec(t, db, `UPDATE evm.txes SET state='confirmed' WHERE id = $1`, etx1.ID) pgtest.MustExec(t, db, `UPDATE evm.txes SET state='fatal_error', nonce=NULL, error='foo', broadcast_at=NULL, initial_broadcast_at=NULL WHERE id = $1`, etx2.ID) - etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(testutils.Context(t), fromAddress, &cltest.FixtureChainID) + etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) assert.Len(t, etxs, 1) @@ -1136,7 +1137,7 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ctx := testutils.Context(t) + ctx := tests.Context(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1146,7 +1147,7 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { t.Run("successfully mark errored transactions", func(t *testing.T) { etx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 1, 7, time.Now(), fromAddress) - err := txStore.MarkOldTxesMissingReceiptAsErrored(testutils.Context(t), 10, 2, ethClient.ConfiguredChainID()) + err := txStore.MarkOldTxesMissingReceiptAsErrored(tests.Context(t), 10, 2, ethClient.ConfiguredChainID()) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1156,7 +1157,7 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { t.Run("successfully mark errored transactions w/ qopt passing in sql.Tx", func(t *testing.T) { etx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 1, 7, time.Now(), fromAddress) - err := txStore.MarkOldTxesMissingReceiptAsErrored(testutils.Context(t), 10, 2, ethClient.ConfiguredChainID()) + err := txStore.MarkOldTxesMissingReceiptAsErrored(tests.Context(t), 10, 2, ethClient.ConfiguredChainID()) require.NoError(t, err) // must run other query outside of postgres transaction so changes are committed @@ -1169,7 +1170,7 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { func TestORM_LoadEthTxesAttempts(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1222,7 +1223,7 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) { func TestORM_SaveReplacementInProgressAttempt(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1233,7 +1234,7 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) { oldAttempt := etx.TxAttempts[0] newAttempt := cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) - err := txStore.SaveReplacementInProgressAttempt(testutils.Context(t), oldAttempt, &newAttempt) + err := txStore.SaveReplacementInProgressAttempt(tests.Context(t), oldAttempt, &newAttempt) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1256,14 +1257,14 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { t.Run("cannot find unstarted tx", func(t *testing.T) { mustInsertInProgressEthTxWithAttempt(t, txStore, 13, fromAddress) - resultEtx, err := txStore.FindNextUnstartedTransactionFromAddress(testutils.Context(t), fromAddress, ethClient.ConfiguredChainID()) + resultEtx, err := txStore.FindNextUnstartedTransactionFromAddress(tests.Context(t), fromAddress, ethClient.ConfiguredChainID()) assert.ErrorIs(t, err, sql.ErrNoRows) assert.Nil(t, resultEtx) }) t.Run("finds unstarted tx", func(t *testing.T) { - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) - resultEtx, err := txStore.FindNextUnstartedTransactionFromAddress(testutils.Context(t), fromAddress, ethClient.ConfiguredChainID()) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) + resultEtx, err := txStore.FindNextUnstartedTransactionFromAddress(tests.Context(t), fromAddress, ethClient.ConfiguredChainID()) require.NoError(t, err) assert.NotNil(t, resultEtx) }) @@ -1272,7 +1273,7 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { func TestORM_UpdateTxFatalError(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1284,7 +1285,7 @@ func TestORM_UpdateTxFatalError(t *testing.T) { etxPretendError := null.StringFrom("no more toilet paper") etx.Error = etxPretendError - err := txStore.UpdateTxFatalError(testutils.Context(t), &etx) + err := txStore.UpdateTxFatalError(tests.Context(t), &etx) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -1296,7 +1297,7 @@ func TestORM_UpdateTxFatalError(t *testing.T) { func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1311,7 +1312,7 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { i := int16(0) etx.BroadcastAt = &time1 etx.InitialBroadcastAt = &time1 - err := txStore.UpdateTxAttemptInProgressToBroadcast(testutils.Context(t), &etx, attempt, txmgrtypes.TxAttemptBroadcast) + err := txStore.UpdateTxAttemptInProgressToBroadcast(tests.Context(t), &etx, attempt, txmgrtypes.TxAttemptBroadcast) require.NoError(t, err) // Increment sequence i++ @@ -1327,7 +1328,7 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() @@ -1335,11 +1336,11 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { nonce := evmtypes.Nonce(123) t.Run("update successful", func(t *testing.T) { - etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) + etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx.Sequence = &nonce attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - err := txStore.UpdateTxUnstartedToInProgress(testutils.Context(t), &etx, &attempt) + err := txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx, &attempt) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) @@ -1349,7 +1350,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { }) t.Run("update fails because tx is removed", func(t *testing.T) { - etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) + etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx.Sequence = &nonce attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) @@ -1357,7 +1358,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { _, err := db.ExecContext(ctx, "DELETE FROM evm.txes WHERE id = $1", etx.ID) require.NoError(t, err) - err = txStore.UpdateTxUnstartedToInProgress(testutils.Context(t), &etx, &attempt) + err = txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx, &attempt) require.ErrorContains(t, err, "tx removed") }) @@ -1385,14 +1386,14 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { err := txMgr.XXXTestAbandon(fromAddress) // mark transaction as abandoned require.NoError(t, err) - etx2 := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) + etx2 := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx2.Sequence = &nonce attempt2 := cltest.NewLegacyEthTxAttempt(t, etx2.ID) attempt2.Hash = etx.TxAttempts[0].Hash // Even though this will initially fail due to idx_eth_tx_attempts_hash constraint, because the conflicting tx has been abandoned // it should succeed after removing the abandoned attempt and retrying the insert - err = txStore.UpdateTxUnstartedToInProgress(testutils.Context(t), &etx2, &attempt2) + err = txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx2, &attempt2) require.NoError(t, err) }) @@ -1406,7 +1407,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { etx.State = txmgrcommon.TxUnstarted // Should fail due to idx_eth_tx_attempt_hash constraint - err := txStore.UpdateTxUnstartedToInProgress(testutils.Context(t), &etx, &etx.TxAttempts[0]) + err := txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx, &etx.TxAttempts[0]) assert.ErrorContains(t, err, "idx_eth_tx_attempts_hash") txStore = cltest.NewTestTxStore(t, db) // current txStore is poisened now, next test will need fresh one }) @@ -1421,7 +1422,7 @@ func TestORM_GetTxInProgress(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("gets 0 in progress eth transaction", func(t *testing.T) { - etxResult, err := txStore.GetTxInProgress(testutils.Context(t), fromAddress) + etxResult, err := txStore.GetTxInProgress(tests.Context(t), fromAddress) require.NoError(t, err) require.Nil(t, etxResult) }) @@ -1429,7 +1430,7 @@ func TestORM_GetTxInProgress(t *testing.T) { t.Run("get 1 in progress eth transaction", func(t *testing.T) { etx := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) - etxResult, err := txStore.GetTxInProgress(testutils.Context(t), fromAddress) + etxResult, err := txStore.GetTxInProgress(tests.Context(t), fromAddress) require.NoError(t, err) assert.Equal(t, etxResult.ID, etx.ID) }) @@ -1447,7 +1448,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { enabledAddrs := []common.Address{enabled} t.Run("get 0 abandoned transactions", func(t *testing.T) { - txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) + txes, err := txStore.GetAbandonedTransactionsByBatch(tests.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) require.NoError(t, err) require.Empty(t, txes) }) @@ -1455,7 +1456,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { t.Run("do not return enabled addresses", func(t *testing.T) { _ = mustInsertInProgressEthTxWithAttempt(t, txStore, 123, enabled) _ = mustCreateUnstartedGeneratedTx(t, txStore, enabled, ethClient.ConfiguredChainID()) - txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) + txes, err := txStore.GetAbandonedTransactionsByBatch(tests.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) require.NoError(t, err) require.Empty(t, txes) }) @@ -1464,7 +1465,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { inProgressTx := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) unstartedTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, ethClient.ConfiguredChainID()) - txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) + txes, err := txStore.GetAbandonedTransactionsByBatch(tests.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) require.NoError(t, err) require.Len(t, txes, 2) @@ -1482,7 +1483,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { allTxes := make([]*txmgr.Tx, 0) err := sqlutil.Batch(func(offset, limit uint) (count uint, err error) { - batchTxes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, offset, limit) + batchTxes, err := txStore.GetAbandonedTransactionsByBatch(tests.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, offset, limit) require.NoError(t, err) allTxes = append(allTxes, batchTxes...) return uint(len(batchTxes)), nil @@ -1501,14 +1502,14 @@ func TestORM_GetTxByID(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("no transaction", func(t *testing.T) { - tx, err := txStore.GetTxByID(testutils.Context(t), int64(0)) + tx, err := txStore.GetTxByID(tests.Context(t), int64(0)) require.NoError(t, err) require.Nil(t, tx) }) t.Run("get transaction by ID", func(t *testing.T) { insertedTx := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) - tx, err := txStore.GetTxByID(testutils.Context(t), insertedTx.ID) + tx, err := txStore.GetTxByID(tests.Context(t), insertedTx.ID) require.NoError(t, err) require.NotNil(t, tx) }) @@ -1523,14 +1524,14 @@ func TestORM_GetFatalTransactions(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("gets 0 fatal eth transactions", func(t *testing.T) { - txes, err := txStore.GetFatalTransactions(testutils.Context(t)) + txes, err := txStore.GetFatalTransactions(tests.Context(t)) require.NoError(t, err) require.Empty(t, txes) }) t.Run("get fatal transactions", func(t *testing.T) { fatalTx := mustInsertFatalErrorEthTx(t, txStore, fromAddress) - txes, err := txStore.GetFatalTransactions(testutils.Context(t)) + txes, err := txStore.GetFatalTransactions(tests.Context(t)) require.NoError(t, err) require.Equal(t, txes[0].ID, fatalTx.ID) }) @@ -1546,7 +1547,7 @@ func TestORM_HasInProgressTransaction(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("no in progress eth transaction", func(t *testing.T) { - exists, err := txStore.HasInProgressTransaction(testutils.Context(t), fromAddress, ethClient.ConfiguredChainID()) + exists, err := txStore.HasInProgressTransaction(tests.Context(t), fromAddress, ethClient.ConfiguredChainID()) require.NoError(t, err) require.False(t, exists) }) @@ -1554,7 +1555,7 @@ func TestORM_HasInProgressTransaction(t *testing.T) { t.Run("has in progress eth transaction", func(t *testing.T) { mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) - exists, err := txStore.HasInProgressTransaction(testutils.Context(t), fromAddress, ethClient.ConfiguredChainID()) + exists, err := txStore.HasInProgressTransaction(tests.Context(t), fromAddress, ethClient.ConfiguredChainID()) require.NoError(t, err) require.True(t, exists) }) @@ -1575,7 +1576,7 @@ func TestORM_CountUnconfirmedTransactions(t *testing.T) { cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - count, err := txStore.CountUnconfirmedTransactions(testutils.Context(t), fromAddress, &cltest.FixtureChainID) + count, err := txStore.CountUnconfirmedTransactions(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) assert.Equal(t, int(count), 3) } @@ -1595,7 +1596,7 @@ func TestORM_CountTransactionsByState(t *testing.T) { cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress2) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress3) - count, err := txStore.CountTransactionsByState(testutils.Context(t), txmgrcommon.TxUnconfirmed, &cltest.FixtureChainID) + count, err := txStore.CountTransactionsByState(tests.Context(t), txmgrcommon.TxUnconfirmed, testutils.FixtureChainID) require.NoError(t, err) assert.Equal(t, int(count), 3) } @@ -1610,12 +1611,12 @@ func TestORM_CountUnstartedTransactions(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID) - mustCreateUnstartedGeneratedTx(t, txStore, otherAddress, &cltest.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) + mustCreateUnstartedGeneratedTx(t, txStore, otherAddress, testutils.FixtureChainID) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - count, err := txStore.CountUnstartedTransactions(testutils.Context(t), fromAddress, &cltest.FixtureChainID) + count, err := txStore.CountUnstartedTransactions(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) assert.Equal(t, int(count), 2) } @@ -1637,17 +1638,17 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { var maxUnconfirmedTransactions uint64 = 2 t.Run("with no eth_txes returns nil", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.NoError(t, err) }) // deliberately one extra to exceed limit for i := 0; i <= int(maxUnconfirmedTransactions); i++ { - mustCreateUnstartedTx(t, txStore, otherAddress, toAddress, encodedPayload, feeLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, otherAddress, toAddress, encodedPayload, feeLimit, value, testutils.FixtureChainID) } t.Run("with eth_txes from another address returns nil", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.NoError(t, err) }) @@ -1656,7 +1657,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { } t.Run("ignores fatally_errored transactions", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.NoError(t, err) }) @@ -1667,7 +1668,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { n++ t.Run("unconfirmed and in_progress transactions do not count", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, 1, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, 1, testutils.FixtureChainID) require.NoError(t, err) }) @@ -1678,39 +1679,39 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { } t.Run("with many confirmed eth_txes from the same address returns nil", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.NoError(t, err) }) for i := 0; i < int(maxUnconfirmedTransactions)-1; i++ { - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, testutils.FixtureChainID) } t.Run("with fewer unstarted eth_txes than limit returns nil", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.NoError(t, err) }) - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, testutils.FixtureChainID) t.Run("with equal or more unstarted eth_txes than limit returns error", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.Error(t, err) require.Contains(t, err.Error(), fmt.Sprintf("cannot create transaction; too many unstarted transactions in the queue (2/%d). WARNING: Hitting EVM.Transactions.MaxQueued", maxUnconfirmedTransactions)) - mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, &cltest.FixtureChainID) - err = txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, &cltest.FixtureChainID) + mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, feeLimit, value, testutils.FixtureChainID) + err = txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, testutils.FixtureChainID) require.Error(t, err) require.Contains(t, err.Error(), fmt.Sprintf("cannot create transaction; too many unstarted transactions in the queue (3/%d). WARNING: Hitting EVM.Transactions.MaxQueued", maxUnconfirmedTransactions)) }) t.Run("with different chain ID ignores txes", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, maxUnconfirmedTransactions, big.NewInt(42)) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, maxUnconfirmedTransactions, big.NewInt(42)) require.NoError(t, err) }) t.Run("disables check with 0 limit", func(t *testing.T) { - err := txStore.CheckTxQueueCapacity(testutils.Context(t), fromAddress, 0, &cltest.FixtureChainID) + err := txStore.CheckTxQueueCapacity(tests.Context(t), fromAddress, 0, testutils.FixtureChainID) require.NoError(t, err) }) } @@ -1733,7 +1734,7 @@ func TestORM_CreateTransaction(t *testing.T) { subject := uuid.New() strategy := newMockTxStrategy(t) strategy.On("Subject").Return(uuid.NullUUID{UUID: subject, Valid: true}) - etx, err := txStore.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txStore.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -1776,10 +1777,10 @@ func TestORM_CreateTransaction(t *testing.T) { PipelineTaskRunID: &id, Strategy: txmgrcommon.NewSendEveryStrategy(), } - tx1, err := txStore.CreateTransaction(testutils.Context(t), txRequest, ethClient.ConfiguredChainID()) + tx1, err := txStore.CreateTransaction(tests.Context(t), txRequest, ethClient.ConfiguredChainID()) assert.NoError(t, err) - tx2, err := txStore.CreateTransaction(testutils.Context(t), txRequest, ethClient.ConfiguredChainID()) + tx2, err := txStore.CreateTransaction(tests.Context(t), txRequest, ethClient.ConfiguredChainID()) assert.NoError(t, err) assert.Equal(t, tx1.GetID(), tx2.GetID()) @@ -1789,7 +1790,7 @@ func TestORM_CreateTransaction(t *testing.T) { subject := uuid.New() strategy := newMockTxStrategy(t) strategy.On("Subject").Return(uuid.NullUUID{UUID: subject, Valid: true}) - etx, err := txStore.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txStore.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -1827,7 +1828,7 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { subject1 := uuid.New() strategy1 := txmgrcommon.NewDropOldestStrategy(subject1, uint32(5)) for i := 0; i < 5; i++ { - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, txRequestWithStrategy(strategy1)) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithStrategy(strategy1)) } AssertCountPerSubject(t, txStore, int64(4), subject1) }) @@ -1836,7 +1837,7 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { subject2 := uuid.New() strategy2 := txmgrcommon.NewDropOldestStrategy(subject2, uint32(3)) for i := 0; i < 5; i++ { - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, &cltest.FixtureChainID, txRequestWithStrategy(strategy2)) + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID, txRequestWithStrategy(strategy2)) } AssertCountPerSubject(t, txStore, int64(2), subject2) }) @@ -1848,7 +1849,7 @@ func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -1866,7 +1867,7 @@ func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) { func AssertCountPerSubject(t *testing.T, txStore txmgr.TestEvmTxStore, expected int64, subject uuid.UUID) { t.Helper() - count, err := txStore.CountTxesByStateAndSubject(testutils.Context(t), "unstarted", subject) + count, err := txStore.CountTxesByStateAndSubject(tests.Context(t), "unstarted", subject) require.NoError(t, err) require.Equal(t, int(expected), count) } diff --git a/core/chains/evm/txmgr/mocks/config.go b/core/chains/evm/txmgr/mocks/config.go index 5b8e77a69cc..5ec00e960ab 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/common/config" + chaintype "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" mock "github.com/stretchr/testify/mock" ) @@ -13,18 +13,18 @@ type Config struct { } // ChainType provides a mock function with given fields: -func (_m *Config) ChainType() config.ChainType { +func (_m *Config) ChainType() chaintype.ChainType { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for ChainType") } - var r0 config.ChainType - if rf, ok := ret.Get(0).(func() config.ChainType); ok { + var r0 chaintype.ChainType + if rf, ok := ret.Get(0).(func() chaintype.ChainType); ok { r0 = rf() } else { - r0 = ret.Get(0).(config.ChainType) + r0 = ret.Get(0).(chaintype.ChainType) } return r0 diff --git a/core/chains/evm/txmgr/nonce_tracker_test.go b/core/chains/evm/txmgr/nonce_tracker_test.go index 17c042e375e..c9e3cbd76c3 100644 --- a/core/chains/evm/txmgr/nonce_tracker_test.go +++ b/core/chains/evm/txmgr/nonce_tracker_test.go @@ -13,12 +13,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" clientmock "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txstoremock "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "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/internal/testutils/pgtest" ) @@ -26,7 +26,7 @@ import ( func TestNonceTracker_LoadSequenceMap(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) txStore := txstoremock.NewEvmTxStore(t) @@ -77,7 +77,7 @@ func TestNonceTracker_LoadSequenceMap(t *testing.T) { func TestNonceTracker_syncOnChain(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) txStore := txstoremock.NewEvmTxStore(t) @@ -133,7 +133,7 @@ func TestNonceTracker_syncOnChain(t *testing.T) { func TestNonceTracker_SyncSequence(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) txStore := txstoremock.NewEvmTxStore(t) @@ -180,7 +180,7 @@ func TestNonceTracker_SyncSequence(t *testing.T) { func TestNonceTracker_GetNextSequence(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) txStore := txstoremock.NewEvmTxStore(t) @@ -230,7 +230,7 @@ func TestNonceTracker_GetNextSequence(t *testing.T) { func TestNonceTracker_GenerateNextSequence(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) txStore := txstoremock.NewEvmTxStore(t) @@ -259,10 +259,10 @@ func TestNonceTracker_GenerateNextSequence(t *testing.T) { func Test_SetNonceAfterInit(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) chainID := big.NewInt(0) db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgr.NewTxStore(db, logger.Test(t)) client := clientmock.NewClient(t) client.On("ConfiguredChainID").Return(chainID) diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go index 331e39d6ccf..48a1ec3af16 100644 --- a/core/chains/evm/txmgr/resender_test.go +++ b/core/chains/evm/txmgr/resender_test.go @@ -15,15 +15,14 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/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" ) func Test_EthResender_resendUnconfirmed(t *testing.T) { @@ -32,9 +31,9 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) { db := pgtest.NewSqlxDB(t) lggr := logger.Test(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) - ccfg := evmtest.NewChainScopedConfig(t, cfg) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() + ccfg := testutils.NewTestChainScopedConfig(t, nil) _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, fromAddress2 := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -102,17 +101,15 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { db := pgtest.NewSqlxDB(t) lggr, o := logger.TestObserved(t, zapcore.DebugLevel) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() // Set this to the smallest non-zero value possible for the attempt to be eligible for resend delay := commonconfig.MustNewDuration(1 * time.Nanosecond) - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0] = &toml.EVMConfig{ - Chain: toml.Defaults(ubig.New(big.NewInt(0)), &toml.Chain{ - Transactions: toml.Transactions{ResendAfterThreshold: delay}, - }), - } + ccfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + c.Chain = toml.Defaults(ubig.New(big.NewInt(0)), &toml.Chain{ + Transactions: toml.Transactions{ResendAfterThreshold: delay}, + }) }) - ccfg := evmtest.NewChainScopedConfig(t, cfg) _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -132,7 +129,7 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { err2 := er.XXXTestResendUnconfirmed() require.NoError(t, err2) - testutils.WaitForLogMessageCount(t, o, "TxAttempt has been unconfirmed for more than max duration", 1) + tests.AssertLogCountEventually(t, o, "TxAttempt has been unconfirmed for more than max duration", 1) }) } @@ -140,21 +137,22 @@ func Test_EthResender_Start(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + ccfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { // This can be anything as long as it isn't zero - c.EVM[0].Transactions.ResendAfterThreshold = commonconfig.MustNewDuration(42 * time.Hour) + c.Transactions.ResendAfterThreshold = commonconfig.MustNewDuration(42 * time.Hour) // Set batch size low to test batching - c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) + c.RPCDefaultBatchSize = ptr[uint32](1) }) + txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ccfg := evmtest.NewChainScopedConfig(t, cfg) _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.Test(t) t.Run("resends transactions that have been languishing unconfirmed for too long", func(t *testing.T) { - ctx := testutils.Context(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() er := txmgr.NewEvmResender(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTracker(txStore, ethKeyStore, big.NewInt(0), lggr), ethKeyStore, 100*time.Millisecond, ccfg.EVM(), ccfg.EVM().Transactions()) diff --git a/core/chains/evm/txmgr/strategies_test.go b/core/chains/evm/txmgr/strategies_test.go index d7f4ceaf450..4b04009fd24 100644 --- a/core/chains/evm/txmgr/strategies_test.go +++ b/core/chains/evm/txmgr/strategies_test.go @@ -8,9 +8,10 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + 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" ) func Test_SendEveryStrategy(t *testing.T) { @@ -20,7 +21,7 @@ func Test_SendEveryStrategy(t *testing.T) { assert.Equal(t, uuid.NullUUID{}, s.Subject()) - ids, err := s.PruneQueue(testutils.Context(t), nil) + ids, err := s.PruneQueue(tests.Context(t), nil) assert.NoError(t, err) assert.Len(t, ids, 0) } @@ -44,7 +45,7 @@ func Test_DropOldestStrategy_PruneQueue(t *testing.T) { t.Run("calls PrineUnstartedTxQueue for the given subject and queueSize, ignoring fromAddress", func(t *testing.T) { strategy1 := txmgrcommon.NewDropOldestStrategy(subject, queueSize) mockTxStore.On("PruneUnstartedTxQueue", mock.Anything, queueSize-1, subject, mock.Anything, mock.Anything).Once().Return([]int64{1, 2}, nil) - ids, err := strategy1.PruneQueue(testutils.Context(t), mockTxStore) + ids, err := strategy1.PruneQueue(tests.Context(t), mockTxStore) require.NoError(t, err) assert.Equal(t, []int64{1, 2}, ids) }) diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index d48cdf00e79..23cb9b2698a 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -14,11 +14,11 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/common/config" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" ) @@ -44,7 +44,7 @@ type stuckTxDetectorConfig interface { type stuckTxDetector struct { lggr logger.Logger chainID *big.Int - chainType config.ChainType + chainType chaintype.ChainType maxPrice *assets.Wei cfg stuckTxDetectorConfig @@ -57,7 +57,7 @@ type stuckTxDetector struct { purgeBlockNumMap map[common.Address]int64 // Tracks the last block num a tx was purged for each from address if the PurgeOverflowTxs feature is enabled } -func NewStuckTxDetector(lggr logger.Logger, chainID *big.Int, chainType config.ChainType, maxPrice *assets.Wei, cfg stuckTxDetectorConfig, gasEstimator stuckTxDetectorGasEstimator, txStore stuckTxDetectorTxStore, chainClient stuckTxDetectorClient) *stuckTxDetector { +func NewStuckTxDetector(lggr logger.Logger, chainID *big.Int, chainType chaintype.ChainType, maxPrice *assets.Wei, cfg stuckTxDetectorConfig, gasEstimator stuckTxDetectorGasEstimator, txStore stuckTxDetectorTxStore, chainClient stuckTxDetectorClient) *stuckTxDetector { t := http.DefaultTransport.(*http.Transport).Clone() t.DisableCompression = true httpClient := &http.Client{Transport: t} @@ -124,9 +124,9 @@ func (d *stuckTxDetector) DetectStuckTransactions(ctx context.Context, enabledAd } switch d.chainType { - case config.ChainScroll: + case chaintype.ChainScroll: return d.detectStuckTransactionsScroll(ctx, txs) - case config.ChainZkEvm: + case chaintype.ChainZkEvm: return d.detectStuckTransactionsZkEVM(ctx, txs) default: return d.detectStuckTransactionsHeuristic(ctx, txs, blockNum) @@ -365,7 +365,7 @@ func (d *stuckTxDetector) SetPurgeBlockNum(fromAddress common.Address, blockNum func (d *stuckTxDetector) StuckTxFatalError() *string { var errorMsg string switch d.chainType { - case config.ChainScroll, config.ChainZkEvm: + case chaintype.ChainScroll, chaintype.ChainZkEvm: errorMsg = "transaction skipped by chain" default: errorMsg = "transaction terminally stuck" diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go index 39c275d286f..e980527c989 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector_test.go +++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go @@ -16,17 +16,18 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/logger" - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "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/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "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/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -44,7 +45,7 @@ func TestStuckTxDetector_Disabled(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.Test(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) autoPurgeCfg := testAutoPurgeConfig{ enabled: false, @@ -52,7 +53,7 @@ func TestStuckTxDetector_Disabled(t *testing.T) { stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) t.Run("returns empty list if auto-purge feature is disabled", func(t *testing.T) { - txs, err := stuckTxDetector.DetectStuckTransactions(testutils.Context(t), []common.Address{fromAddress}, 100) + txs, err := stuckTxDetector.DetectStuckTransactions(tests.Context(t), []common.Address{fromAddress}, 100) require.NoError(t, err) require.Len(t, txs, 0) }) @@ -64,11 +65,11 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) blockNum := int64(100) lggr := logger.Test(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) marketGasPrice := assets.GWei(15) fee := gas.EvmFee{Legacy: marketGasPrice} @@ -109,10 +110,10 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { _, config := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) lggr := logger.Test(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) @@ -162,7 +163,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) lggr := logger.Test(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) @@ -170,7 +171,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { marketGasPrice := tenGwei fee := gas.EvmFee{Legacy: marketGasPrice} feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) autoPurgeCfg := testAutoPurgeConfig{ @@ -261,16 +262,16 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) lggr := logger.Test(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) autoPurgeCfg := testAutoPurgeConfig{ enabled: true, } blockNum := int64(100) - stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, commonconfig.ChainZkEvm, assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) + stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, chaintype.ChainZkEvm, assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) t.Run("returns empty list if no stuck transactions identified", func(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, blockNum, tenGwei) @@ -323,11 +324,11 @@ func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ctx := testutils.Context(t) + ctx := tests.Context(t) lggr := logger.Test(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) blockNum := int64(100) t.Run("returns stuck tx identified using the custom scroll API", func(t *testing.T) { @@ -353,7 +354,7 @@ func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) { enabled: true, detectionApiUrl: testUrl, } - stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, commonconfig.ChainScroll, assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) + stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, chaintype.ChainScroll, assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress1, fromAddress2}, blockNum) require.NoError(t, err) @@ -363,7 +364,7 @@ func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) { } func mustInsertUnconfirmedTxWithBroadcastAttempts(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, numAttempts uint32, latestBroadcastBlockNum int64, latestGasPrice *assets.Wei) txmgr.Tx { - ctx := testutils.Context(t) + ctx := tests.Context(t) etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) // Insert attempts from oldest to newest for i := int64(numAttempts - 1); i >= 0; i-- { @@ -390,10 +391,10 @@ func mustInsertFatalErrorTxWithError(t *testing.T, txStore txmgr.TestEvmTxStore, n := types.Nonce(nonce) etx.Sequence = &n etx.ChainID = testutils.FixtureChainID - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) + require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - ctx := testutils.Context(t) + ctx := tests.Context(t) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.IsPurgeAttempt = true require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -410,7 +411,7 @@ func mustInsertFatalErrorTxWithError(t *testing.T, txStore txmgr.TestEvmTxStore, func mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address) txmgr.Tx { etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - ctx := testutils.Context(t) + ctx := tests.Context(t) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.IsPurgeAttempt = true diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index ea19e056431..3b3584a988b 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -7,9 +7,9 @@ import ( "github.com/ethereum/go-ethereum/common" - commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/config" ) @@ -63,7 +63,7 @@ func (e *TestEvmConfig) NonceAutoSync() bool { return true } func (e *TestEvmConfig) FinalityDepth() uint32 { return 42 } -func (e *TestEvmConfig) ChainType() commonconfig.ChainType { return "" } +func (e *TestEvmConfig) ChainType() chaintype.ChainType { return "" } type TestGasEstimatorConfig struct { bumpThreshold uint64 @@ -151,12 +151,12 @@ func (c *MockConfig) EVM() evmconfig.EVM { return c.EvmConfig } -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 (c *MockConfig) NonceAutoSync() bool { return true } +func (c *MockConfig) ChainType() chaintype.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: utils.DefaultQueryTimeout} diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go index a0503253591..904a10d48c3 100644 --- a/core/chains/evm/txmgr/tracker_test.go +++ b/core/chains/evm/txmgr/tracker_test.go @@ -5,17 +5,18 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" ) const waitTime = 5 * time.Millisecond @@ -29,7 +30,7 @@ func newTestEvmTrackerSetup(t *testing.T) (*txmgr.Tracker, txmgr.TestEvmTxStore, _, addr1 := cltest.MustInsertRandomKey(t, ethKeyStore, *ubig.NewI(chainID.Int64())) _, addr2 := cltest.MustInsertRandomKey(t, ethKeyStore, *ubig.NewI(chainID.Int64())) enabledAddresses = append(enabledAddresses, addr1, addr2) - lggr := logger.TestLogger(t) + lggr := logger.Test(t) return txmgr.NewEvmTracker(txStore, ethKeyStore, chainID, lggr), txStore, ethKeyStore, enabledAddresses } @@ -46,7 +47,7 @@ func TestEvmTracker_Initialization(t *testing.T) { t.Parallel() tracker, _, _, _ := newTestEvmTrackerSetup(t) - ctx := testutils.Context(t) + ctx := tests.Context(t) require.NoError(t, tracker.Start(ctx)) require.True(t, tracker.IsStarted()) @@ -59,10 +60,10 @@ func TestEvmTracker_Initialization(t *testing.T) { func TestEvmTracker_AddressTracking(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("track abandoned addresses", func(t *testing.T) { - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) tracker, txStore, _, _ := newTestEvmTrackerSetup(t) inProgressAddr := cltest.MustGenerateRandomKey(t).Address unstartedAddr := cltest.MustGenerateRandomKey(t).Address @@ -119,7 +120,7 @@ func TestEvmTracker_AddressTracking(t *testing.T) { func TestEvmTracker_ExceedingTTL(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("exceeding ttl", func(t *testing.T) { tracker, txStore, _, _ := newTestEvmTrackerSetup(t) diff --git a/core/chains/evm/txmgr/transmitchecker_test.go b/core/chains/evm/txmgr/transmitchecker_test.go index 2fce9cf7aac..af41bbfdaa6 100644 --- a/core/chains/evm/txmgr/transmitchecker_test.go +++ b/core/chains/evm/txmgr/transmitchecker_test.go @@ -14,27 +14,24 @@ import ( "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" "github.com/stretchr/testify/mock" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" + txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" v1 "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/evmtest" ) func TestFactory(t *testing.T) { - client := cltest.NewEthMocksWithDefaultChain(t) + client := testutils.NewEthClientMockWithDefaultChain(t) factory := &txmgr.CheckerFactory{Client: client} t.Run("no checker", func(t *testing.T) { @@ -105,9 +102,9 @@ func TestFactory(t *testing.T) { } func TestTransmitCheckers(t *testing.T) { - client := evmtest.NewEthClientMockWithDefaultChain(t) + client := testutils.NewEthClientMockWithDefaultChain(t) log := logger.Sugared(logger.Test(t)) - ctx := testutils.Context(t) + ctx := tests.Context(t) t.Run("no checker", func(t *testing.T) { checker := txmgr.NoChecker diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 9570f67efe6..e4aa727b22a 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" @@ -36,12 +37,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "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" @@ -96,12 +97,12 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) keyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) 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) + _, err = txm.SendNativeToken(tests.Context(t), big.NewInt(0), from, to, *value, 21000) require.Error(t, err) require.EqualError(t, err, "cannot send native token to zero address") } @@ -120,7 +121,7 @@ func TestTxm_CreateTransaction(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth()) @@ -132,7 +133,7 @@ func TestTxm_CreateTransaction(t *testing.T) { strategy.On("Subject").Return(uuid.NullUUID{UUID: subject, Valid: true}) strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(nil, nil) evmConfig.MaxQueued = uint64(1) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -168,7 +169,7 @@ func TestTxm_CreateTransaction(t *testing.T) { t.Run("with queue at capacity does not insert eth_tx", func(t *testing.T) { evmConfig.MaxQueued = uint64(1) - _, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + _, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: testutils.NewAddress(), EncodedPayload: []byte{1, 2, 3}, @@ -183,7 +184,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) id := uuid.New() - tx1, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + tx1, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: testutils.NewAddress(), EncodedPayload: []byte{1, 2, 3}, @@ -193,7 +194,7 @@ func TestTxm_CreateTransaction(t *testing.T) { }) assert.NoError(t, err) - tx2, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + tx2, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: testutils.NewAddress(), EncodedPayload: []byte{1, 2, 3}, @@ -208,7 +209,7 @@ func TestTxm_CreateTransaction(t *testing.T) { t.Run("returns error if eth key state is missing or doesn't match chain ID", func(t *testing.T) { rndAddr := testutils.NewAddress() - _, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + _, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: rndAddr, ToAddress: testutils.NewAddress(), EncodedPayload: []byte{1, 2, 3}, @@ -220,7 +221,7 @@ func TestTxm_CreateTransaction(t *testing.T) { _, otherAddress := cltest.MustInsertRandomKey(t, kst.Eth(), *ubig.NewI(1337)) - _, err = txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + _, err = txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: otherAddress, ToAddress: testutils.NewAddress(), EncodedPayload: []byte{1, 2, 3}, @@ -238,7 +239,7 @@ func TestTxm_CreateTransaction(t *testing.T) { CheckerType: txmgr.TransmitCheckerTypeSimulate, } evmConfig.MaxQueued = uint64(1) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -281,7 +282,7 @@ func TestTxm_CreateTransaction(t *testing.T) { CheckerType: txmgr.TransmitCheckerTypeVRFV2, VRFCoordinatorAddress: testutils.NewAddressPtr(), } - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -313,11 +314,11 @@ func TestTxm_CreateTransaction(t *testing.T) { // Create mock forwarder, mock authorizedsenders call. form := forwarders.NewORM(db) fwdrAddr := testutils.NewAddress() - fwdr, err := form.CreateForwarder(testutils.Context(t), fwdrAddr, ubig.Big(cltest.FixtureChainID)) + fwdr, err := form.CreateForwarder(tests.Context(t), fwdrAddr, ubig.Big(cltest.FixtureChainID)) require.NoError(t, err) require.Equal(t, fwdr.Address, fwdrAddr) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: fromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -341,7 +342,7 @@ func TestTxm_CreateTransaction(t *testing.T) { evmConfig.MaxQueued = uint64(3) id := uuid.New() idempotencyKey := "1" - _, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + _, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ IdempotencyKey: &idempotencyKey, FromAddress: fromAddress, ToAddress: testutils.NewAddress(), @@ -357,7 +358,7 @@ func TestTxm_CreateTransaction(t *testing.T) { evmConfig.MaxQueued = uint64(3) id := uuid.New() idempotencyKey := "2" - tx1, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + tx1, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ IdempotencyKey: &idempotencyKey, FromAddress: fromAddress, ToAddress: testutils.NewAddress(), @@ -368,7 +369,7 @@ func TestTxm_CreateTransaction(t *testing.T) { }) assert.NoError(t, err) - tx2, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + tx2, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ IdempotencyKey: &idempotencyKey, FromAddress: fromAddress, ToAddress: testutils.NewAddress(), @@ -402,7 +403,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore) require.NoError(t, err) @@ -416,7 +417,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { strategy.On("Subject").Return(uuid.NullUUID{}) strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(nil, nil) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: evmFromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -440,7 +441,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { strategy.On("Subject").Return(uuid.NullUUID{}) strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(nil, nil) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: evmFromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -462,7 +463,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(nil, nil) evmConfig.MaxQueued = uint64(1) - etx, err := txm.CreateTransaction(testutils.Context(t), txmgr.TxRequest{ + etx, err := txm.CreateTransaction(tests.Context(t), txmgr.TxRequest{ FromAddress: evmFromAddress, ToAddress: toAddress, EncodedPayload: payload, @@ -478,7 +479,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { func TestTxm_Lifecycle(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) kst := ksmocks.NewEth(t) config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) @@ -500,13 +501,13 @@ func TestTxm_Lifecycle(t *testing.T) { head := cltest.Head(42) // It should not hang or panic - txm.OnNewLongestChain(testutils.Context(t), head) + txm.OnNewLongestChain(tests.Context(t), head) evmConfig.BumpThreshold = uint64(1) - require.NoError(t, txm.Start(testutils.Context(t))) + require.NoError(t, txm.Start(tests.Context(t))) - ctx, cancel := context.WithTimeout(testutils.Context(t), 5*time.Second) + ctx, cancel := context.WithTimeout(tests.Context(t), 5*time.Second) t.Cleanup(cancel) txm.OnNewLongestChain(ctx, head) require.NoError(t, ctx.Err()) @@ -543,7 +544,7 @@ func TestTxm_Reset(t *testing.T) { cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr2) } - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil) ethClient.On("BatchCallContextAll", mock.Anything, mock.Anything).Return(nil).Maybe() ethClient.On("PendingNonceAt", mock.Anything, addr).Return(uint64(128), nil).Maybe() @@ -615,7 +616,7 @@ func newEthReceipt(blockNumber int64, blockHash common.Hash, txHash common.Hash, func mustInsertEthReceipt(t *testing.T, txStore txmgr.TestEvmTxStore, blockNumber int64, blockHash common.Hash, txHash common.Hash) txmgr.Receipt { r := newEthReceipt(blockNumber, blockHash, txHash, 0x1) - id, err := txStore.InsertReceipt(testutils.Context(t), &r.Receipt) + id, err := txStore.InsertReceipt(tests.Context(t), &r.Receipt) require.NoError(t, err) r.ID = id return r @@ -623,7 +624,7 @@ func mustInsertEthReceipt(t *testing.T, txStore txmgr.TestEvmTxStore, blockNumbe func mustInsertRevertedEthReceipt(t *testing.T, txStore txmgr.TestEvmTxStore, blockNumber int64, blockHash common.Hash, txHash common.Hash) txmgr.Receipt { r := newEthReceipt(blockNumber, blockHash, txHash, 0x0) - id, err := txStore.InsertReceipt(testutils.Context(t), &r.Receipt) + id, err := txStore.InsertReceipt(tests.Context(t), &r.Receipt) require.NoError(t, err) r.ID = id return r @@ -644,7 +645,7 @@ func mustInsertConfirmedEthTxBySaveFetchedReceipts(t *testing.T, txStore txmgr.T BlockNumber: big.NewInt(nonce), TransactionIndex: uint(1), } - err := txStore.SaveFetchedReceipts(testutils.Context(t), []*evmtypes.Receipt{&receipt}, txmgrcommon.TxConfirmed, nil, &chainID) + err := txStore.SaveFetchedReceipts(tests.Context(t), []*evmtypes.Receipt{&receipt}, txmgrcommon.TxConfirmed, nil, &chainID) require.NoError(t, err) return etx } @@ -654,14 +655,14 @@ func mustInsertFatalErrorEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, fromA etx.Error = null.StringFrom("something exploded") etx.State = txmgrcommon.TxFatalError - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) + require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) return etx } func mustInsertUnconfirmedEthTxWithAttemptState(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, txAttemptState txmgrtypes.TxAttemptState, opts ...interface{}) txmgr.Tx { etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - ctx := testutils.Context(t) + ctx := tests.Context(t) tx := cltest.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) @@ -679,7 +680,7 @@ func mustInsertUnconfirmedEthTxWithAttemptState(t *testing.T, txStore txmgr.Test func mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) attempt := cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) - ctx := testutils.Context(t) + ctx := tests.Context(t) addr := testutils.NewAddress() dtx := types.DynamicFeeTx{ @@ -708,7 +709,7 @@ func mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t *testing.T, txSt func mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address) txmgr.Tx { timeNow := time.Now() etx := cltest.NewEthTx(fromAddress) - ctx := testutils.Context(t) + ctx := tests.Context(t) etx.BroadcastAt = &timeNow etx.InitialBroadcastAt = &timeNow @@ -735,7 +736,7 @@ func mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, broadcastBeforeBlockNum int64, broadcastAt time.Time, fromAddress common.Address) txmgr.Tx { etx := cltest.NewEthTx(fromAddress) - ctx := testutils.Context(t) + ctx := tests.Context(t) etx.BroadcastAt = &broadcastAt etx.InitialBroadcastAt = &broadcastAt @@ -753,7 +754,7 @@ func mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( func mustInsertInProgressEthTxWithAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce evmtypes.Nonce, fromAddress common.Address) txmgr.Tx { etx := cltest.NewEthTx(fromAddress) - ctx := testutils.Context(t) + ctx := tests.Context(t) etx.Sequence = &nonce etx.State = txmgrcommon.TxInProgress @@ -810,10 +811,10 @@ func mustCreateUnstartedTx(t testing.TB, txStore txmgr.EvmTxStore, fromAddress c } func mustCreateUnstartedTxFromEvmTxRequest(t testing.TB, txStore txmgr.EvmTxStore, txRequest txmgr.TxRequest, chainID *big.Int) (tx txmgr.Tx) { - tx, err := txStore.CreateTransaction(testutils.Context(t), txRequest, chainID) + tx, err := txStore.CreateTransaction(tests.Context(t), txRequest, chainID) require.NoError(t, err) - _, err = txRequest.Strategy.PruneQueue(testutils.Context(t), txStore) + _, err = txRequest.Strategy.PruneQueue(tests.Context(t), txStore) require.NoError(t, err) return tx diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 24ea295a4f5..b38cd2c4508 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -212,7 +212,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { client = evmclient.NewNullClient(chainID, l) } else if opts.GenEthClient == nil { - client = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes) + client = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes, cfg.EVM().ChainType()) } else { client = opts.GenEthClient(chainID) } diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go index 2e2451ab57a..8f46497cb5f 100644 --- a/core/config/docs/docs_test.go +++ b/core/config/docs/docs_test.go @@ -15,8 +15,8 @@ import ( stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink-common/pkg/config" - 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/chaintype" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/config/docs" @@ -47,7 +47,7 @@ func TestDoc(t *testing.T) { fallbackDefaults := evmcfg.Defaults(nil) docDefaults := defaults.EVM[0].Chain - require.Equal(t, commonconfig.ChainType(""), docDefaults.ChainType.ChainType()) + require.Equal(t, chaintype.ChainType(""), docDefaults.ChainType.ChainType()) docDefaults.ChainType = nil // clean up KeySpecific as a special case diff --git a/core/gethwrappers/keystone/generated/forwarder/forwarder.go b/core/gethwrappers/keystone/generated/forwarder/forwarder.go index b4f209f1c32..eeeb322d96e 100644 --- a/core/gethwrappers/keystone/generated/forwarder/forwarder.go +++ b/core/gethwrappers/keystone/generated/forwarder/forwarder.go @@ -31,15 +31,15 @@ var ( ) var KeystoneForwarderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyProcessed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611786806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146101cb578063ee59d26c146101e9578063ef6e17a0146101fc578063f2fde38b1461020f57600080fd5b8063112895651461008d578063181f5a77146100a257806379ba5097146100ea5780638864b864146100f2575b600080fd5b6100a061009b3660046112e6565b610222565b005b604080518082018252601781527f4b657973746f6e65466f7277617264657220312e302e30000000000000000000602082015290516100e191906113f5565b60405180910390f35b6100a0610983565b6101a661010036600461140f565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526003909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e1565b60005473ffffffffffffffffffffffffffffffffffffffff166101a6565b6100a06101f7366004611488565b610a80565b6100a061020a366004611506565b610de5565b6100a061021d366004611539565b610ee5565b60015474010000000000000000000000000000000000000000900460ff1615610277576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055606d8510156102f1576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008060006103388b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ef992505050565b6040805163ffffffff808616602083015284169181019190915293985096509093509150606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600081815260029093529082205490945060ff16908190036103f8576040517f16c0791600000000000000000000000000000000000000000000000000000000815263ffffffff8085166004830152831660248201526044015b60405180910390fd5b86610404826001611583565b60ff161461045657610417816001611583565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018890526044016103ef565b50506040805160608d901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018790527fffff0000000000000000000000000000000000000000000000000000000000008616605483015282516036818403018152605690920190925280519101206000915060008181526003602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1615610538576040517f1a20d3e6000000000000000000000000000000000000000000000000000000008152600481018290526024016103ef565b60008a8a60405161054a9291906115a2565b604051908190038120610563918b908b906020016115b2565b604051602081830303815290604052805190602001209050610583611173565b6000805b888110156107ea5760008060006105f58d8d868181106105a9576105a96115cc565b90506020028101906105bb91906115fb565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f9b92505050565b91945092509050600060018861060c84601b611583565b6040805160008152602081018083529390935260ff90911690820152606081018690526080810185905260a0016020604051602081039080840390855afa15801561065b573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015160008d81526002602081815284832073ffffffffffffffffffffffffffffffffffffffff851684529091019052918220549850925060ff88169003905061070f576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b61071a600187611660565b955060008760ff8816601f8110610733576107336115cc565b602002015173ffffffffffffffffffffffffffffffffffffffff161461079d576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b80878760ff16601f81106107b3576107b36115cc565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152506107e392508391506116799050565b9050610587565b5050505060008b73ffffffffffffffffffffffffffffffffffffffff1663805f21328c8c602d90606d92610820939291906116b1565b8e8e606d908092610833939291906116b1565b6040518563ffffffff1660e01b81526004016108529493929190611724565b600060405180830381600087803b15801561086c57600080fd5b505af192505050801561087d575060015b15610886575060015b604080518082018252338152821515602080830191825260008681526003909152839020915182549151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9182161791909117909155905186918e16907fbe015fd2fd7c1a00158e111095c794ae7030eb413d2a0990e5b78d3114df1d499061094590851515815260200190565b60405180910390a35050600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103ef565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a88610ffb565b8260ff16600003610ac5576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f811115610b0a576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016103ef565b610b15836003611756565b60ff168111610b735780610b2a846003611756565b610b35906001611583565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016103ef565b6040805163ffffffff878116602080840191909152908716828401528251808303840181526060909201909252805191012060005b600082815260026020526040902060010154811015610c32576000828152600260205260408120600101805483908110610be457610be46115cc565b60009182526020808320909101548583526002808352604080852073ffffffffffffffffffffffffffffffffffffffff9093168552910190915281205550610c2b81611679565b9050610ba8565b506000818152600260205260409020610c4f906001018484611192565b5060005b82811015610d9f576000848483818110610c6f57610c6f6115cc565b9050602002016020810190610c849190611539565b600084815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205490915015610d08576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b610d13826001611583565b600084815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616808552868401835290842060ff959095169094559081526001938401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055610d9881611679565b9050610c53565b50600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff949094169390931790925550505050565b610ded610ffb565b6040805163ffffffff848116602080840191909152908416828401528251808303840181526060909201909252805191012060005b600082815260026020526040902060010154811015610eac576000828152600260205260408120600101805483908110610e5e57610e5e6115cc565b60009182526020808320909101548583526002808352604080852073ffffffffffffffffffffffffffffffffffffffff9093168552910190915281205550610ea581611679565b9050610e22565b50600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b610eed610ffb565b610ef68161107e565b50565b60008060008084600081518110610f1257610f126115cc565b60209101015160f81c600114610f735784600081518110610f3557610f356115cc565b01602001516040517f7207be2000000000000000000000000000000000000000000000000000000000815260f89190911c60048201526024016103ef565b50505050602181015160458201516049830151608b90930151919360e091821c9390911c9190565b60008060006041845114610fdd57836040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016103ef91906113f5565b50505060208101516040820151606090920151909260009190911a90565b60005473ffffffffffffffffffffffffffffffffffffffff16331461107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ef565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ef565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b604051806103e00160405280601f906020820280368337509192915050565b82805482825590600052602060002090810192821561120a579160200282015b8281111561120a5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906111b2565b5061121692915061121a565b5090565b5b80821115611216576000815560010161121b565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125357600080fd5b919050565b60008083601f84011261126a57600080fd5b50813567ffffffffffffffff81111561128257600080fd5b60208301915083602082850101111561129a57600080fd5b9250929050565b60008083601f8401126112b357600080fd5b50813567ffffffffffffffff8111156112cb57600080fd5b6020830191508360208260051b850101111561129a57600080fd5b60008060008060008060006080888a03121561130157600080fd5b61130a8861122f565b9650602088013567ffffffffffffffff8082111561132757600080fd5b6113338b838c01611258565b909850965060408a013591508082111561134c57600080fd5b6113588b838c01611258565b909650945060608a013591508082111561137157600080fd5b5061137e8a828b016112a1565b989b979a50959850939692959293505050565b6000815180845260005b818110156113b75760208185018101518683018201520161139b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006114086020830184611391565b9392505050565b60008060006060848603121561142457600080fd5b61142d8461122f565b92506020840135915060408401357fffff0000000000000000000000000000000000000000000000000000000000008116811461146957600080fd5b809150509250925092565b803563ffffffff8116811461125357600080fd5b6000806000806000608086880312156114a057600080fd5b6114a986611474565b94506114b760208701611474565b9350604086013560ff811681146114cd57600080fd5b9250606086013567ffffffffffffffff8111156114e957600080fd5b6114f5888289016112a1565b969995985093965092949392505050565b6000806040838503121561151957600080fd5b61152283611474565b915061153060208401611474565b90509250929050565b60006020828403121561154b57600080fd5b6114088261122f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216019081111561159c5761159c611554565b92915050565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261163057600080fd5b83018035915067ffffffffffffffff82111561164b57600080fd5b60200191503681900382131561129a57600080fd5b60ff828116828216039081111561159c5761159c611554565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116aa576116aa611554565b5060010190565b600080858511156116c157600080fd5b838611156116ce57600080fd5b5050820193919092039150565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006117386040830186886116db565b828103602084015261174b8185876116db565b979650505050505050565b60ff818116838216029081169081811461177257611772611554565b509291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"configId\",\"type\":\"uint64\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionState\",\"outputs\":[{\"internalType\":\"enumIRouter.TransmissionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b5060405162001b4a38038062001b4a833981016040819052620000349162000193565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e8565b5050600280546001600160a01b0319166001600160a01b03939093169290921790915550620001c5565b336001600160a01b03821603620001425760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001a657600080fd5b81516001600160a01b0381168114620001be57600080fd5b9392505050565b61197580620001d56000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638864b86411610081578063ee59d26c1161005b578063ee59d26c14610270578063ef6e17a014610283578063f2fde38b1461029657600080fd5b80638864b864146101fc5780638da5cb5b14610234578063b0f479a11461025257600080fd5b8063354bdd66116100b2578063354bdd661461013557806343c16467146101d457806379ba5097146101f457600080fd5b806311289565146100ce578063181f5a77146100e3575b600080fd5b6100e16100dc3660046112ec565b6102a9565b005b61011f6040518060400160405280601781526020017f4b657973746f6e65466f7277617264657220312e302e3000000000000000000081525081565b60405161012c9190611399565b60405180910390f35b6101c6610143366004611405565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b60405190815260200161012c565b6101e76101e2366004611405565b610891565b60405161012c919061146c565b6100e16109a6565b61020f61020a366004611405565b610aa3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161012c565b60005473ffffffffffffffffffffffffffffffffffffffff1661020f565b60025473ffffffffffffffffffffffffffffffffffffffff1661020f565b6100e161027e3660046114c6565b610bb0565b6100e1610291366004611544565b610f39565b6100e16102a4366004611577565b610fd9565b606d8510156102e4576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061032889898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610fed92505050565b67ffffffffffffffff8216600090815260036020526040812080549497509195509193509160ff169081900361039b576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856103a78260016115ca565b60ff16146103f9576103ba8160016115ca565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101879052604401610392565b60008b8b60405161040b9291906115e9565b604051908190038120610424918c908c906020016115f9565b604051602081830303815290604052805190602001209050610444611180565b60005b888110156106cd573660008b8b8481811061046457610464611613565b90506020028101906104769190611642565b9092509050604181146104b95781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016103929291906116f0565b6000600186848460408181106104d1576104d1611613565b6104e392013560f81c9050601b6115ca565b6104f1602060008789611704565b6104fa9161172e565b61050860406020888a611704565b6105119161172e565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa15801561055f573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c01602052918220549093509150819003610605576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610392565b600086826020811061061957610619611613565b602002015173ffffffffffffffffffffffffffffffffffffffff1614610683576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610392565b8186826020811061069657610696611613565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152506106c6925083915061176a9050565b9050610447565b50506002546000945073ffffffffffffffffffffffffffffffffffffffff16925063233fd52d915061078090508c86866040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b338d8d8d602d90606d9261079693929190611704565b8f8f606d9080926107a993929190611704565b6040518863ffffffff1660e01b81526004016107cb97969594939291906117a2565b6020604051808303816000875af11580156107ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080e9190611803565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b58460405161087d911515815260200190565b60405180910390a450505050505050505050565b600254604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b16602080830191909152603482018690527fffff0000000000000000000000000000000000000000000000000000000000008516605483015282518083036036018152605683019384905280519101207f516db40800000000000000000000000000000000000000000000000000000000909252605a81019190915260009173ffffffffffffffffffffffffffffffffffffffff169063516db40890607a01602060405180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190611825565b949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610392565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600254604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b16602080830191909152603482018690527fffff0000000000000000000000000000000000000000000000000000000000008516605483015282518083036036018152605683019384905280519101207fe6b7145800000000000000000000000000000000000000000000000000000000909252605a81019190915260009173ffffffffffffffffffffffffffffffffffffffff169063e6b7145890607a01602060405180830381865afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190611846565b610bb8611008565b8260ff16600003610bf5576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f811115610c3a576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f6024820152604401610392565b610c45836003611863565b60ff168111610ca35780610c5a846003611863565b610c659060016115ca565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff166024820152604401610392565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff8216600090815260036020526040902060010154811015610d595767ffffffffffffffff821660009081526003602052604081206001810180546002909201929184908110610d1757610d17611613565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055610d528161176a565b9050610cbd565b5060005b82811015610e7b576000848483818110610d7957610d79611613565b9050602002016020810190610d8e9190611577565b67ffffffffffffffff8416600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845260020190915290205490915015610e1e576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610392565b610e29826001611886565b67ffffffffffffffff8416600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff9095168352600290940190529190912055610e748161176a565b9050610d5d565b5067ffffffffffffffff81166000908152600360205260409020610ea390600101848461119f565b5067ffffffffffffffff81166000908152600360205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a45590610f2990889088908890611899565b60405180910390a3505050505050565b610f41611008565b63ffffffff818116602084811b67ffffffff00000000168217600090815260038252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a45591604051610fcd929190611901565b60405180910390a35050565b610fe1611008565b610fea8161108b565b50565b60218101516045820151608b90920151909260c09290921c91565b60005473ffffffffffffffffffffffffffffffffffffffff163314611089576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610392565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361110a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610392565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611217579160200282015b828111156112175781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906111bf565b50611223929150611227565b5090565b5b808211156112235760008155600101611228565b73ffffffffffffffffffffffffffffffffffffffff81168114610fea57600080fd5b60008083601f84011261127057600080fd5b50813567ffffffffffffffff81111561128857600080fd5b6020830191508360208285010111156112a057600080fd5b9250929050565b60008083601f8401126112b957600080fd5b50813567ffffffffffffffff8111156112d157600080fd5b6020830191508360208260051b85010111156112a057600080fd5b60008060008060008060006080888a03121561130757600080fd5b87356113128161123c565b9650602088013567ffffffffffffffff8082111561132f57600080fd5b61133b8b838c0161125e565b909850965060408a013591508082111561135457600080fd5b6113608b838c0161125e565b909650945060608a013591508082111561137957600080fd5b506113868a828b016112a7565b989b979a50959850939692959293505050565b600060208083528351808285015260005b818110156113c6578581018301518582016040015282016113aa565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008060006060848603121561141a57600080fd5b83356114258161123c565b92506020840135915060408401357fffff0000000000000000000000000000000000000000000000000000000000008116811461146157600080fd5b809150509250925092565b60208101600383106114a7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b803563ffffffff811681146114c157600080fd5b919050565b6000806000806000608086880312156114de57600080fd5b6114e7866114ad565b94506114f5602087016114ad565b9350604086013560ff8116811461150b57600080fd5b9250606086013567ffffffffffffffff81111561152757600080fd5b611533888289016112a7565b969995985093965092949392505050565b6000806040838503121561155757600080fd5b611560836114ad565b915061156e602084016114ad565b90509250929050565b60006020828403121561158957600080fd5b81356115948161123c565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821601908111156115e3576115e361159b565b92915050565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261167757600080fd5b83018035915067ffffffffffffffff82111561169257600080fd5b6020019150368190038213156112a057600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60208152600061099e6020830184866116a7565b6000808585111561171457600080fd5b8386111561172157600080fd5b5050820193919092039150565b803560208310156115e3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361179b5761179b61159b565b5060010190565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a060608301526117e260a0830186886116a7565b82810360808401526117f58185876116a7565b9a9950505050505050505050565b60006020828403121561181557600080fd5b8151801515811461159457600080fd5b60006020828403121561183757600080fd5b81516003811061159457600080fd5b60006020828403121561185857600080fd5b81516115948161123c565b60ff818116838216029081169081811461187f5761187f61159b565b5092915050565b808201808211156115e3576115e361159b565b60ff8416815260406020808301829052908201839052600090849060608401835b868110156118f55783356118cd8161123c565b73ffffffffffffffffffffffffffffffffffffffff16825292820192908201906001016118ba565b50979650505050505050565b60006040820160ff851683526020604081850152818551808452606086019150828701935060005b8181101561195b57845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611929565b509097965050505050505056fea164736f6c6343000813000a", } var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI var KeystoneForwarderBin = KeystoneForwarderMetaData.Bin -func DeployKeystoneForwarder(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneForwarder, error) { +func DeployKeystoneForwarder(auth *bind.TransactOpts, backend bind.ContractBackend, router common.Address) (common.Address, *types.Transaction, *KeystoneForwarder, error) { parsed, err := KeystoneForwarderMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -48,7 +48,7 @@ func DeployKeystoneForwarder(auth *bind.TransactOpts, backend bind.ContractBacke return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KeystoneForwarderBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KeystoneForwarderBin), backend, router) if err != nil { return common.Address{}, nil, nil, err } @@ -171,6 +171,72 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transact(opts *bind.Tr return _KeystoneForwarder.Contract.contract.Transact(opts, method, params...) } +func (_KeystoneForwarder *KeystoneForwarderCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getRouter") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetRouter() (common.Address, error) { + return _KeystoneForwarder.Contract.GetRouter(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetRouter() (common.Address, error) { + return _KeystoneForwarder.Contract.GetRouter(&_KeystoneForwarder.CallOpts) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionId", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionState(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionState", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionState(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + return _KeystoneForwarder.Contract.GetTransmissionState(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionState(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + return _KeystoneForwarder.Contract.GetTransmissionState(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { var out []interface{} err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmitter", receiver, workflowExecutionId, reportId) @@ -261,16 +327,16 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorSession) ClearConfig(donId return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) } -func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "report", receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "report", receiver, rawReport, reportContext, signatures) } -func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) } -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) } func (_KeystoneForwarder *KeystoneForwarderTransactor) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { @@ -297,6 +363,144 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorSession) TransferOwnership( return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) } +type KeystoneForwarderConfigSetIterator struct { + Event *KeystoneForwarderConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderConfigSet) + 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(KeystoneForwarderConfigSet) + 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 *KeystoneForwarderConfigSetIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderConfigSet struct { + DonId uint32 + ConfigVersion uint32 + F uint8 + Signers []common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderConfigSetIterator{contract: _KeystoneForwarder.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) { + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type KeystoneForwarderOwnershipTransferRequestedIterator struct { Event *KeystoneForwarderOwnershipTransferRequested @@ -632,11 +836,12 @@ func (it *KeystoneForwarderReportProcessedIterator) Close() error { type KeystoneForwarderReportProcessed struct { Receiver common.Address WorkflowExecutionId [32]byte + ReportId [2]byte Result bool Raw types.Log } -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte) (*KeystoneForwarderReportProcessedIterator, error) { +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) { var receiverRule []interface{} for _, receiverItem := range receiver { @@ -646,15 +851,19 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts for _, workflowExecutionIdItem := range workflowExecutionId { workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule) + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) if err != nil { return nil, err } return &KeystoneForwarderReportProcessedIterator{contract: _KeystoneForwarder.contract, event: "ReportProcessed", logs: logs, sub: sub}, nil } -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte) (event.Subscription, error) { +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) { var receiverRule []interface{} for _, receiverItem := range receiver { @@ -664,8 +873,12 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts * for _, workflowExecutionIdItem := range workflowExecutionId { workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule) + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) if err != nil { return nil, err } @@ -708,6 +921,8 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseReportProcessed(log ty func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { + case _KeystoneForwarder.abi.Events["ConfigSet"].ID: + return _KeystoneForwarder.ParseConfigSet(log) case _KeystoneForwarder.abi.Events["OwnershipTransferRequested"].ID: return _KeystoneForwarder.ParseOwnershipTransferRequested(log) case _KeystoneForwarder.abi.Events["OwnershipTransferred"].ID: @@ -720,6 +935,10 @@ func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated. } } +func (KeystoneForwarderConfigSet) Topic() common.Hash { + return common.HexToHash("0x4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455") +} + func (KeystoneForwarderOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -729,7 +948,7 @@ func (KeystoneForwarderOwnershipTransferred) Topic() common.Hash { } func (KeystoneForwarderReportProcessed) Topic() common.Hash { - return common.HexToHash("0xbe015fd2fd7c1a00158e111095c794ae7030eb413d2a0990e5b78d3114df1d49") + return common.HexToHash("0x3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b5") } func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { @@ -737,6 +956,12 @@ func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { } type KeystoneForwarderInterface interface { + GetRouter(opts *bind.CallOpts) (common.Address, error) + + GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) + + GetTransmissionState(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) + GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -747,12 +972,18 @@ type KeystoneForwarderInterface interface { ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) - Report(opts *bind.TransactOpts, receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) + Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -765,9 +996,9 @@ type KeystoneForwarderInterface interface { ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) - FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte) (*KeystoneForwarderReportProcessedIterator, error) + FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) - WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte) (event.Subscription, error) + WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 786c44db8ab..f68d29f8009 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -46,7 +46,7 @@ type CapabilityRegistryCapabilityConfiguration struct { type CapabilityRegistryDONInfo struct { Id uint32 ConfigCount uint32 - F uint32 + F uint8 IsPublic bool AcceptsWorkflows bool NodeP2PIds [][32]byte @@ -66,8 +66,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"},{\"internalType\":\"uint32[]\",\"name\":\"\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b614db980620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635d83d967116100ee57806386fa4246116100975780639cb7c5f4116100715780639cb7c5f4146103ea578063ddbe4f821461040a578063e29581aa1461041f578063f2fde38b1461043557600080fd5b806386fa42461461039c5780638da5cb5b146103af57806395864d1f146103d757600080fd5b8063715f5295116100c8578063715f52951461036e57806373ac22b41461038157806379ba50971461039457600080fd5b80635d83d967146103335780635e65e3091461034657806366acaa331461035957600080fd5b806322bdbcbc1161015b5780632c01a1e8116101355780632c01a1e8146102cb578063398f3773146102de5780633f2a13c9146102f157806350c946fe1461031257600080fd5b806322bdbcbc146102785780632353740514610298578063275459f2146102b857600080fd5b8063193ec0061161018c578063193ec0061461023b5780631d05394c14610250578063214502431461026357600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613bd7565b610448565b6040519081526020015b60405180910390f35b6101ec6101e7366004613c3b565b61047c565b60405190151581526020016101d0565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101d09190613cc2565b61024e610249366004613d41565b610489565b005b61024e61025e366004613de6565b610553565b61026b61070f565b6040516101d09190613f50565b61028b610286366004613fd0565b610874565b6040516101d09190614028565b6102ab6102a6366004613fd0565b610961565b6040516101d0919061403b565b61024e6102c6366004613de6565b6109a5565b61024e6102d9366004613de6565b610a7c565b61024e6102ec366004613de6565b610c9f565b6103046102ff36600461404e565b610e67565b6040516101d0929190614078565b610325610320366004613c3b565b611053565b6040516101d09291906140df565b61024e610341366004613de6565b6110f8565b61024e610354366004613de6565b611246565b6103616116b8565b6040516101d09190614107565b61024e61037c366004613de6565b6118a3565b61024e61038f366004613de6565b61195e565b61024e611dcf565b61024e6103aa36600461417a565b611ecc565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b61024e6103e53660046141e6565b612212565b6103fd6103f8366004613c3b565b6122de565b6040516101d09190614357565b6104126124e3565b6040516101d0919061436a565b6104276127e1565b6040516101d09291906143dd565b61024e6104433660046144c0565b612959565b6000828260405160200161045d929190614078565b6040516020818303038152906040528051906020012090505b92915050565b600061047660058361296d565b610491612988565b600e805460009164010000000090910463ffffffff169060046104b38361450a565b82546101009290920a63ffffffff8181021990931691831602179091558181166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a0810183529283526001908301528715159082015285151560608201529084166080820152909150610549908990899089908990612a0b565b5050505050505050565b61055b612988565b60005b8181101561070a57600083838381811061057a5761057a61452d565b905060200201602081019061058f9190613fd0565b63ffffffff8082166000908152600d60209081526040808320805464010000000090049094168084526001850190925282209394509192905b6105d1826130bb565b811015610629576106188563ffffffff16600c60006105f985876130c590919063ffffffff16565b81526020019081526020016000206004016130d190919063ffffffff16565b506106228161455c565b90506105c8565b508254640100000000900463ffffffff16600003610680576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff851660048201526024015b60405180910390fd5b63ffffffff84166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffff00000000000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a150505050806107039061455c565b905061055e565b505050565b600e54606090640100000000900463ffffffff166000610730600183614594565b63ffffffff1667ffffffffffffffff81111561074e5761074e613a71565b6040519080825280602002602001820160405280156107d557816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161076c5790505b509050600060015b8363ffffffff168163ffffffff1610156108515763ffffffff8082166000908152600d6020526040902054161561084157610817816130dd565b8383815181106108295761082961452d565b60200260200101819052508161083e9061455c565b91505b61084a8161450a565b90506107dd565b5061085d600184614594565b63ffffffff16811461086d578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff16835260018101805491928401916108d8906145b1565b80601f0160208091040260200160405190810160405280929190818152602001828054610904906145b1565b80156109515780601f1061092657610100808354040283529160200191610951565b820191906000526020600020905b81548152906001019060200180831161093457829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c0810191909152610476826130dd565b6109ad612988565b60005b63ffffffff811682111561070a57600083838363ffffffff168181106109d8576109d861452d565b90506020020160208101906109ed9190613fd0565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610a386001830182613a04565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a250610a758161450a565b90506109b0565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c99576000848483818110610ab657610ab661452d565b602090810292909201356000818152600c90935260409092206001810154929350919050610b13576040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260048101839052602401610677565b6000610b21826004016130bb565b1115610b5c576040517f34a4a3f600000000000000000000000000000000000000000000000000000000815260048101839052602401610677565b83158015610b965750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610bcf576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610677565b6001810154610be0906007906130d1565b506002810154610bf2906009906130d1565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016815560018101829055600281018290559060048201818181610c478282613a3e565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610c7e91815260200190565b60405180910390a1505080610c929061455c565b9050610a9a565b50505050565b610ca7612988565b60005b8181101561070a576000838383818110610cc657610cc661452d565b9050602002810190610cd89190614604565b610ce190614642565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d32576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610dbe90826146fa565b5050600e8054909150600090610dd99063ffffffff1661450a565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610e4c9190613cc2565b60405180910390a3505080610e609061455c565b9050610caa565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610eb9906145b1565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee5906145b1565b8015610f325780601f10610f0757610100808354040283529160200191610f32565b820191906000526020600020905b815481529060010190602001808311610f1557829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611045905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610ffc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110429190810190614814565b90505b9093509150505b9250929050565b6040805160808101825260008082526020820181905291810191909152606080820152604080516080810182526000848152600c6020908152838220805463ffffffff8082168652600183015484870152600283015486880152640100000000909104168352600301905291822060608201906110cf906133b9565b90526000938452600c602052604090932054929364010000000090930463ffffffff1692915050565b611100612988565b60005b8181101561070a57600083838381811061111f5761111f61452d565b90506020020135905061113c81600361296d90919063ffffffff16565b611175576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610677565b6111806005826133c6565b6111b9576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610677565b6000818152600260205260408120906111d28282613a04565b6111e0600183016000613a04565b5060020180547fffffffffffffffffffff0000000000000000000000000000000000000000000016905560405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25061123f8161455c565b9050611103565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c995760008484838181106112805761128061452d565b90506020028101906112929190614882565b61129b906148b6565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549596509394919390928401916112f1906145b1565b80601f016020809104026020016040519081016040528092919081815260200182805461131d906145b1565b801561136a5780601f1061133f5761010080835404028352916020019161136a565b820191906000526020600020905b81548152906001019060200180831161134d57829003601f168201915b50505050508152505090508315801561139a5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113d3576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610677565b6040808301516000908152600c6020522060018101546114275782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161067791815260200190565b6020830151158061145757508260200151816001015414158015611457575060208301516114579060079061296d565b1561148e576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606083015180516000036114d057806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106779190614989565b8154640100000000900463ffffffff168260046114ec8361450a565b82546101009290920a63ffffffff8181021990931691831602179091558354640100000000900416905060005b82518110156115e45761154f8382815181106115375761153761452d565b6020026020010151600361296d90919063ffffffff16565b61158757826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106779190614989565b6115d383828151811061159c5761159c61452d565b60200260200101518560030160008563ffffffff1663ffffffff1681526020019081526020016000206133c690919063ffffffff16565b506115dd8161455c565b9050611519565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909116178355604085015160028401556001830154602086015181146116565761163b6007826130d1565b50602086015160018501819055611654906007906133c6565b505b85516040808801516020808a015183519283529082015263ffffffff909216917f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a2505050505050806116b19061455c565b9050611264565b600e5460609063ffffffff1660006116d1600183614594565b63ffffffff1667ffffffffffffffff8111156116ef576116ef613a71565b60405190808252806020026020018201604052801561173557816020015b60408051808201909152600081526060602082015281526020019060019003908161170d5790505b509050600060015b8363ffffffff168163ffffffff16101561188d5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff161561187d5763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff16835260018101805491928401916117d1906145b1565b80601f01602080910402602001604051908101604052809291908181526020018280546117fd906145b1565b801561184a5780601f1061181f5761010080835404028352916020019161184a565b820191906000526020600020905b81548152906001019060200180831161182d57829003601f168201915b5050505050815250508383815181106118655761186561452d565b60200260200101819052508161187a9061455c565b91505b6118868161450a565b905061173d565b50600e5461085d9060019063ffffffff16614594565b6118ab612988565b60005b8181101561070a5760008383838181106118ca576118ca61452d565b90506020028101906118dc919061499c565b6118e5906149df565b905060006118fb82600001518360200151610448565b90506119086003826133c6565b611941576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610677565b61194b81836133d2565b5050806119579061455c565b90506118ae565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c995760008484838181106119985761199861452d565b90506020028101906119aa9190614882565b6119b3906148b6565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611a09906145b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611a35906145b1565b8015611a825780601f10611a5757610100808354040283529160200191611a82565b820191906000526020600020905b815481529060010190602001808311611a6557829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611ae85781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610677565b83158015611b0d5750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611b46576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610677565b6040808301516000908152600c602052206001810154151580611b6b57506040830151155b15611baa5782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161067791815260200190565b60208301511580611bc757506020830151611bc79060079061296d565b15611bfe576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611c4057806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106779190614989565b81548290600490611c5e90640100000000900463ffffffff1661450a565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611d0557611ca78382815181106115375761153761452d565b611cdf57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106779190614989565b611cf483828151811061159c5761159c61452d565b50611cfe8161455c565b9050611c89565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff91821617845560408601516002850155602086015160018501819055611d5b91600791906133c616565b506040850151611d6d906009906133c6565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080611dc89061455c565b905061197c565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610677565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b828114611f0f576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610677565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561220a576000868683818110611f4757611f4761452d565b9050602002016020810190611f5c9190613fd0565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16611fcb576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610677565b6000868685818110611fdf57611fdf61452d565b9050602002810190611ff19190614604565b611ffa90614642565b805190915073ffffffffffffffffffffffffffffffffffffffff1661204b576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061208857503373ffffffffffffffffffffffffffffffffffffffff861614155b156120c1576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610677565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061213d57506020808201516040516120fa9201613cc2565b60405160208183030381529060405280519060200120826001016040516020016121249190614a85565b6040516020818303038152906040528051906020012014155b156121f657805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020810151600183019061219790826146fa565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516121ed9190613cc2565b60405180910390a35b505050806122039061455c565b9050611f2b565b505050505050565b61221a612988565b63ffffffff8089166000908152600d602052604081205464010000000090049091169081900361227e576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610677565b6122d3888888886040518060a001604052808f63ffffffff168152602001876122a69061450a565b97508763ffffffff1681526020018a1515815260200189151581526020018863ffffffff16815250612a0b565b505050505050505050565b61230e6040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b60008281526002602052604090819020815160a08101909252805482908290612336906145b1565b80601f0160208091040260200160405190810160405280929190818152602001828054612362906145b1565b80156123af5780601f10612384576101008083540402835291602001916123af565b820191906000526020600020905b81548152906001019060200180831161239257829003601f168201915b505050505081526020016001820180546123c8906145b1565b80601f01602080910402602001604051908101604052809291908181526020018280546123f4906145b1565b80156124415780601f1061241657610100808354040283529160200191612441565b820191906000526020600020905b81548152906001019060200180831161242457829003601f168201915b5050509183525050600282015460209091019060ff1660038111156124685761246861429b565b60038111156124795761247961429b565b81526020016002820160019054906101000a900460ff1660018111156124a1576124a161429b565b60018111156124b2576124b261429b565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b606060006124f160036133b9565b905060006124ff60056130bb565b825161250b9190614b2e565b67ffffffffffffffff81111561252357612523613a71565b60405190808252806020026020018201604052801561258457816020015b6125716040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b8152602001906001900390816125415790505b5090506000805b83518110156127d85760008482815181106125a8576125a861452d565b602002602001015190506125c681600561296d90919063ffffffff16565b6127c75760008181526002602052604090819020815160a081019092528054829082906125f2906145b1565b80601f016020809104026020016040519081016040528092919081815260200182805461261e906145b1565b801561266b5780601f106126405761010080835404028352916020019161266b565b820191906000526020600020905b81548152906001019060200180831161264e57829003601f168201915b50505050508152602001600182018054612684906145b1565b80601f01602080910402602001604051908101604052809291908181526020018280546126b0906145b1565b80156126fd5780601f106126d2576101008083540402835291602001916126fd565b820191906000526020600020905b8154815290600101906020018083116126e057829003601f168201915b5050509183525050600282015460209091019060ff1660038111156127245761272461429b565b60038111156127355761273561429b565b81526020016002820160019054906101000a900460ff16600181111561275d5761275d61429b565b600181111561276e5761276e61429b565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff1660209091015284518590859081106127ad576127ad61452d565b602002602001018190525082806127c39061455c565b9350505b506127d18161455c565b905061258b565b50909392505050565b60608060006127f060096133b9565b90506000815167ffffffffffffffff81111561280e5761280e613a71565b60405190808252806020026020018201604052801561287d57816020015b60408051608081018252600080825260208083018290529282015260608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161282c5790505b5090506000825167ffffffffffffffff81111561289c5761289c613a71565b6040519080825280602002602001820160405280156128c5578160200160208202803683370190505b50905060005b835181101561294e576128f68482815181106128e9576128e961452d565b6020026020010151611053565b8483815181106129085761290861452d565b602002602001018484815181106129215761292161452d565b602002602001018263ffffffff1663ffffffff168152508290525050806129479061455c565b90506128cb565b509094909350915050565b612961612988565b61296a81613666565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610677565b565b805163ffffffff9081166000908152600d602090815260408083208286015185168452600101909152902060808301519091161580612a5f575060808201518590612a57906001614b41565b63ffffffff16115b15612aab5760808201516040517fd5f5269100000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101869052604401610677565b6001826020015163ffffffff161115612b5757815163ffffffff166000908152600d602090815260408220908401516001918201918391612aec9190614594565b63ffffffff1663ffffffff168152602001908152602001600020905060005b612b14826130bb565b811015612b5457612b43846000015163ffffffff16600c60006105f985876000016130c590919063ffffffff16565b50612b4d8161455c565b9050612b0b565b50505b60005b85811015612c4157612b87878783818110612b7757612b7761452d565b85926020909102013590506133c6565b612be8578251878783818110612b9f57612b9f61452d565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610677565b8251612c309063ffffffff16600c60008a8a86818110612c0a57612c0a61452d565b9050602002013581526020019081526020016000206004016133c690919063ffffffff16565b50612c3a8161455c565b9050612b5a565b5060005b83811015612f2d5736858583818110612c6057612c6061452d565b9050602002810190612c729190614604565b9050612c806003823561296d565b612cb9576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610677565b612cc56005823561296d565b15612cff576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610677565b8035600090815260038401602052604081208054612d1c906145b1565b90501115612d685783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610677565b60005b87811015612e7a57612e0f8235600c60008c8c86818110612d8e57612d8e61452d565b9050602002013581526020019081526020016000206003016000600c60008e8e88818110612dbe57612dbe61452d565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200190815260200160002061296d90919063ffffffff16565b612e6a57888882818110612e2557612e2561452d565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610677565b612e738161455c565b9050612d6b565b5060028301805460018101825560009182526020918290208335910155612ea390820182614b5e565b82356000908152600386016020526040902091612ec1919083614bc3565b508351602080860151612f1c92918435908c908c90612ee290880188614b5e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061375b92505050565b50612f268161455c565b9050612c45565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff90951694909417909355606086015186518316825284822080549115156d0100000000000000000000000000027fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff9092169190911790556080860151865183168252848220805491841668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651926130ab929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b6000610476825490565b6000612981838361383c565b60006129818383613866565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d825284832080546401000000009004909116808452600190910182528483206002810180548751818602810186019098528088529596929591949390919083018282801561318e57602002820191906000526020600020905b81548152602001906001019080831161317a575b505050505090506000815167ffffffffffffffff8111156131b1576131b1613a71565b6040519080825280602002602001820160405280156131f757816020015b6040805180820190915260008152606060208201528152602001906001900390816131cf5790505b50905060005b81518110156133185760405180604001604052808483815181106132235761322361452d565b602002602001015181526020018560030160008685815181106132485761324861452d565b602002602001015181526020019081526020016000208054613269906145b1565b80601f0160208091040260200160405190810160405280929190818152602001828054613295906145b1565b80156132e25780601f106132b7576101008083540402835291602001916132e2565b820191906000526020600020905b8154815290600101906020018083116132c557829003601f168201915b50505050508152508282815181106132fc576132fc61452d565b6020026020010181905250806133119061455c565b90506131fd565b506040805160e08101825263ffffffff8089166000818152600d60208181528683205480861687528b8616828801526801000000000000000081049095169686019690965260ff6c010000000000000000000000008504811615156060870152929091529093526d010000000000000000000000000090049091161515608082015260a081016133a7856133b9565b81526020019190915295945050505050565b6060600061298183613959565b600061298183836139b5565b608081015173ffffffffffffffffffffffffffffffffffffffff161561352057608081015173ffffffffffffffffffffffffffffffffffffffff163b15806134cb575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa1580156134a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c99190614cde565b155b156135205760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610677565b60008281526002602052604090208151829190819061353f90826146fa565b506020820151600182019061355490826146fa565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156135965761359661429b565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156135dd576135dd61429b565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff8216036136e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610677565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561220a57600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613802908690869086908b908d90600401614cfb565b600060405180830381600087803b15801561381c57600080fd5b505af1158015613830573d6000803e3d6000fd5b50505050505050505050565b60008260000182815481106138535761385361452d565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561394f57600061388a600183614b2e565b855490915060009061389e90600190614b2e565b90508181146139035760008660000182815481106138be576138be61452d565b90600052602060002001549050808760000184815481106138e1576138e161452d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061391457613914614d7d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610476565b6000915050610476565b6060816000018054806020026020016040519081016040528092919081815260200182805480156139a957602002820191906000526020600020905b815481526020019060010190808311613995575b50505050509050919050565b60008181526001830160205260408120546139fc57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610476565b506000610476565b508054613a10906145b1565b6000825580601f10613a20575050565b601f01602090049060005260206000209081019061296a9190613a58565b508054600082559060005260206000209081019061296a91905b5b80821115613a6d5760008155600101613a59565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ac357613ac3613a71565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ac357613ac3613a71565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613b3357613b33613a71565b604052919050565b600067ffffffffffffffff821115613b5557613b55613a71565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613b9257600080fd5b8135613ba5613ba082613b3b565b613aec565b818152846020838601011115613bba57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613bea57600080fd5b823567ffffffffffffffff80821115613c0257600080fd5b613c0e86838701613b81565b93506020850135915080821115613c2457600080fd5b50613c3185828601613b81565b9150509250929050565b600060208284031215613c4d57600080fd5b5035919050565b60005b83811015613c6f578181015183820152602001613c57565b50506000910152565b60008151808452613c90816020860160208601613c54565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129816020830184613c78565b60008083601f840112613ce757600080fd5b50813567ffffffffffffffff811115613cff57600080fd5b6020830191508360208260051b850101111561104c57600080fd5b801515811461296a57600080fd5b803563ffffffff81168114613d3c57600080fd5b919050565b600080600080600080600060a0888a031215613d5c57600080fd5b873567ffffffffffffffff80821115613d7457600080fd5b613d808b838c01613cd5565b909950975060208a0135915080821115613d9957600080fd5b50613da68a828b01613cd5565b9096509450506040880135613dba81613d1a565b92506060880135613dca81613d1a565b9150613dd860808901613d28565b905092959891949750929550565b60008060208385031215613df957600080fd5b823567ffffffffffffffff811115613e1057600080fd5b613e1c85828601613cd5565b90969095509350505050565b600081518084526020808501945080840160005b83811015613e5857815187529582019590820190600101613e3c565b509495945050505050565b600063ffffffff80835116845260208181850151168186015260408281860151168187015260608501511515606087015260808501511515608087015260a0850151925060e060a0870152613ebb60e0870184613e28565b925060c085015186840360c08801528381518086528486019150848160051b870101858401935060005b82811015613f42578782037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018452845180518352870151878301879052613f2f87840182613c78565b9588019594880194925050600101613ee5565b509998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613fc3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613fb1858351613e63565b94509285019290850190600101613f77565b5092979650505050505050565b600060208284031215613fe257600080fd5b61298182613d28565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526140206040850182613c78565b949350505050565b6020815260006129816020830184613feb565b6020815260006129816020830184613e63565b6000806040838503121561406157600080fd5b61406a83613d28565b946020939093013593505050565b60408152600061408b6040830185613c78565b828103602084015261409d8185613c78565b95945050505050565b63ffffffff8151168252602081015160208301526040810151604083015260006060820151608060608501526140206080850182613e28565b6040815260006140f260408301856140a6565b905063ffffffff831660208301529392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613fc3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614168858351613feb565b9450928501929085019060010161412e565b6000806000806040858703121561419057600080fd5b843567ffffffffffffffff808211156141a857600080fd5b6141b488838901613cd5565b909650945060208701359150808211156141cd57600080fd5b506141da87828801613cd5565b95989497509550505050565b60008060008060008060008060c0898b03121561420257600080fd5b61420b89613d28565b9750602089013567ffffffffffffffff8082111561422857600080fd5b6142348c838d01613cd5565b909950975060408b013591508082111561424d57600080fd5b5061425a8b828c01613cd5565b909650945050606089013561426e81613d1a565b9250608089013561427e81613d1a565b915061428c60a08a01613d28565b90509295985092959890939650565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000815160a084526142df60a0850182613c78565b9050602083015184820360208601526142f88282613c78565b9150506040830151600481106143105761431061429b565b604085015260608301516002811061432a5761432a61429b565b606085015260809283015173ffffffffffffffffffffffffffffffffffffffff1692909301919091525090565b60208152600061298160208301846142ca565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613fc3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143cb8583516142ca565b94509285019290850190600101614391565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015614452577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526144408683516140a6565b95509382019390820190600101614406565b50508584038187015286518085528782019482019350915060005b8281101561448f57845163ffffffff168452938101939281019260010161446d565b5091979650505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114613d3c57600080fd5b6000602082840312156144d257600080fd5b6129818261449c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614523576145236144db565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361458d5761458d6144db565b5060010190565b63ffffffff82811682821603908082111561086d5761086d6144db565b600181811c908216806145c557607f821691505b6020821081036145fe577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261463857600080fd5b9190910192915050565b60006040823603121561465457600080fd5b6040516040810167ffffffffffffffff828210818311171561467857614678613a71565b816040526146858561449c565b8352602085013591508082111561469b57600080fd5b506146a836828601613b81565b60208301525092915050565b601f82111561070a57600081815260208120601f850160051c810160208610156146db5750805b601f850160051c820191505b8181101561220a578281556001016146e7565b815167ffffffffffffffff81111561471457614714613a71565b6147288161472284546145b1565b846146b4565b602080601f83116001811461477b57600084156147455750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561220a565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156147c8578886015182559484019460019091019084016147a9565b508582101561480457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561482657600080fd5b815167ffffffffffffffff81111561483d57600080fd5b8201601f8101841361484e57600080fd5b805161485c613ba082613b3b565b81815285602083850101111561487157600080fd5b61409d826020830160208601613c54565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261463857600080fd5b6000608082360312156148c857600080fd5b6148d0613aa0565b6148d983613d28565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff8082111561490a57600080fd5b9085019036601f83011261491d57600080fd5b81358181111561492f5761492f613a71565b8060051b9150614940848301613aec565b818152918301840191848101903684111561495a57600080fd5b938501935b838510156149785784358252938501939085019061495f565b606087015250939695505050505050565b6020815260006129816020830184613e28565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261463857600080fd5b803560028110613d3c57600080fd5b600060a082360312156149f157600080fd5b6149f9613ac9565b823567ffffffffffffffff80821115614a1157600080fd5b614a1d36838701613b81565b83526020850135915080821115614a3357600080fd5b50614a4036828601613b81565b602083015250604083013560048110614a5857600080fd5b6040820152614a69606084016149d0565b6060820152614a7a6080840161449c565b608082015292915050565b6000602080835260008454614a99816145b1565b80848701526040600180841660008114614aba5760018114614af257614b20565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550614b20565b896000528660002060005b85811015614b185781548b8201860152908301908801614afd565b8a0184019650505b509398975050505050505050565b81810381811115610476576104766144db565b63ffffffff81811683821601908082111561086d5761086d6144db565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614b9357600080fd5b83018035915067ffffffffffffffff821115614bae57600080fd5b60200191503681900382131561104c57600080fd5b67ffffffffffffffff831115614bdb57614bdb613a71565b614bef83614be983546145b1565b836146b4565b6000601f841160018114614c415760008515614c0b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614cd7565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c905786850135825560209485019460019092019101614c70565b5086821015614ccb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b600060208284031215614cf057600080fd5b815161298181613d1a565b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115614d3457600080fd5b8560051b808860a0850137820182810360a09081016020850152614d5a90820187613c78565b91505063ffffffff80851660408401528084166060840152509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodeInfo\",\"type\":\"tuple[]\"},{\"internalType\":\"uint32[]\",\"name\":\"configCounts\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b614e4980620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635e65e309116100ee5780638da5cb5b11610097578063d8bc7b6811610071578063d8bc7b68146103f7578063ddbe4f821461040a578063e29581aa14610420578063f2fde38b1461043657600080fd5b80638da5cb5b1461039c5780639cb7c5f4146103c4578063d59a79f6146103e457600080fd5b806373ac22b4116100c857806373ac22b41461036e57806379ba50971461038157806386fa42461461038957600080fd5b80635e65e3091461033357806366acaa3314610346578063715f52951461035b57600080fd5b8063235374051161015b578063398f377311610135578063398f3773146102cb5780633f2a13c9146102de57806350c946fe146102ff5780635d83d9671461032057600080fd5b80632353740514610285578063275459f2146102a55780632c01a1e8146102b857600080fd5b80631d05394c1161018c5780631d05394c1461023b578063214502431461025057806322bdbcbc1461026557600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613c5d565b610449565b6040519081526020015b60405180910390f35b6101ec6101e7366004613cc1565b61047d565b60405190151581526020016101d0565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101d09190613d48565b61024e610249366004613da0565b61048a565b005b610258610646565b6040516101d09190613f00565b610278610273366004613f99565b6107ab565b6040516101d09190613ff1565b610298610293366004613f99565b610898565b6040516101d09190614004565b61024e6102b3366004613da0565b6108dc565b61024e6102c6366004613da0565b6109b3565b61024e6102d9366004613da0565b610bd6565b6102f16102ec366004614017565b610d9e565b6040516101d0929190614041565b61031261030d366004613cc1565b610f8a565b6040516101d092919061409f565b61024e61032e366004613da0565b61102f565b61024e610341366004613da0565b61117d565b61034e6115ef565b6040516101d091906140c7565b61024e610369366004613da0565b6117da565b61024e61037c366004613da0565b611895565b61024e611d3a565b61024e61039736600461413a565b611e37565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6103d76103d2366004613cc1565b61217d565b6040516101d09190614262565b61024e6103f2366004614294565b612382565b61024e610405366004614349565b61244b565b610412612515565b6040516101d09291906143ee565b610428612880565b6040516101d092919061447e565b61024e610444366004614554565b6129ef565b6000828260405160200161045e929190614041565b6040516020818303038152906040528051906020012090505b92915050565b6000610477600583612a03565b610492612a1e565b60005b818110156106415760008383838181106104b1576104b161456f565b90506020020160208101906104c69190613f99565b63ffffffff8082166000908152600d60209081526040808320805464010000000090049094168084526001850190925282209394509192905b61050882612aa1565b8110156105605761054f8563ffffffff16600c60006105308587612aab90919063ffffffff16565b8152602001908152602001600020600401612ab790919063ffffffff16565b50610559816145cd565b90506104ff565b508254640100000000900463ffffffff166000036105b7576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff851660048201526024015b60405180910390fd5b63ffffffff84166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a1505050508061063a906145cd565b9050610495565b505050565b600e54606090640100000000900463ffffffff166000610667600183614605565b63ffffffff1667ffffffffffffffff81111561068557610685613af7565b60405190808252806020026020018201604052801561070c57816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106a35790505b509050600060015b8363ffffffff168163ffffffff1610156107885763ffffffff8082166000908152600d602052604090205416156107785761074e81612ac3565b8383815181106107605761076061456f565b602002602001018190525081610775906145cd565b91505b61078181614622565b9050610714565b50610794600184614605565b63ffffffff1681146107a4578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161080f90614645565b80601f016020809104026020016040519081016040528092919081815260200182805461083b90614645565b80156108885780601f1061085d57610100808354040283529160200191610888565b820191906000526020600020905b81548152906001019060200180831161086b57829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047782612ac3565b6108e4612a1e565b60005b63ffffffff811682111561064157600083838363ffffffff1681811061090f5761090f61456f565b90506020020160208101906109249190613f99565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815591925061096f6001830182613a8a565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a2506109ac81614622565b90506108e7565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610bd05760008484838181106109ed576109ed61456f565b602090810292909201356000818152600c90935260409092206001810154929350919050610a4a576040517fd82f6adb000000000000000000000000000000000000000000000000000000008152600481018390526024016105ae565b6000610a5882600401612aa1565b1115610a93576040517f34a4a3f6000000000000000000000000000000000000000000000000000000008152600481018390526024016105ae565b83158015610acd5750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610b06576040517f9473075d0000000000000000000000000000000000000000000000000000000081523360048201526024016105ae565b6001810154610b1790600790612ab7565b506002810154610b2990600990612ab7565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016815560018101829055600281018290559060048201818181610b7e8282613ac4565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610bb591815260200190565b60405180910390a1505080610bc9906145cd565b90506109d1565b50505050565b610bde612a1e565b60005b81811015610641576000838383818110610bfd57610bfd61456f565b9050602002810190610c0f9190614698565b610c18906146d6565b805190915073ffffffffffffffffffffffffffffffffffffffff16610c69576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610cf5908261478e565b5050600e8054909150600090610d109063ffffffff16614622565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610d839190613d48565b60405180910390a3505080610d97906145cd565b9050610be1565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610df090614645565b80601f0160208091040260200160405190810160405280929190818152602001828054610e1c90614645565b8015610e695780601f10610e3e57610100808354040283529160200191610e69565b820191906000526020600020905b815481529060010190602001808311610e4c57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150610f7c905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610f33573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610f7991908101906148a8565b90505b9093509150505b9250929050565b6040805160808101825260008082526020820181905291810191909152606080820152604080516080810182526000848152600c6020908152838220805463ffffffff80821686526001830154848701526002830154868801526401000000009091041683526003019052918220606082019061100690612d97565b90526000938452600c602052604090932054929364010000000090930463ffffffff1692915050565b611037612a1e565b60005b818110156106415760008383838181106110565761105661456f565b905060200201359050611073816003612a0390919063ffffffff16565b6110ac576040517fe181733f000000000000000000000000000000000000000000000000000000008152600481018290526024016105ae565b6110b7600582612da4565b6110f0576040517ff7d7a294000000000000000000000000000000000000000000000000000000008152600481018290526024016105ae565b6000818152600260205260408120906111098282613a8a565b611117600183016000613a8a565b5060020180547fffffffffffffffffffff0000000000000000000000000000000000000000000016905560405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250611176816145cd565b905061103a565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610bd05760008484838181106111b7576111b761456f565b90506020028101906111c99190614916565b6111d29061494a565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161122890614645565b80601f016020809104026020016040519081016040528092919081815260200182805461125490614645565b80156112a15780601f10611276576101008083540402835291602001916112a1565b820191906000526020600020905b81548152906001019060200180831161128457829003601f168201915b5050505050815250509050831580156112d15750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561130a576040517f9473075d0000000000000000000000000000000000000000000000000000000081523360048201526024016105ae565b6040808301516000908152600c60205220600181015461135e5782604001516040517fd82f6adb0000000000000000000000000000000000000000000000000000000081526004016105ae91815260200190565b6020830151158061138e5750826020015181600101541415801561138e5750602083015161138e90600790612a03565b156113c5576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060830151805160000361140757806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016105ae9190614a1d565b8154640100000000900463ffffffff1682600461142383614622565b82546101009290920a63ffffffff8181021990931691831602179091558354640100000000900416905060005b825181101561151b5761148683828151811061146e5761146e61456f565b60200260200101516003612a0390919063ffffffff16565b6114be57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016105ae9190614a1d565b61150a8382815181106114d3576114d361456f565b60200260200101518560030160008563ffffffff1663ffffffff168152602001908152602001600020612da490919063ffffffff16565b50611514816145cd565b9050611450565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9091161783556040850151600284015560018301546020860151811461158d57611572600782612ab7565b5060208601516001850181905561158b90600790612da4565b505b85516040808801516020808a015183519283529082015263ffffffff909216917f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a2505050505050806115e8906145cd565b905061119b565b600e5460609063ffffffff166000611608600183614605565b63ffffffff1667ffffffffffffffff81111561162657611626613af7565b60405190808252806020026020018201604052801561166c57816020015b6040805180820190915260008152606060208201528152602001906001900390816116445790505b509050600060015b8363ffffffff168163ffffffff1610156117c45763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff16156117b45763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161170890614645565b80601f016020809104026020016040519081016040528092919081815260200182805461173490614645565b80156117815780601f1061175657610100808354040283529160200191611781565b820191906000526020600020905b81548152906001019060200180831161176457829003601f168201915b50505050508152505083838151811061179c5761179c61456f565b6020026020010181905250816117b1906145cd565b91505b6117bd81614622565b9050611674565b50600e546107949060019063ffffffff16614605565b6117e2612a1e565b60005b818110156106415760008383838181106118015761180161456f565b90506020028101906118139190614a30565b61181c90614a73565b9050600061183282600001518360200151610449565b905061183f600382612da4565b611878576040517febf52551000000000000000000000000000000000000000000000000000000008152600481018290526024016105ae565b6118828183612db0565b50508061188e906145cd565b90506117e5565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610bd05760008484838181106118cf576118cf61456f565b90506020028101906118e19190614916565b6118ea9061494a565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161194090614645565b80601f016020809104026020016040519081016040528092919081815260200182805461196c90614645565b80156119b95780601f1061198e576101008083540402835291602001916119b9565b820191906000526020600020905b81548152906001019060200180831161199c57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611a1f5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526024016105ae565b83158015611a445750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611a7d576040517f9473075d0000000000000000000000000000000000000000000000000000000081523360048201526024016105ae565b6040808301516000908152600c60205220600181015415611ad25782604001516040517f546184830000000000000000000000000000000000000000000000000000000081526004016105ae91815260200190565b6040830151611b155782604001516040517f64e2ee920000000000000000000000000000000000000000000000000000000081526004016105ae91815260200190565b60208301511580611b3257506020830151611b3290600790612a03565b15611b69576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611bab57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016105ae9190614a1d565b81548290600490611bc990640100000000900463ffffffff16614622565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611c7057611c1283828151811061146e5761146e61456f565b611c4a57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016105ae9190614a1d565b611c5f8382815181106114d3576114d361456f565b50611c69816145cd565b9050611bf4565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff91821617845560408601516002850155602086015160018501819055611cc69160079190612da416565b506040850151611cd890600990612da4565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080611d33906145cd565b90506118b3565b60015473ffffffffffffffffffffffffffffffffffffffff163314611dbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016105ae565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b828114611e7a576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044016105ae565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b84811015612175576000868683818110611eb257611eb261456f565b9050602002016020810190611ec79190613f99565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16611f36576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff831660048201526024016105ae565b6000868685818110611f4a57611f4a61456f565b9050602002810190611f5c9190614698565b611f65906146d6565b805190915073ffffffffffffffffffffffffffffffffffffffff16611fb6576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff163314801590611ff357503373ffffffffffffffffffffffffffffffffffffffff861614155b1561202c576040517f9473075d0000000000000000000000000000000000000000000000000000000081523360048201526024016105ae565b8051825473ffffffffffffffffffffffffffffffffffffffff90811691161415806120a857506020808201516040516120659201613d48565b604051602081830303815290604052805190602001208260010160405160200161208f9190614b19565b6040516020818303038152906040528051906020012014155b1561216157805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560208101516001830190612102908261478e565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516121589190613d48565b60405180910390a35b5050508061216e906145cd565b9050611e96565b505050505050565b6121ad6040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b60008281526002602052604090819020815160a081019092528054829082906121d590614645565b80601f016020809104026020016040519081016040528092919081815260200182805461220190614645565b801561224e5780601f106122235761010080835404028352916020019161224e565b820191906000526020600020905b81548152906001019060200180831161223157829003601f168201915b5050505050815260200160018201805461226790614645565b80601f016020809104026020016040519081016040528092919081815260200182805461229390614645565b80156122e05780601f106122b5576101008083540402835291602001916122e0565b820191906000526020600020905b8154815290600101906020018083116122c357829003601f168201915b5050509183525050600282015460209091019060ff166003811115612307576123076141a6565b6003811115612318576123186141a6565b81526020016002820160019054906101000a900460ff166001811115612340576123406141a6565b6001811115612351576123516141a6565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61238a612a1e565b63ffffffff8089166000908152600d60205260408120546401000000009004909116908190036123ee576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a1660048201526024016105ae565b612440888888886040518060a001604052808f63ffffffff1681526020018761241690614622565b97508763ffffffff1681526020018a1515815260200189151581526020018860ff16815250613044565b505050505050505050565b612453612a1e565b600e805460009164010000000090910463ffffffff1690600461247583614622565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff8416608082015290915061250b908990899089908990613044565b5050505050505050565b60608060006125246003612d97565b905060006125326005612aa1565b825161253e9190614bc2565b905060008167ffffffffffffffff81111561255b5761255b613af7565b6040519080825280602002602001820160405280156125bc57816020015b6125a96040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b8152602001906001900390816125795790505b50905060008267ffffffffffffffff8111156125da576125da613af7565b604051908082528060200260200182016040528015612603578160200160208202803683370190505b5090506000805b85518110156128725760008682815181106126275761262761456f565b60200260200101519050612645816005612a0390919063ffffffff16565b6128615760008181526002602052604090819020815160a0810190925280548290829061267190614645565b80601f016020809104026020016040519081016040528092919081815260200182805461269d90614645565b80156126ea5780601f106126bf576101008083540402835291602001916126ea565b820191906000526020600020905b8154815290600101906020018083116126cd57829003601f168201915b5050505050815260200160018201805461270390614645565b80601f016020809104026020016040519081016040528092919081815260200182805461272f90614645565b801561277c5780601f106127515761010080835404028352916020019161277c565b820191906000526020600020905b81548152906001019060200180831161275f57829003601f168201915b5050509183525050600282015460209091019060ff1660038111156127a3576127a36141a6565b60038111156127b4576127b46141a6565b81526020016002820160019054906101000a900460ff1660018111156127dc576127dc6141a6565b60018111156127ed576127ed6141a6565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff16602090910152855186908590811061282c5761282c61456f565b60200260200101819052508084848151811061284a5761284a61456f565b602090810291909101015261285e836145cd565b92505b5061286b816145cd565b905061260a565b509096919550909350505050565b606080600061288f6009612d97565b9050805167ffffffffffffffff8111156128ab576128ab613af7565b60405190808252806020026020018201604052801561291a57816020015b60408051608081018252600080825260208083018290529282015260608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816128c95790505b509250805167ffffffffffffffff81111561293757612937613af7565b604051908082528060200260200182016040528015612960578160200160208202803683370190505b50915060005b81518110156129e9576129918282815181106129845761298461456f565b6020026020010151610f8a565b8583815181106129a3576129a361456f565b602002602001018584815181106129bc576129bc61456f565b602002602001018263ffffffff1663ffffffff168152508290525050806129e2906145cd565b9050612966565b50509091565b6129f7612a1e565b612a00816136ec565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105ae565b565b6000610477825490565b6000612a1783836137e1565b6000612a17838361380b565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612b7457602002820191906000526020600020905b815481526020019060010190808311612b60575b505050505090506000815167ffffffffffffffff811115612b9757612b97613af7565b604051908082528060200260200182016040528015612bdd57816020015b604080518082019091526000815260606020820152815260200190600190039081612bb55790505b50905060005b8151811015612cfe576040518060400160405280848381518110612c0957612c0961456f565b60200260200101518152602001856003016000868581518110612c2e57612c2e61456f565b602002602001015181526020019081526020016000208054612c4f90614645565b80601f0160208091040260200160405190810160405280929190818152602001828054612c7b90614645565b8015612cc85780601f10612c9d57610100808354040283529160200191612cc8565b820191906000526020600020905b815481529060010190602001808311612cab57829003601f168201915b5050505050815250828281518110612ce257612ce261456f565b602002602001018190525080612cf7906145cd565b9050612be3565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a08101612d8585612d97565b81526020019190915295945050505050565b60606000612a17836138fe565b6000612a17838361395a565b608081015173ffffffffffffffffffffffffffffffffffffffff1615612efe57608081015173ffffffffffffffffffffffffffffffffffffffff163b1580612ea9575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa158015612e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea79190614bd5565b155b15612efe5760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016105ae565b600082815260026020526040902081518291908190612f1d908261478e565b5060208201516001820190612f32908261478e565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836003811115612f7457612f746141a6565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115612fbb57612fbb6141a6565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613096575060808201518590613091906001614bf2565b60ff16115b156130df5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018690526044016105ae565b6001826020015163ffffffff16111561318b57815163ffffffff166000908152600d6020908152604082209084015160019182019183916131209190614605565b63ffffffff1663ffffffff168152602001908152602001600020905060005b61314882612aa1565b81101561318857613177846000015163ffffffff16600c60006105308587600001612aab90919063ffffffff16565b50613181816145cd565b905061313f565b50505b60005b85811015613275576131bb8787838181106131ab576131ab61456f565b8592602090910201359050612da4565b61321c5782518787838181106131d3576131d361456f565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff909416600485015260200291909101356024830152506044016105ae565b82516132649063ffffffff16600c60008a8a8681811061323e5761323e61456f565b905060200201358152602001908152602001600020600401612da490919063ffffffff16565b5061326e816145cd565b905061318e565b5060005b8381101561356157368585838181106132945761329461456f565b90506020028101906132a69190614698565b90506132b460038235612a03565b6132ed576040517fe181733f000000000000000000000000000000000000000000000000000000008152813560048201526024016105ae565b6132f960058235612a03565b15613333576040517ff7d7a294000000000000000000000000000000000000000000000000000000008152813560048201526024016105ae565b803560009081526003840160205260408120805461335090614645565b9050111561339c5783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152813560248201526044016105ae565b60005b878110156134ae576134438235600c60008c8c868181106133c2576133c261456f565b9050602002013581526020019081526020016000206003016000600c60008e8e888181106133f2576133f261456f565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612a0390919063ffffffff16565b61349e578888828181106134595761345961456f565b6040517fa7e7925000000000000000000000000000000000000000000000000000000000815260209091029290920135600483015250823560248201526044016105ae565b6134a7816145cd565b905061339f565b50600283018054600181018255600091825260209182902083359101556134d790820182614c0b565b823560009081526003860160205260409020916134f5919083614c70565b50835160208086015161355092918435908c908c9061351690880188614c0b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506139a992505050565b5061355a816145cd565b9050613279565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606086015186518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080860151865183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651926136dc929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361376b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105ae565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008260000182815481106137f8576137f861456f565b9060005260206000200154905092915050565b600081815260018301602052604081205480156138f457600061382f600183614bc2565b855490915060009061384390600190614bc2565b90508181146138a85760008660000182815481106138635761386361456f565b90600052602060002001549050808760000184815481106138865761388661456f565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806138b9576138b9614d8b565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610477565b6000915050610477565b60608160000180548060200260200160405190810160405280929190818152602001828054801561394e57602002820191906000526020600020905b81548152602001906001019080831161393a575b50505050509050919050565b60008181526001830160205260408120546139a157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610477565b506000610477565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561217557600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613a50908690869086908b908d90600401614dba565b600060405180830381600087803b158015613a6a57600080fd5b505af1158015613a7e573d6000803e3d6000fd5b50505050505050505050565b508054613a9690614645565b6000825580601f10613aa6575050565b601f016020900490600052602060002090810190612a009190613ade565b5080546000825590600052602060002090810190612a0091905b5b80821115613af35760008155600101613adf565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613b4957613b49613af7565b60405290565b60405160a0810167ffffffffffffffff81118282101715613b4957613b49613af7565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bb957613bb9613af7565b604052919050565b600067ffffffffffffffff821115613bdb57613bdb613af7565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613c1857600080fd5b8135613c2b613c2682613bc1565b613b72565b818152846020838601011115613c4057600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613c7057600080fd5b823567ffffffffffffffff80821115613c8857600080fd5b613c9486838701613c07565b93506020850135915080821115613caa57600080fd5b50613cb785828601613c07565b9150509250929050565b600060208284031215613cd357600080fd5b5035919050565b60005b83811015613cf5578181015183820152602001613cdd565b50506000910152565b60008151808452613d16816020860160208601613cda565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612a176020830184613cfe565b60008083601f840112613d6d57600080fd5b50813567ffffffffffffffff811115613d8557600080fd5b6020830191508360208260051b8501011115610f8357600080fd5b60008060208385031215613db357600080fd5b823567ffffffffffffffff811115613dca57600080fd5b613dd685828601613d5b565b90969095509350505050565b600081518084526020808501945080840160005b83811015613e1257815187529582019590820190600101613df6565b509495945050505050565b600081518084526020808501808196508360051b8101915082860160005b85811015613e795782840389528151805185528501516040868601819052613e6581870183613cfe565b9a87019a9550505090840190600101613e3b565b5091979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a0850152613ede60e0850182613de2565b905060c083015184820360c0860152613ef78282613e1d565b95945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613f73577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613f61858351613e86565b94509285019290850190600101613f27565b5092979650505050505050565b803563ffffffff81168114613f9457600080fd5b919050565b600060208284031215613fab57600080fd5b612a1782613f80565b73ffffffffffffffffffffffffffffffffffffffff81511682526000602082015160406020850152613fe96040850182613cfe565b949350505050565b602081526000612a176020830184613fb4565b602081526000612a176020830184613e86565b6000806040838503121561402a57600080fd5b61403383613f80565b946020939093013593505050565b6040815260006140546040830185613cfe565b8281036020840152613ef78185613cfe565b63ffffffff815116825260208101516020830152604081015160408301526000606082015160806060850152613fe96080850182613de2565b6040815260006140b26040830185614066565b905063ffffffff831660208301529392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613f73577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614128858351613fb4565b945092850192908501906001016140ee565b6000806000806040858703121561415057600080fd5b843567ffffffffffffffff8082111561416857600080fd5b61417488838901613d5b565b9096509450602087013591508082111561418d57600080fd5b5061419a87828801613d5b565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000815160a084526141ea60a0850182613cfe565b9050602083015184820360208601526142038282613cfe565b91505060408301516004811061421b5761421b6141a6565b6040850152606083015160028110614235576142356141a6565b606085015260809283015173ffffffffffffffffffffffffffffffffffffffff1692909301919091525090565b602081526000612a1760208301846141d5565b8015158114612a0057600080fd5b803560ff81168114613f9457600080fd5b60008060008060008060008060c0898b0312156142b057600080fd5b6142b989613f80565b9750602089013567ffffffffffffffff808211156142d657600080fd5b6142e28c838d01613d5b565b909950975060408b01359150808211156142fb57600080fd5b506143088b828c01613d5b565b909650945050606089013561431c81614275565b9250608089013561432c81614275565b915061433a60a08a01614283565b90509295985092959890939650565b600080600080600080600060a0888a03121561436457600080fd5b873567ffffffffffffffff8082111561437c57600080fd5b6143888b838c01613d5b565b909950975060208a01359150808211156143a157600080fd5b506143ae8a828b01613d5b565b90965094505060408801356143c281614275565b925060608801356143d281614275565b91506143e060808901614283565b905092959891949750929550565b6040815260006144016040830185613de2565b6020838203818501528185518084528284019150828160051b85010183880160005b8381101561446f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087840301855261445d8383516141d5565b94860194925090850190600101614423565b50909998505050505050505050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b838110156144f3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526144e1868351614066565b955093820193908201906001016144a7565b50508584038187015286518085528782019482019350915060005b82811015613e7957845163ffffffff168452938101939281019260010161450e565b803573ffffffffffffffffffffffffffffffffffffffff81168114613f9457600080fd5b60006020828403121561456657600080fd5b612a1782614530565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145fe576145fe61459e565b5060010190565b63ffffffff8281168282160390808211156107a4576107a461459e565b600063ffffffff80831681810361463b5761463b61459e565b6001019392505050565b600181811c9082168061465957607f821691505b602082108103614692577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126146cc57600080fd5b9190910192915050565b6000604082360312156146e857600080fd5b6040516040810167ffffffffffffffff828210818311171561470c5761470c613af7565b8160405261471985614530565b8352602085013591508082111561472f57600080fd5b5061473c36828601613c07565b60208301525092915050565b601f82111561064157600081815260208120601f850160051c8101602086101561476f5750805b601f850160051c820191505b818110156121755782815560010161477b565b815167ffffffffffffffff8111156147a8576147a8613af7565b6147bc816147b68454614645565b84614748565b602080601f83116001811461480f57600084156147d95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612175565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561485c5788860151825594840194600190910190840161483d565b508582101561489857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156148ba57600080fd5b815167ffffffffffffffff8111156148d157600080fd5b8201601f810184136148e257600080fd5b80516148f0613c2682613bc1565b81815285602083850101111561490557600080fd5b613ef7826020830160208601613cda565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126146cc57600080fd5b60006080823603121561495c57600080fd5b614964613b26565b61496d83613f80565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff8082111561499e57600080fd5b9085019036601f8301126149b157600080fd5b8135818111156149c3576149c3613af7565b8060051b91506149d4848301613b72565b81815291830184019184810190368411156149ee57600080fd5b938501935b83851015614a0c578435825293850193908501906149f3565b606087015250939695505050505050565b602081526000612a176020830184613de2565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126146cc57600080fd5b803560028110613f9457600080fd5b600060a08236031215614a8557600080fd5b614a8d613b4f565b823567ffffffffffffffff80821115614aa557600080fd5b614ab136838701613c07565b83526020850135915080821115614ac757600080fd5b50614ad436828601613c07565b602083015250604083013560048110614aec57600080fd5b6040820152614afd60608401614a64565b6060820152614b0e60808401614530565b608082015292915050565b6000602080835260008454614b2d81614645565b80848701526040600180841660008114614b4e5760018114614b8657614bb4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550614bb4565b896000528660002060005b85811015614bac5781548b8201860152908301908801614b91565b8a0184019650505b509398975050505050505050565b818103818111156104775761047761459e565b600060208284031215614be757600080fd5b8151612a1781614275565b60ff81811683821601908111156104775761047761459e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614c4057600080fd5b83018035915067ffffffffffffffff821115614c5b57600080fd5b602001915036819003821315610f8357600080fd5b67ffffffffffffffff831115614c8857614c88613af7565b614c9c83614c968354614645565b83614748565b6000601f841160018114614cee5760008515614cb85750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614d84565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614d3d5786850135825560209485019460019092019101614d1d565b5086821015614d78577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115614df357600080fd5b8560051b808860a0850137820182810360a09081016020850152614e1990820187613cfe565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -206,25 +206,26 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind. return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([][32]byte, []CapabilityRegistryCapability, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilities") if err != nil { - return *new([]CapabilityRegistryCapability), err + return *new([][32]byte), *new([]CapabilityRegistryCapability), err } - out0 := *abi.ConvertType(out[0], new([]CapabilityRegistryCapability)).(*[]CapabilityRegistryCapability) + out0 := *abi.ConvertType(out[0], new([][32]byte)).(*[][32]byte) + out1 := *abi.ConvertType(out[1], new([]CapabilityRegistryCapability)).(*[]CapabilityRegistryCapability) - return out0, err + return out0, out1, err } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilities() ([]CapabilityRegistryCapability, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilities() ([][32]byte, []CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([]CapabilityRegistryCapability, error) { +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([][32]byte, []CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) } @@ -406,26 +407,33 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperators() ( return _CapabilityRegistry.Contract.GetNodeOperators(&_CapabilityRegistry.CallOpts) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodes(opts *bind.CallOpts) ([]CapabilityRegistryNodeInfo, []uint32, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodes(opts *bind.CallOpts) (GetNodes, + + error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getNodes") + outstruct := new(GetNodes) if err != nil { - return *new([]CapabilityRegistryNodeInfo), *new([]uint32), err + return *outstruct, err } - out0 := *abi.ConvertType(out[0], new([]CapabilityRegistryNodeInfo)).(*[]CapabilityRegistryNodeInfo) - out1 := *abi.ConvertType(out[1], new([]uint32)).(*[]uint32) + outstruct.NodeInfo = *abi.ConvertType(out[0], new([]CapabilityRegistryNodeInfo)).(*[]CapabilityRegistryNodeInfo) + outstruct.ConfigCounts = *abi.ConvertType(out[1], new([]uint32)).(*[]uint32) - return out0, out1, err + return *outstruct, err } -func (_CapabilityRegistry *CapabilityRegistrySession) GetNodes() ([]CapabilityRegistryNodeInfo, []uint32, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) GetNodes() (GetNodes, + + error) { return _CapabilityRegistry.Contract.GetNodes(&_CapabilityRegistry.CallOpts) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodes() ([]CapabilityRegistryNodeInfo, []uint32, error) { +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodes() (GetNodes, + + error) { return _CapabilityRegistry.Contract.GetNodes(&_CapabilityRegistry.CallOpts) } @@ -519,15 +527,15 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapabilities( return _CapabilityRegistry.Contract.AddCapabilities(&_CapabilityRegistry.TransactOpts, capabilities) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "addDON", nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } -func (_CapabilityRegistry *CapabilityRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddDON(&_CapabilityRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddDON(&_CapabilityRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } @@ -615,15 +623,15 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) TransferOwnershi return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "updateDON", donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } -func (_CapabilityRegistry *CapabilityRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.Contract.UpdateDON(&_CapabilityRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { return _CapabilityRegistry.Contract.UpdateDON(&_CapabilityRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) } @@ -2071,6 +2079,11 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseOwnershipTransferred return event, nil } +type GetNodes struct { + NodeInfo []CapabilityRegistryNodeInfo + ConfigCounts []uint32 +} + func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { case _CapabilityRegistry.abi.Events["CapabilityConfigured"].ID: @@ -2150,7 +2163,7 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { } type CapabilityRegistryInterface interface { - GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) + GetCapabilities(opts *bind.CallOpts) ([][32]byte, []CapabilityRegistryCapability, error) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) @@ -2168,7 +2181,9 @@ type CapabilityRegistryInterface interface { GetNodeOperators(opts *bind.CallOpts) ([]CapabilityRegistryNodeOperator, error) - GetNodes(opts *bind.CallOpts) ([]CapabilityRegistryNodeInfo, []uint32, error) + GetNodes(opts *bind.CallOpts) (GetNodes, + + error) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) @@ -2180,7 +2195,7 @@ type CapabilityRegistryInterface interface { AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilityRegistryCapability) (*types.Transaction, error) - AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) + AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) @@ -2196,7 +2211,7 @@ type CapabilityRegistryInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) + UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) diff --git a/core/gethwrappers/keystone/generated/router/router.go b/core/gethwrappers/keystone/generated/router/router.go new file mode 100644 index 00000000000..5c58af890bc --- /dev/null +++ b/core/gethwrappers/keystone/generated/router/router.go @@ -0,0 +1,954 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package router + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var KeystoneRouterMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"addForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"getTransmissionState\",\"outputs\":[{\"internalType\":\"enumIRouter.TransmissionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"removeForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"route\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610aa6806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806379ba509711610076578063abcef5541161005b578063abcef554146101c7578063e6b7145814610200578063f2fde38b1461023657600080fd5b806379ba5097146101805780638da5cb5b1461018857600080fd5b80634d93172d116100a75780634d93172d14610138578063516db4081461014d5780635c41d2fe1461016d57600080fd5b8063181f5a77146100c3578063233fd52d14610115575b600080fd5b6100ff6040518060400160405280601481526020017f4b657973746f6e65526f7574657220312e302e3000000000000000000000000081525081565b60405161010c9190610834565b60405180910390f35b610128610123366004610912565b610249565b604051901515815260200161010c565b61014b6101463660046109ad565b610441565b005b61016061015b3660046109cf565b6104bd565b60405161010c91906109e8565b61014b61017b3660046109ad565b61052c565b61014b6105ab565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b6101286101d53660046109ad565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460ff1690565b6101a261020e3660046109cf565b60009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61014b6102443660046109ad565b6106a8565b3360009081526002602052604081205460ff16610292576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008881526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16156102f6576040517fa53dc8ca000000000000000000000000000000000000000000000000000000008152600481018990526024015b60405180910390fd5b600088815260036020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a81169190911790915587163b900361035857506000610436565b6040517f805f213200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169063805f2132906103b0908890889088908890600401610a72565b600060405180830381600087803b1580156103ca57600080fd5b505af19250505080156103db575060015b6103e757506000610436565b50600087815260036020526040902080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560015b979650505050505050565b6104496106bc565b73ffffffffffffffffffffffffffffffffffffffff811660008181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b60008181526003602052604081205473ffffffffffffffffffffffffffffffffffffffff166104ee57506000919050565b60008281526003602052604090205474010000000000000000000000000000000000000000900460ff16610523576002610526565b60015b92915050565b6105346106bc565b73ffffffffffffffffffffffffffffffffffffffff811660008181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff16331461062c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102ed565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6106b06106bc565b6106b98161073f565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102ed565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036107be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102ed565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b8181101561086157858101830151858201604001528201610845565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108c457600080fd5b919050565b60008083601f8401126108db57600080fd5b50813567ffffffffffffffff8111156108f357600080fd5b60208301915083602082850101111561090b57600080fd5b9250929050565b600080600080600080600060a0888a03121561092d57600080fd5b8735965061093d602089016108a0565b955061094b604089016108a0565b9450606088013567ffffffffffffffff8082111561096857600080fd5b6109748b838c016108c9565b909650945060808a013591508082111561098d57600080fd5b5061099a8a828b016108c9565b989b979a50959850939692959293505050565b6000602082840312156109bf57600080fd5b6109c8826108a0565b9392505050565b6000602082840312156109e157600080fd5b5035919050565b6020810160038310610a23577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000610a86604083018688610a29565b8281036020840152610436818587610a2956fea164736f6c6343000813000a", +} + +var KeystoneRouterABI = KeystoneRouterMetaData.ABI + +var KeystoneRouterBin = KeystoneRouterMetaData.Bin + +func DeployKeystoneRouter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneRouter, error) { + parsed, err := KeystoneRouterMetaData.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(KeystoneRouterBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &KeystoneRouter{address: address, abi: *parsed, KeystoneRouterCaller: KeystoneRouterCaller{contract: contract}, KeystoneRouterTransactor: KeystoneRouterTransactor{contract: contract}, KeystoneRouterFilterer: KeystoneRouterFilterer{contract: contract}}, nil +} + +type KeystoneRouter struct { + address common.Address + abi abi.ABI + KeystoneRouterCaller + KeystoneRouterTransactor + KeystoneRouterFilterer +} + +type KeystoneRouterCaller struct { + contract *bind.BoundContract +} + +type KeystoneRouterTransactor struct { + contract *bind.BoundContract +} + +type KeystoneRouterFilterer struct { + contract *bind.BoundContract +} + +type KeystoneRouterSession struct { + Contract *KeystoneRouter + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type KeystoneRouterCallerSession struct { + Contract *KeystoneRouterCaller + CallOpts bind.CallOpts +} + +type KeystoneRouterTransactorSession struct { + Contract *KeystoneRouterTransactor + TransactOpts bind.TransactOpts +} + +type KeystoneRouterRaw struct { + Contract *KeystoneRouter +} + +type KeystoneRouterCallerRaw struct { + Contract *KeystoneRouterCaller +} + +type KeystoneRouterTransactorRaw struct { + Contract *KeystoneRouterTransactor +} + +func NewKeystoneRouter(address common.Address, backend bind.ContractBackend) (*KeystoneRouter, error) { + abi, err := abi.JSON(strings.NewReader(KeystoneRouterABI)) + if err != nil { + return nil, err + } + contract, err := bindKeystoneRouter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &KeystoneRouter{address: address, abi: abi, KeystoneRouterCaller: KeystoneRouterCaller{contract: contract}, KeystoneRouterTransactor: KeystoneRouterTransactor{contract: contract}, KeystoneRouterFilterer: KeystoneRouterFilterer{contract: contract}}, nil +} + +func NewKeystoneRouterCaller(address common.Address, caller bind.ContractCaller) (*KeystoneRouterCaller, error) { + contract, err := bindKeystoneRouter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &KeystoneRouterCaller{contract: contract}, nil +} + +func NewKeystoneRouterTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneRouterTransactor, error) { + contract, err := bindKeystoneRouter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &KeystoneRouterTransactor{contract: contract}, nil +} + +func NewKeystoneRouterFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneRouterFilterer, error) { + contract, err := bindKeystoneRouter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &KeystoneRouterFilterer{contract: contract}, nil +} + +func bindKeystoneRouter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := KeystoneRouterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_KeystoneRouter *KeystoneRouterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneRouter.Contract.KeystoneRouterCaller.contract.Call(opts, result, method, params...) +} + +func (_KeystoneRouter *KeystoneRouterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneRouter.Contract.KeystoneRouterTransactor.contract.Transfer(opts) +} + +func (_KeystoneRouter *KeystoneRouterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneRouter.Contract.KeystoneRouterTransactor.contract.Transact(opts, method, params...) +} + +func (_KeystoneRouter *KeystoneRouterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneRouter.Contract.contract.Call(opts, result, method, params...) +} + +func (_KeystoneRouter *KeystoneRouterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneRouter.Contract.contract.Transfer(opts) +} + +func (_KeystoneRouter *KeystoneRouterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneRouter.Contract.contract.Transact(opts, method, params...) +} + +func (_KeystoneRouter *KeystoneRouterCaller) GetTransmissionState(opts *bind.CallOpts, transmissionId [32]byte) (uint8, error) { + var out []interface{} + err := _KeystoneRouter.contract.Call(opts, &out, "getTransmissionState", transmissionId) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_KeystoneRouter *KeystoneRouterSession) GetTransmissionState(transmissionId [32]byte) (uint8, error) { + return _KeystoneRouter.Contract.GetTransmissionState(&_KeystoneRouter.CallOpts, transmissionId) +} + +func (_KeystoneRouter *KeystoneRouterCallerSession) GetTransmissionState(transmissionId [32]byte) (uint8, error) { + return _KeystoneRouter.Contract.GetTransmissionState(&_KeystoneRouter.CallOpts, transmissionId) +} + +func (_KeystoneRouter *KeystoneRouterCaller) GetTransmitter(opts *bind.CallOpts, transmissionId [32]byte) (common.Address, error) { + var out []interface{} + err := _KeystoneRouter.contract.Call(opts, &out, "getTransmitter", transmissionId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_KeystoneRouter *KeystoneRouterSession) GetTransmitter(transmissionId [32]byte) (common.Address, error) { + return _KeystoneRouter.Contract.GetTransmitter(&_KeystoneRouter.CallOpts, transmissionId) +} + +func (_KeystoneRouter *KeystoneRouterCallerSession) GetTransmitter(transmissionId [32]byte) (common.Address, error) { + return _KeystoneRouter.Contract.GetTransmitter(&_KeystoneRouter.CallOpts, transmissionId) +} + +func (_KeystoneRouter *KeystoneRouterCaller) IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) { + var out []interface{} + err := _KeystoneRouter.contract.Call(opts, &out, "isForwarder", forwarder) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_KeystoneRouter *KeystoneRouterSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneRouter.Contract.IsForwarder(&_KeystoneRouter.CallOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterCallerSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneRouter.Contract.IsForwarder(&_KeystoneRouter.CallOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _KeystoneRouter.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_KeystoneRouter *KeystoneRouterSession) Owner() (common.Address, error) { + return _KeystoneRouter.Contract.Owner(&_KeystoneRouter.CallOpts) +} + +func (_KeystoneRouter *KeystoneRouterCallerSession) Owner() (common.Address, error) { + return _KeystoneRouter.Contract.Owner(&_KeystoneRouter.CallOpts) +} + +func (_KeystoneRouter *KeystoneRouterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _KeystoneRouter.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_KeystoneRouter *KeystoneRouterSession) TypeAndVersion() (string, error) { + return _KeystoneRouter.Contract.TypeAndVersion(&_KeystoneRouter.CallOpts) +} + +func (_KeystoneRouter *KeystoneRouterCallerSession) TypeAndVersion() (string, error) { + return _KeystoneRouter.Contract.TypeAndVersion(&_KeystoneRouter.CallOpts) +} + +func (_KeystoneRouter *KeystoneRouterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneRouter.contract.Transact(opts, "acceptOwnership") +} + +func (_KeystoneRouter *KeystoneRouterSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneRouter.Contract.AcceptOwnership(&_KeystoneRouter.TransactOpts) +} + +func (_KeystoneRouter *KeystoneRouterTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneRouter.Contract.AcceptOwnership(&_KeystoneRouter.TransactOpts) +} + +func (_KeystoneRouter *KeystoneRouterTransactor) AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.contract.Transact(opts, "addForwarder", forwarder) +} + +func (_KeystoneRouter *KeystoneRouterSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.AddForwarder(&_KeystoneRouter.TransactOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterTransactorSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.AddForwarder(&_KeystoneRouter.TransactOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterTransactor) RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.contract.Transact(opts, "removeForwarder", forwarder) +} + +func (_KeystoneRouter *KeystoneRouterSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.RemoveForwarder(&_KeystoneRouter.TransactOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterTransactorSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.RemoveForwarder(&_KeystoneRouter.TransactOpts, forwarder) +} + +func (_KeystoneRouter *KeystoneRouterTransactor) Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, report []byte) (*types.Transaction, error) { + return _KeystoneRouter.contract.Transact(opts, "route", transmissionId, transmitter, receiver, metadata, report) +} + +func (_KeystoneRouter *KeystoneRouterSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, report []byte) (*types.Transaction, error) { + return _KeystoneRouter.Contract.Route(&_KeystoneRouter.TransactOpts, transmissionId, transmitter, receiver, metadata, report) +} + +func (_KeystoneRouter *KeystoneRouterTransactorSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, report []byte) (*types.Transaction, error) { + return _KeystoneRouter.Contract.Route(&_KeystoneRouter.TransactOpts, transmissionId, transmitter, receiver, metadata, report) +} + +func (_KeystoneRouter *KeystoneRouterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _KeystoneRouter.contract.Transact(opts, "transferOwnership", to) +} + +func (_KeystoneRouter *KeystoneRouterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.TransferOwnership(&_KeystoneRouter.TransactOpts, to) +} + +func (_KeystoneRouter *KeystoneRouterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneRouter.Contract.TransferOwnership(&_KeystoneRouter.TransactOpts, to) +} + +type KeystoneRouterForwarderAddedIterator struct { + Event *KeystoneRouterForwarderAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneRouterForwarderAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneRouterForwarderAdded) + 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(KeystoneRouterForwarderAdded) + 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 *KeystoneRouterForwarderAddedIterator) Error() error { + return it.fail +} + +func (it *KeystoneRouterForwarderAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneRouterForwarderAdded struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneRouter *KeystoneRouterFilterer) FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneRouterForwarderAddedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneRouter.contract.FilterLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneRouterForwarderAddedIterator{contract: _KeystoneRouter.contract, event: "ForwarderAdded", logs: logs, sub: sub}, nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneRouterForwarderAdded, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneRouter.contract.WatchLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneRouterForwarderAdded) + if err := _KeystoneRouter.contract.UnpackLog(event, "ForwarderAdded", 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 (_KeystoneRouter *KeystoneRouterFilterer) ParseForwarderAdded(log types.Log) (*KeystoneRouterForwarderAdded, error) { + event := new(KeystoneRouterForwarderAdded) + if err := _KeystoneRouter.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneRouterForwarderRemovedIterator struct { + Event *KeystoneRouterForwarderRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneRouterForwarderRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneRouterForwarderRemoved) + 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(KeystoneRouterForwarderRemoved) + 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 *KeystoneRouterForwarderRemovedIterator) Error() error { + return it.fail +} + +func (it *KeystoneRouterForwarderRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneRouterForwarderRemoved struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneRouter *KeystoneRouterFilterer) FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneRouterForwarderRemovedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneRouter.contract.FilterLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneRouterForwarderRemovedIterator{contract: _KeystoneRouter.contract, event: "ForwarderRemoved", logs: logs, sub: sub}, nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneRouterForwarderRemoved, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneRouter.contract.WatchLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneRouterForwarderRemoved) + if err := _KeystoneRouter.contract.UnpackLog(event, "ForwarderRemoved", 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 (_KeystoneRouter *KeystoneRouterFilterer) ParseForwarderRemoved(log types.Log) (*KeystoneRouterForwarderRemoved, error) { + event := new(KeystoneRouterForwarderRemoved) + if err := _KeystoneRouter.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneRouterOwnershipTransferRequestedIterator struct { + Event *KeystoneRouterOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneRouterOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneRouterOwnershipTransferRequested) + 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(KeystoneRouterOwnershipTransferRequested) + 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 *KeystoneRouterOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *KeystoneRouterOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneRouterOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneRouter *KeystoneRouterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneRouterOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneRouter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneRouterOwnershipTransferRequestedIterator{contract: _KeystoneRouter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneRouterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneRouter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneRouterOwnershipTransferRequested) + if err := _KeystoneRouter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneRouterOwnershipTransferRequested, error) { + event := new(KeystoneRouterOwnershipTransferRequested) + if err := _KeystoneRouter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneRouterOwnershipTransferredIterator struct { + Event *KeystoneRouterOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneRouterOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneRouterOwnershipTransferred) + 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(KeystoneRouterOwnershipTransferred) + 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 *KeystoneRouterOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *KeystoneRouterOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneRouterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneRouter *KeystoneRouterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneRouterOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneRouter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneRouterOwnershipTransferredIterator{contract: _KeystoneRouter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneRouterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneRouter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneRouterOwnershipTransferred) + if err := _KeystoneRouter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneRouter *KeystoneRouterFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneRouterOwnershipTransferred, error) { + event := new(KeystoneRouterOwnershipTransferred) + if err := _KeystoneRouter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_KeystoneRouter *KeystoneRouter) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _KeystoneRouter.abi.Events["ForwarderAdded"].ID: + return _KeystoneRouter.ParseForwarderAdded(log) + case _KeystoneRouter.abi.Events["ForwarderRemoved"].ID: + return _KeystoneRouter.ParseForwarderRemoved(log) + case _KeystoneRouter.abi.Events["OwnershipTransferRequested"].ID: + return _KeystoneRouter.ParseOwnershipTransferRequested(log) + case _KeystoneRouter.abi.Events["OwnershipTransferred"].ID: + return _KeystoneRouter.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (KeystoneRouterForwarderAdded) Topic() common.Hash { + return common.HexToHash("0x0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e7") +} + +func (KeystoneRouterForwarderRemoved) Topic() common.Hash { + return common.HexToHash("0xb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d38") +} + +func (KeystoneRouterOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (KeystoneRouterOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_KeystoneRouter *KeystoneRouter) Address() common.Address { + return _KeystoneRouter.address +} + +type KeystoneRouterInterface interface { + GetTransmissionState(opts *bind.CallOpts, transmissionId [32]byte) (uint8, error) + + GetTransmitter(opts *bind.CallOpts, transmissionId [32]byte) (common.Address, error) + + IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + + RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + + Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, report []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneRouterForwarderAddedIterator, error) + + WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneRouterForwarderAdded, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderAdded(log types.Log) (*KeystoneRouterForwarderAdded, error) + + FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneRouterForwarderRemovedIterator, error) + + WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneRouterForwarderRemoved, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderRemoved(log types.Log) (*KeystoneRouterForwarderRemoved, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneRouterOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneRouterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*KeystoneRouterOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneRouterOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneRouterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*KeystoneRouterOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 54f0035dcab..75b743316ac 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,5 @@ GETH_VERSION: 1.13.8 -forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin ec6e94293700d400ca7b22989d54793e905d6febce3b84054727a58c473b9cf3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 07b0d5eae760a400aaf3616201adb1ab962f92f77e05184677d94c8fc158f347 +forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin eb51d0a17d036385b840872d73022269a26ce79f3515a7f4adeefe07bdf4bdcd +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 334fdeb3953509130edeeb3db63ed0c82e3ff0f86a884f2a11368963a617812b ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 +router: ../../../contracts/solc/v0.8.19/KeystoneRouter/KeystoneRouter.abi ../../../contracts/solc/v0.8.19/KeystoneRouter/KeystoneRouter.bin d579702bbbe3c03caf2336a9d097f691e3c9033139480e97945b1e4c5f989523 diff --git a/core/gethwrappers/keystone/go_generate.go b/core/gethwrappers/keystone/go_generate.go index 679b678b8f2..e6287906443 100644 --- a/core/gethwrappers/keystone/go_generate.go +++ b/core/gethwrappers/keystone/go_generate.go @@ -5,5 +5,6 @@ package gethwrappers // Keystone //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin KeystoneForwarder forwarder +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/KeystoneRouter/KeystoneRouter.abi ../../../contracts/solc/v0.8.19/KeystoneRouter/KeystoneRouter.bin KeystoneRouter router //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin OCR3Capability ocr3_capability //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin CapabilityRegistry keystone_capability_registry diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index f4867eda69a..6b4388fccf4 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -62,11 +62,6 @@ func NewAddress() common.Address { return common.BytesToAddress(randomBytes(20)) } -func NewAddressPtr() *common.Address { - a := common.BytesToAddress(randomBytes(20)) - return &a -} - // NewPrivateKeyAndAddress returns a new private key and the corresponding address func NewPrivateKeyAndAddress(t testing.TB) (*ecdsa.PrivateKey, common.Address) { privateKey, err := crypto.GenerateKey() @@ -128,12 +123,6 @@ func WaitTimeout(t *testing.T) time.Duration { return DefaultWaitTimeout } -// AfterWaitTimeout returns a channel that will send a time value when the -// WaitTimeout is reached -func AfterWaitTimeout(t *testing.T) <-chan time.Time { - return time.After(WaitTimeout(t)) -} - // Context returns a context with the test's deadline, if available. func Context(tb testing.TB) context.Context { ctx := context.Background() diff --git a/core/scripts/go.mod b/core/scripts/go.mod index e2dcfcdba9b..22df752d056 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c @@ -274,7 +274,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 76215a34c15..83b4c29294b 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,12 +1212,12 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 h1:53zVcdDxrHG3oewhP7AWOiLtwTozcQ0/wzFTsaTBS5M= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0/go.mod h1:DUZccDEW98n+J1mhdWGO7wr/Njad9p9Fzks839JN7Rs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 h1:nsnLzpBTDAQWkfsOz/qd8BTlb1hUpaow1KmA1tPwTf4= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a h1:/QIQciKjhZy+iBB74WG4pP88O2FwS1KZtSXO5COTTgI= diff --git a/core/scripts/keystone/src/01_deploy_contracts_cmd.go b/core/scripts/keystone/src/01_deploy_contracts_cmd.go index 2ca60bdfaf2..34b8143f082 100644 --- a/core/scripts/keystone/src/01_deploy_contracts_cmd.go +++ b/core/scripts/keystone/src/01_deploy_contracts_cmd.go @@ -14,10 +14,12 @@ import ( helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/router" ) type deployedContracts struct { OCRContract common.Address `json:"ocrContract"` + RouterContract common.Address `json:"routerContract"` ForwarderContract common.Address `json:"forwarderContract"` // The block number of the transaction that set the config on the OCR3 contract. We use this to replay blocks from this point on // when we load the OCR3 job specs on the nodes. @@ -107,12 +109,15 @@ func deploy( fmt.Println("Deploying keystone ocr3 contract...") ocrContract := DeployKeystoneOCR3Capability(env) + fmt.Println("Deploying keystone router contract...") + routerContract := DeployRouter(env) fmt.Println("Deploying keystone forwarder contract...") - forwarderContract := DeployForwarder(env) + forwarderContract := DeployForwarder(env, routerContract.Address()) fmt.Println("Writing deployed contract addresses to file...") contracts := deployedContracts{ OCRContract: ocrContract.Address(), + RouterContract: routerContract.Address(), ForwarderContract: forwarderContract.Address(), } jsonBytes, err := json.Marshal(contracts) @@ -121,6 +126,11 @@ func deploy( err = os.WriteFile(DeployedContractsFilePath(), jsonBytes, 0600) PanicErr(err) + // Add forwarder to router allow list + tx, err := routerContract.AddForwarder(env.Owner, forwarderContract.Address()) + PanicErr(err) + _ = helpers.ConfirmTXMined(context.Background(), env.Ec, tx, env.ChainID) + setOCR3Config(env, ocrConfig) if skipFunding { @@ -189,8 +199,16 @@ func DeployedContractsFilePath() string { return filepath.Join(artefactsDir, deployedContractsJSON) } -func DeployForwarder(e helpers.Environment) *forwarder.KeystoneForwarder { - _, tx, contract, err := forwarder.DeployKeystoneForwarder(e.Owner, e.Ec) +func DeployRouter(e helpers.Environment) *router.KeystoneRouter { + _, tx, contract, err := router.DeployKeystoneRouter(e.Owner, e.Ec) + PanicErr(err) + helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) + + return contract +} + +func DeployForwarder(e helpers.Environment, routerAddress common.Address) *forwarder.KeystoneForwarder { + _, tx, contract, err := forwarder.DeployKeystoneForwarder(e.Owner, e.Ec, routerAddress) PanicErr(err) helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index f489cfe8c4a..f413c4959e9 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -26,9 +26,9 @@ import ( stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink/v2/common/client" - 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/chaintype" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -496,7 +496,7 @@ func TestConfig_Marshal(t *testing.T) { }, BlockBackfillDepth: ptr[uint32](100), BlockBackfillSkip: ptr(true), - ChainType: commonconfig.NewChainTypeConfig("Optimism"), + ChainType: chaintype.NewChainTypeConfig("Optimism"), FinalityDepth: ptr[uint32](42), FinalityTagEnabled: ptr[bool](false), FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"), diff --git a/core/services/feeds/models.go b/core/services/feeds/models.go index ac0568ca131..3fedc98d0f1 100644 --- a/core/services/feeds/models.go +++ b/core/services/feeds/models.go @@ -76,14 +76,17 @@ func (p *Plugins) Scan(value interface{}) error { type ChainType string const ( - ChainTypeUnknown ChainType = "UNKNOWN" - ChainTypeEVM ChainType = "EVM" + ChainTypeUnknown ChainType = "UNKNOWN" + ChainTypeEVM ChainType = "EVM" + ChainTypeStarknet ChainType = "STARKNET" ) func NewChainType(s string) (ChainType, error) { switch s { case "EVM": return ChainTypeEVM, nil + case "STARKNET": + return ChainTypeStarknet, nil default: return ChainTypeUnknown, errors.New("invalid chain type") } @@ -103,17 +106,18 @@ type FeedsManager struct { // ChainConfig defines the chain configuration for a Feeds Manager. type ChainConfig struct { - ID int64 - FeedsManagerID int64 - ChainID string - ChainType ChainType - AccountAddress string - AdminAddress string - FluxMonitorConfig FluxMonitorConfig - OCR1Config OCR1Config - OCR2Config OCR2ConfigModel - CreatedAt time.Time - UpdatedAt time.Time + ID int64 + FeedsManagerID int64 + ChainID string + ChainType ChainType + AccountAddress string + AccountAddressPublicKey null.String + AdminAddress string + FluxMonitorConfig FluxMonitorConfig + OCR1Config OCR1Config + OCR2Config OCR2ConfigModel + CreatedAt time.Time + UpdatedAt time.Time } // FluxMonitorConfig defines configuration for FluxMonitorJobs. diff --git a/core/services/feeds/models_test.go b/core/services/feeds/models_test.go index 9e3bb0f9f1c..13567281735 100644 --- a/core/services/feeds/models_test.go +++ b/core/services/feeds/models_test.go @@ -23,6 +23,11 @@ func Test_NewChainType(t *testing.T) { give: "EVM", want: ChainTypeEVM, }, + { + name: "Starknet Chain Type", + give: "STARKNET", + want: ChainTypeStarknet, + }, { name: "Invalid Chain Type", give: "", diff --git a/core/services/feeds/orm.go b/core/services/feeds/orm.go index bf77051dad7..23d7044879e 100644 --- a/core/services/feeds/orm.go +++ b/core/services/feeds/orm.go @@ -101,8 +101,8 @@ RETURNING id; // CreateChainConfig creates a new chain config. func (o *orm) CreateChainConfig(ctx context.Context, cfg ChainConfig) (id int64, err error) { stmt := ` -INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) -VALUES ($1,$2,$3,$4,$5,$6,$7,$8,NOW(),NOW()) +INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, account_address_public_key, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) +VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,NOW(),NOW()) RETURNING id; ` @@ -113,6 +113,7 @@ RETURNING id; cfg.ChainID, cfg.ChainType, cfg.AccountAddress, + cfg.AccountAddressPublicKey, cfg.AdminAddress, cfg.FluxMonitorConfig, cfg.OCR1Config, @@ -129,7 +130,7 @@ func (o *orm) CreateBatchChainConfig(ctx context.Context, cfgs []ChainConfig) (i } stmt := ` -INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) +INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, account_address_public_key, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) VALUES %s RETURNING id; ` @@ -141,16 +142,16 @@ RETURNING id; for i, cfg := range cfgs { // Generate the placeholders - pnumidx := i * 8 + pnumidx := i * 9 - lo, hi := pnumidx+1, pnumidx+8 + lo, hi := pnumidx+1, pnumidx+9 pnums := make([]any, hi-lo+1) for i := range pnums { pnums[i] = i + lo } vStrs = append(vStrs, fmt.Sprintf( - "($%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, NOW(), NOW())", pnums..., + "($%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, NOW(), NOW())", pnums..., )) // Append the values @@ -159,6 +160,7 @@ RETURNING id; cfg.ChainID, cfg.ChainType, cfg.AccountAddress, + cfg.AccountAddressPublicKey, cfg.AdminAddress, cfg.FluxMonitorConfig, cfg.OCR1Config, @@ -192,7 +194,7 @@ RETURNING id; // GetChainConfig fetches a chain config. func (o *orm) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { stmt := ` -SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at +SELECT id, feeds_manager_id, chain_id, chain_type, account_address, account_address_public_key, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs WHERE id = $1; ` @@ -207,7 +209,7 @@ WHERE id = $1; // ids. func (o *orm) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { stmt := ` -SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at +SELECT id, feeds_manager_id, chain_id, chain_type, account_address, account_address_public_key, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs WHERE feeds_manager_id = ANY($1) ` @@ -227,8 +229,9 @@ SET account_address = $1, flux_monitor_config = $3, ocr1_config = $4, ocr2_config = $5, + account_address_public_key = $6, updated_at = NOW() -WHERE id = $6 +WHERE id = $7 RETURNING id; ` @@ -239,6 +242,7 @@ RETURNING id; cfg.FluxMonitorConfig, cfg.OCR1Config, cfg.OCR2Config, + cfg.AccountAddressPublicKey, cfg.ID, ) diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index df2624319f5..c4c9ced2ce3 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -206,11 +206,12 @@ func Test_ORM_CreateChainConfig(t *testing.T) { orm = setupORM(t) fmID = createFeedsManager(t, orm) cfg1 = feeds.ChainConfig{ - FeedsManagerID: fmID, - ChainID: "1", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0001", - AdminAddress: "0x1001", + FeedsManagerID: fmID, + ChainID: "1", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0001", + AdminAddress: "0x1001", + AccountAddressPublicKey: null.StringFrom("0x0002"), FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: true, }, @@ -235,14 +236,15 @@ func Test_ORM_CreateChainConfig(t *testing.T) { require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ - "feedsManagerID": cfg1.FeedsManagerID, - "chainID": cfg1.ChainID, - "chainType": cfg1.ChainType, - "accountAddress": cfg1.AccountAddress, - "adminAddress": cfg1.AdminAddress, - "fluxMonitorConfig": cfg1.FluxMonitorConfig, - "ocrConfig": cfg1.OCR1Config, - "ocr2Config": cfg1.OCR2Config, + "feedsManagerID": cfg1.FeedsManagerID, + "chainID": cfg1.ChainID, + "chainType": cfg1.ChainType, + "accountAddress": cfg1.AccountAddress, + "accountAddressPublicKey": cfg1.AccountAddressPublicKey, + "adminAddress": cfg1.AdminAddress, + "fluxMonitorConfig": cfg1.FluxMonitorConfig, + "ocrConfig": cfg1.OCR1Config, + "ocr2Config": cfg1.OCR2Config, }, *actual) } @@ -254,11 +256,12 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { orm = setupORM(t) fmID = createFeedsManager(t, orm) cfg1 = feeds.ChainConfig{ - FeedsManagerID: fmID, - ChainID: "1", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0001", - AdminAddress: "0x1001", + FeedsManagerID: fmID, + ChainID: "1", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0001", + AccountAddressPublicKey: null.StringFrom("0x0002"), + AdminAddress: "0x1001", } cfg2 = feeds.ChainConfig{ FeedsManagerID: fmID, @@ -278,14 +281,15 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ - "feedsManagerID": cfg1.FeedsManagerID, - "chainID": cfg1.ChainID, - "chainType": cfg1.ChainType, - "accountAddress": cfg1.AccountAddress, - "adminAddress": cfg1.AdminAddress, - "fluxMonitorConfig": cfg1.FluxMonitorConfig, - "ocrConfig": cfg1.OCR1Config, - "ocr2Config": cfg1.OCR2Config, + "feedsManagerID": cfg1.FeedsManagerID, + "chainID": cfg1.ChainID, + "chainType": cfg1.ChainType, + "accountAddress": cfg1.AccountAddress, + "accountAddressPublicKey": cfg1.AccountAddressPublicKey, + "adminAddress": cfg1.AdminAddress, + "fluxMonitorConfig": cfg1.FluxMonitorConfig, + "ocrConfig": cfg1.OCR1Config, + "ocr2Config": cfg1.OCR2Config, }, *actual) actual, err = orm.GetChainConfig(ctx, ids[1]) @@ -346,11 +350,12 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { orm = setupORM(t) fmID = createFeedsManager(t, orm) cfg1 = feeds.ChainConfig{ - FeedsManagerID: fmID, - ChainID: "1", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0001", - AdminAddress: "0x1001", + FeedsManagerID: fmID, + ChainID: "1", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0001", + AccountAddressPublicKey: null.StringFrom("0x0002"), + AdminAddress: "0x1001", FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: true, }, @@ -376,14 +381,15 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { require.Len(t, actual, 1) assertChainConfigEqual(t, map[string]interface{}{ - "feedsManagerID": cfg1.FeedsManagerID, - "chainID": cfg1.ChainID, - "chainType": cfg1.ChainType, - "accountAddress": cfg1.AccountAddress, - "adminAddress": cfg1.AdminAddress, - "fluxMonitorConfig": cfg1.FluxMonitorConfig, - "ocrConfig": cfg1.OCR1Config, - "ocr2Config": cfg1.OCR2Config, + "feedsManagerID": cfg1.FeedsManagerID, + "chainID": cfg1.ChainID, + "chainType": cfg1.ChainType, + "accountAddress": cfg1.AccountAddress, + "accountAddressPublicKey": cfg1.AccountAddressPublicKey, + "adminAddress": cfg1.AdminAddress, + "fluxMonitorConfig": cfg1.FluxMonitorConfig, + "ocrConfig": cfg1.OCR1Config, + "ocr2Config": cfg1.OCR2Config, }, actual[0]) } @@ -395,19 +401,21 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { orm = setupORM(t) fmID = createFeedsManager(t, orm) cfg1 = feeds.ChainConfig{ - FeedsManagerID: fmID, - ChainID: "1", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0001", - AdminAddress: "0x1001", - FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, - OCR1Config: feeds.OCR1Config{Enabled: false}, - OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, + FeedsManagerID: fmID, + ChainID: "1", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0001", + AccountAddressPublicKey: null.NewString("", false), + AdminAddress: "0x1001", + FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, + OCR1Config: feeds.OCR1Config{Enabled: false}, + OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, } updateCfg = feeds.ChainConfig{ - AccountAddress: "0x0002", - AdminAddress: "0x1002", - FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: true}, + AccountAddress: "0x0002", + AdminAddress: "0x1002", + AccountAddressPublicKey: null.StringFrom("0x0002"), + FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: true}, OCR1Config: feeds.OCR1Config{ Enabled: true, IsBootstrap: false, @@ -434,14 +442,15 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ - "feedsManagerID": cfg1.FeedsManagerID, - "chainID": cfg1.ChainID, - "chainType": cfg1.ChainType, - "accountAddress": updateCfg.AccountAddress, - "adminAddress": updateCfg.AdminAddress, - "fluxMonitorConfig": updateCfg.FluxMonitorConfig, - "ocrConfig": updateCfg.OCR1Config, - "ocr2Config": updateCfg.OCR2Config, + "feedsManagerID": cfg1.FeedsManagerID, + "chainID": cfg1.ChainID, + "chainType": cfg1.ChainType, + "accountAddress": updateCfg.AccountAddress, + "accountAddressPublicKey": updateCfg.AccountAddressPublicKey, + "adminAddress": updateCfg.AdminAddress, + "fluxMonitorConfig": updateCfg.FluxMonitorConfig, + "ocrConfig": updateCfg.OCR1Config, + "ocr2Config": updateCfg.OCR2Config, }, *actual) } diff --git a/core/services/feeds/proto/feeds_manager.pb.go b/core/services/feeds/proto/feeds_manager.pb.go index a73b4a0cd29..89f351a4270 100644 --- a/core/services/feeds/proto/feeds_manager.pb.go +++ b/core/services/feeds/proto/feeds_manager.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v3.21.7 +// protoc-gen-go v1.34.1 +// protoc v4.25.3 // source: pkg/noderpc/proto/feeds_manager.proto package proto @@ -79,6 +79,8 @@ const ( ChainType_CHAIN_TYPE_UNSPECIFIED ChainType = 0 ChainType_CHAIN_TYPE_EVM ChainType = 1 ChainType_CHAIN_TYPE_SOLANA ChainType = 2 + ChainType_CHAIN_TYPE_ZKSYNC ChainType = 3 + ChainType_CHAIN_TYPE_STARKNET ChainType = 4 ) // Enum value maps for ChainType. @@ -87,11 +89,15 @@ var ( 0: "CHAIN_TYPE_UNSPECIFIED", 1: "CHAIN_TYPE_EVM", 2: "CHAIN_TYPE_SOLANA", + 3: "CHAIN_TYPE_ZKSYNC", + 4: "CHAIN_TYPE_STARKNET", } ChainType_value = map[string]int32{ "CHAIN_TYPE_UNSPECIFIED": 0, "CHAIN_TYPE_EVM": 1, "CHAIN_TYPE_SOLANA": 2, + "CHAIN_TYPE_ZKSYNC": 3, + "CHAIN_TYPE_STARKNET": 4, } ) @@ -470,12 +476,13 @@ type ChainConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Chain *Chain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` - AccountAddress string `protobuf:"bytes,2,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` - AdminAddress string `protobuf:"bytes,3,opt,name=admin_address,json=adminAddress,proto3" json:"admin_address,omitempty"` - FluxMonitorConfig *FluxMonitorConfig `protobuf:"bytes,4,opt,name=flux_monitor_config,json=fluxMonitorConfig,proto3" json:"flux_monitor_config,omitempty"` - Ocr1Config *OCR1Config `protobuf:"bytes,5,opt,name=ocr1_config,json=ocr1Config,proto3" json:"ocr1_config,omitempty"` - Ocr2Config *OCR2Config `protobuf:"bytes,6,opt,name=ocr2_config,json=ocr2Config,proto3" json:"ocr2_config,omitempty"` + Chain *Chain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + AccountAddress string `protobuf:"bytes,2,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` + AdminAddress string `protobuf:"bytes,3,opt,name=admin_address,json=adminAddress,proto3" json:"admin_address,omitempty"` + FluxMonitorConfig *FluxMonitorConfig `protobuf:"bytes,4,opt,name=flux_monitor_config,json=fluxMonitorConfig,proto3" json:"flux_monitor_config,omitempty"` + Ocr1Config *OCR1Config `protobuf:"bytes,5,opt,name=ocr1_config,json=ocr1Config,proto3" json:"ocr1_config,omitempty"` + Ocr2Config *OCR2Config `protobuf:"bytes,6,opt,name=ocr2_config,json=ocr2Config,proto3" json:"ocr2_config,omitempty"` + AccountAddressPublicKey *string `protobuf:"bytes,7,opt,name=account_address_public_key,json=accountAddressPublicKey,proto3,oneof" json:"account_address_public_key,omitempty"` } func (x *ChainConfig) Reset() { @@ -552,6 +559,13 @@ func (x *ChainConfig) GetOcr2Config() *OCR2Config { return nil } +func (x *ChainConfig) GetAccountAddressPublicKey() string { + if x != nil && x.AccountAddressPublicKey != nil { + return *x.AccountAddressPublicKey + } + return "" +} + type UpdateNodeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1800,7 +1814,7 @@ var file_pkg_noderpc_proto_feeds_manager_proto_rawDesc = []byte{ 0x63, 0x75, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x0b, 0x43, + 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x8a, 0x03, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x27, 0x0a, 0x0f, @@ -1819,123 +1833,132 @@ var file_pkg_noderpc_proto_feeds_manager_proto_rawDesc = []byte{ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x0b, 0x6f, 0x63, 0x72, 0x32, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x6f, 0x63, 0x72, 0x32, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x09, - 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, - 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6a, - 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, - 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, - 0x70, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, 0x42, 0x6f, - 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x13, 0x62, - 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, - 0x72, 0x61, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x03, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, - 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, - 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, - 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x15, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x0a, 0x12, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, - 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, - 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x43, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x71, - 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x22, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0x22, 0x0a, 0x10, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x1a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x17, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, + 0x09, 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, + 0x32, 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, + 0x6a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, + 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, 0x42, + 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x13, + 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, + 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, + 0x74, 0x72, 0x61, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x03, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x22, + 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x66, 0x6d, 0x2e, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x42, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x15, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x0a, 0x12, 0x52, 0x65, 0x6a, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x52, + 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x43, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x71, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x2a, 0x63, 0x0a, 0x07, 0x4a, 0x6f, 0x62, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, - 0x0a, 0x15, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x55, 0x58, 0x5f, - 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x4f, 0x42, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4a, - 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x32, 0x10, 0x03, 0x2a, 0x52, - 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x43, - 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x48, 0x41, 0x49, 0x4e, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x56, 0x4d, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, - 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4f, 0x4c, 0x41, 0x4e, 0x41, - 0x10, 0x02, 0x32, 0xd8, 0x02, 0x0a, 0x0c, 0x46, 0x65, 0x65, 0x64, 0x73, 0x4d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, - 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x66, - 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, - 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x6a, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, - 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc4, 0x01, - 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3d, 0x0a, - 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x16, 0x2e, 0x63, 0x66, - 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x2e, 0x63, 0x66, 0x6d, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x52, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, - 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 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, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x22, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x22, 0x0a, 0x10, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x2a, 0x63, 0x0a, 0x07, 0x4a, 0x6f, + 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x19, 0x0a, 0x15, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x55, 0x58, + 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x4f, + 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, + 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x32, 0x10, 0x03, 0x2a, + 0x82, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, + 0x16, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x48, 0x41, + 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x56, 0x4d, 0x10, 0x01, 0x12, 0x15, 0x0a, + 0x11, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4f, 0x4c, 0x41, + 0x4e, 0x41, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x5a, 0x4b, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x43, + 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x4b, 0x4e, + 0x45, 0x54, 0x10, 0x04, 0x32, 0xd8, 0x02, 0x0a, 0x0c, 0x46, 0x65, 0x65, 0x64, 0x73, 0x4d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, + 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x52, 0x65, 0x6a, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, + 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x18, 0x2e, 0x63, 0x66, 0x6d, + 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, + 0xc4, 0x01, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x3d, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x16, 0x2e, + 0x63, 0x66, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, + 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x2e, 0x63, 0x66, + 0x6d, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, + 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x52, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 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, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x72, 0x70, 0x63, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2354,6 +2377,7 @@ func file_pkg_noderpc_proto_feeds_manager_proto_init() { } } file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[5].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 701cff03c81..4add9ff320d 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -579,6 +579,8 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, ) var id int64 + // we need the specID to auto-approve workflow specs + var specID int64 err = s.orm.Transact(ctx, func(tx ORM) error { var txerr error @@ -598,7 +600,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, } // Create the spec version - _, txerr = tx.CreateSpec(ctx, JobProposalSpec{ + specID, txerr = tx.CreateSpec(ctx, JobProposalSpec{ Definition: args.Spec, Status: SpecStatusPending, Version: args.Version, @@ -616,7 +618,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, // auto approve workflow specs if isWFSpec(logger, args.Spec) { promWorkflowRequests.Inc() - err = s.ApproveSpec(ctx, id, true) + err = s.ApproveSpec(ctx, specID, true) if err != nil { promWorkflowFailures.Inc() logger.Errorw("Failed to auto approve workflow spec", "id", id, "err", err) @@ -801,7 +803,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } } case job.Workflow: - existingJobID, txerr = findExistingWorkflowJob(ctx, *j.WorkflowSpec, tx.jobORM) + existingJobID, txerr = tx.jobORM.FindJobIDByWorkflow(ctx, *j.WorkflowSpec) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -1106,11 +1108,6 @@ func (s *service) observeJobProposalCounts(ctx context.Context) error { return nil } -// TODO KS-205 implement this. Need to figure out how exactly how we want to handle this. -func findExistingWorkflowJob(ctx context.Context, wfSpec job.WorkflowSpec, tx job.ORM) (int32, error) { - return 0, nil -} - // findExistingJobForOCR2 looks for existing job for OCR2 func findExistingJobForOCR2(ctx context.Context, j *job.Job, tx job.ORM) (int32, error) { var contractID string @@ -1210,7 +1207,7 @@ func (s *service) newChainConfigMsg(cfg ChainConfig) (*pb.ChainConfig, error) { return nil, err } - return &pb.ChainConfig{ + pbChainConfig := pb.ChainConfig{ Chain: &pb.Chain{ Id: cfg.ChainID, Type: pb.ChainType_CHAIN_TYPE_EVM, @@ -1220,7 +1217,13 @@ func (s *service) newChainConfigMsg(cfg ChainConfig) (*pb.ChainConfig, error) { FluxMonitorConfig: s.newFluxMonitorConfigMsg(cfg.FluxMonitorConfig), Ocr1Config: ocr1Cfg, Ocr2Config: ocr2Cfg, - }, nil + } + + if cfg.AccountAddressPublicKey.Valid { + pbChainConfig.AccountAddressPublicKey = &cfg.AccountAddressPublicKey.String + } + + return &pbChainConfig, nil } // newFluxMonitorConfigMsg generates a FMConfig protobuf message. Flux Monitor does not diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index 09c710fff9e..d45bc358e1d 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -367,11 +367,12 @@ func Test_Service_CreateChainConfig(t *testing.T) { Version: "1.0.0", } cfg = feeds.ChainConfig{ - FeedsManagerID: mgr.ID, - ChainID: "42", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0000000000000000000000000000000000000000", - AdminAddress: "0x0000000000000000000000000000000000000001", + FeedsManagerID: mgr.ID, + ChainID: "42", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0000000000000000000000000000000000000000", + AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), + AdminAddress: "0x0000000000000000000000000000000000000001", FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: true, }, @@ -398,11 +399,12 @@ func Test_Service_CreateChainConfig(t *testing.T) { Id: cfg.ChainID, Type: proto.ChainType_CHAIN_TYPE_EVM, }, - AccountAddress: cfg.AccountAddress, - AdminAddress: cfg.AdminAddress, - FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, - Ocr1Config: &proto.OCR1Config{Enabled: false}, - Ocr2Config: &proto.OCR2Config{Enabled: false}, + AccountAddress: cfg.AccountAddress, + AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, + AdminAddress: cfg.AdminAddress, + FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, + Ocr1Config: &proto.OCR1Config{Enabled: false}, + Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, }).Return(&proto.UpdateNodeResponse{}, nil) @@ -489,14 +491,15 @@ func Test_Service_UpdateChainConfig(t *testing.T) { Version: "1.0.0", } cfg = feeds.ChainConfig{ - FeedsManagerID: mgr.ID, - ChainID: "42", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0000000000000000000000000000000000000000", - AdminAddress: "0x0000000000000000000000000000000000000001", - FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, - OCR1Config: feeds.OCR1Config{Enabled: false}, - OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, + FeedsManagerID: mgr.ID, + ChainID: "42", + ChainType: feeds.ChainTypeEVM, + AccountAddress: "0x0000000000000000000000000000000000000000", + AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), + AdminAddress: "0x0000000000000000000000000000000000000001", + FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, + OCR1Config: feeds.OCR1Config{Enabled: false}, + OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, } svc = setupTestService(t) @@ -514,11 +517,12 @@ func Test_Service_UpdateChainConfig(t *testing.T) { Id: cfg.ChainID, Type: proto.ChainType_CHAIN_TYPE_EVM, }, - AccountAddress: cfg.AccountAddress, - AdminAddress: cfg.AdminAddress, - FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: false}, - Ocr1Config: &proto.OCR1Config{Enabled: false}, - Ocr2Config: &proto.OCR2Config{Enabled: false}, + AccountAddress: cfg.AccountAddress, + AdminAddress: cfg.AdminAddress, + AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, + FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: false}, + Ocr1Config: &proto.OCR1Config{Enabled: false}, + Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, }).Return(&proto.UpdateNodeResponse{}, nil) @@ -653,31 +657,37 @@ func Test_Service_ProposeJob(t *testing.T) { wfName = "myworkflow" // len 10 specYaml = ` triggers: - - id: "a-trigger" + - id: "a-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" ref: "an-action" + config: {} inputs: trigger_output: $(trigger.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" ref: "a-consensus" + config: {} inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) ` - wfSpec = testspecs.GenerateWorkflowSpec(wfID, wfOwner, wfName, specYaml).Toml() - proposalIDWF = int64(11) - remoteUUIDWF = uuid.New() - argsWF = &feeds.ProposeJobArgs{ + wfSpec = testspecs.GenerateWorkflowSpec(wfID, wfOwner, wfName, specYaml).Toml() + proposalIDWF = int64(11) + jobProposalSpecIdWF = int64(101) + jobIDWF = int32(1001) + remoteUUIDWF = uuid.New() + argsWF = &feeds.ProposeJobArgs{ FeedsManagerID: 1, RemoteUUID: remoteUUIDWF, Spec: wfSpec, @@ -689,12 +699,26 @@ targets: RemoteUUID: remoteUUIDWF, Status: feeds.JobProposalStatusPending, } + acceptedjpWF = feeds.JobProposal{ + ID: 13, + FeedsManagerID: 1, + Name: null.StringFrom("test-spec"), + RemoteUUID: remoteUUIDWF, + Status: feeds.JobProposalStatusPending, + } proposalSpecWF = feeds.JobProposalSpec{ Definition: wfSpec, Status: feeds.SpecStatusPending, Version: 1, JobProposalID: proposalIDWF, } + autoApprovableProposalSpecWF = feeds.JobProposalSpec{ + ID: jobProposalSpecIdWF, + Definition: wfSpec, + Status: feeds.SpecStatusPending, + Version: 1, + JobProposalID: proposalIDWF, + } ) testCases := []struct { @@ -705,11 +729,11 @@ targets: wantErr string }{ { - name: "Auto approve WF spec", + name: "Auto approve new WF spec", before: func(svc *TestService) { svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, argsWF.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) svc.orm.On("UpsertJobProposal", mock.Anything, &jpWF).Return(proposalIDWF, nil) - svc.orm.On("CreateSpec", mock.Anything, proposalSpecWF).Return(int64(100), nil) + svc.orm.On("CreateSpec", mock.Anything, proposalSpecWF).Return(jobProposalSpecIdWF, nil) svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) transactCall.Run(func(args mock.Arguments) { @@ -718,13 +742,14 @@ targets: }) // Auto approve is really a call to ApproveJobProposal and so we have to mock that as well svc.connMgr.On("GetClient", argsWF.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(mock.Anything, proposalIDWF).Return(&proposalSpecWF, nil) - svc.orm.EXPECT().GetJobProposal(mock.Anything, proposalSpecWF.JobProposalID).Return(&jpWF, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, jobProposalSpecIdWF).Return(&autoApprovableProposalSpecWF, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, autoApprovableProposalSpecWF.JobProposalID).Return(&acceptedjpWF, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, mock.Anything).Return(job.Job{}, sql.ErrNoRows) // TODO fix the external job id in wf spec generation + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, mock.Anything).Return(job.Job{}, sql.ErrNoRows) svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + svc.jobORM.On("FindJobIDByWorkflow", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) // no existing job svc.spawner. On("CreateJob", mock.Anything, @@ -737,7 +762,7 @@ targets: Return(nil) svc.orm.On("ApproveSpec", mock.Anything, - proposalSpecWF.JobProposalID, + jobProposalSpecIdWF, mock.IsType(uuid.UUID{}), ).Return(nil) svc.fmsClient.On("ApprovedJob", @@ -751,13 +776,65 @@ targets: args: argsWF, wantID: proposalIDWF, }, + + { + name: "Auto approve existing WF spec found by FindJobIDByWorkflow", + before: func(svc *TestService) { + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, argsWF.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpWF).Return(proposalIDWF, nil) + svc.orm.On("CreateSpec", mock.Anything, proposalSpecWF).Return(jobProposalSpecIdWF, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) + // Auto approve is really a call to ApproveJobProposal and so we have to mock that as well + svc.connMgr.On("GetClient", argsWF.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, jobProposalSpecIdWF).Return(&autoApprovableProposalSpecWF, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, autoApprovableProposalSpecWF.JobProposalID).Return(&acceptedjpWF, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, mock.Anything).Return(job.Job{}, sql.ErrNoRows) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + svc.jobORM.On("FindJobIDByWorkflow", mock.Anything, mock.Anything).Return(jobIDWF, sql.ErrNoRows) + svc.orm.On("GetApprovedSpec", mock.Anything, acceptedjpWF.ID).Return(&autoApprovableProposalSpecWF, nil) + svc.orm.On("CancelSpec", mock.Anything, autoApprovableProposalSpecWF.ID).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, jobIDWF).Return(nil) + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.WorkflowSpec.WorkflowOwner == wfOwner + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + jobProposalSpecIdWF, + mock.IsType(uuid.UUID{}), + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jpWF.RemoteUUID.String(), + Version: int64(proposalSpecWF.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + }, + args: argsWF, + wantID: proposalIDWF, + }, + { - name: "Auto approve WF spec: error creating job", + name: "Auto approve WF spec: error creating job for new spec", before: func(svc *TestService) { svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, argsWF.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) svc.orm.On("UpsertJobProposal", mock.Anything, &jpWF).Return(proposalIDWF, nil) - svc.orm.On("CreateSpec", mock.Anything, proposalSpecWF).Return(int64(100), nil) - // svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CreateSpec", mock.Anything, proposalSpecWF).Return(jobProposalSpecIdWF, nil) transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) transactCall.Run(func(args mock.Arguments) { fn := args[1].(func(orm feeds.ORM) error) @@ -765,13 +842,14 @@ targets: }) // Auto approve is really a call to ApproveJobProposal and so we have to mock that as well svc.connMgr.On("GetClient", argsWF.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(mock.Anything, proposalIDWF).Return(&proposalSpecWF, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, jobProposalSpecIdWF).Return(&proposalSpecWF, nil) svc.orm.EXPECT().GetJobProposal(mock.Anything, proposalSpecWF.JobProposalID).Return(&jpWF, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, mock.Anything).Return(job.Job{}, sql.ErrNoRows) // TODO fix the external job id in wf spec generation + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, mock.Anything).Return(job.Job{}, sql.ErrNoRows) svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + svc.jobORM.On("FindJobIDByWorkflow", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) // no existing job svc.spawner. On("CreateJob", mock.Anything, diff --git a/core/services/job/models.go b/core/services/job/models.go index e1f1e652f53..5c7795a32f6 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -878,6 +878,7 @@ func (w *WorkflowSpec) Validate() error { return fmt.Errorf("%w: incorrect length for id %s: expected %d, got %d", ErrInvalidWorkflowID, w.WorkflowID, workflowIDLen, len(w.WorkflowID)) } + w.WorkflowOwner = strings.TrimPrefix(w.WorkflowOwner, "0x") _, err := hex.DecodeString(w.WorkflowOwner) if err != nil { return fmt.Errorf("%w: expected hex encoding got %s: %w", ErrInvalidWorkflowOwner, w.WorkflowOwner, err) diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index 39ac0f83c1f..a5dc12bcbc6 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -294,7 +294,14 @@ func TestWorkflowSpec_Validate(t *testing.T) { WorkflowName: "ten bytes!", }, }, - + { + name: "valid 0x prefix hex owner", + fields: fields{ + WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", + WorkflowOwner: "0x00000000000000000000000000000000000000ff", + WorkflowName: "ten bytes!", + }, + }, { name: "not hex owner", fields: fields{ @@ -304,7 +311,6 @@ func TestWorkflowSpec_Validate(t *testing.T) { }, expectedErr: ErrInvalidWorkflowOwner, }, - { name: "not len 40 owner", fields: fields{ @@ -314,7 +320,6 @@ func TestWorkflowSpec_Validate(t *testing.T) { }, expectedErr: ErrInvalidWorkflowOwner, }, - { name: "not len 10 name", fields: fields{ diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index 34852bbe74b..8da17908d11 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -22,8 +22,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink/v2/common/config" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" 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" @@ -217,7 +217,7 @@ func (t *OCRContractTracker) processLogs() { select { case <-t.configsMB.Notify(): // NOTE: libocr could take an arbitrary amount of time to process a - // new config. To avoid blocking the log broadcaster, we use this + // new chaintype. To avoid blocking the log broadcaster, we use this // background thread to deliver them and a mailbox as the buffer. for { cc, exists := t.configsMB.Retrieve() @@ -395,12 +395,12 @@ func (t *OCRContractTracker) ConfigFromLogs(ctx context.Context, changedInBlock // LatestBlockHeight queries the eth node for the most recent header func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight uint64, err error) { switch t.cfg.ChainType() { - case config.ChainMetis: + case chaintype.ChainMetis: // We skip confirmation checking anyway on these L2s so there's no need to // 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.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXLayer, config.ChainZkEvm, config.ChainZkSync: + case "", chaintype.ChainArbitrum, chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainKroma, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync: // continue } latestBlockHeight := t.getLatestBlockHeight() diff --git a/core/services/ocr/validate.go b/core/services/ocr/validate.go index a31994f891a..1a93dfb8b5b 100644 --- a/core/services/ocr/validate.go +++ b/core/services/ocr/validate.go @@ -10,8 +10,8 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting" - "github.com/smartcontractkit/chainlink/v2/common/config" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -25,7 +25,7 @@ type GeneralConfig interface { } type ValidationConfig interface { - ChainType() config.ChainType + ChainType() chaintype.ChainType } type OCRValidationConfig interface { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go index 5294530140b..ef0089921ce 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go @@ -188,6 +188,9 @@ func (r *EvmRegistry) checkUpkeeps(ctx context.Context, payloads []ocr2keepers.U indices := map[int]int{} for i, p := range payloads { + if ctx.Err() != nil { + return nil, context.Cause(ctx) + } block, checkHash, upkeepId := r.getBlockAndUpkeepId(p.UpkeepID, p.Trigger) state, retryable := r.verifyCheckBlock(ctx, block, upkeepId, checkHash) if state != encoding.NoPipelineError { diff --git a/core/services/ocrcommon/block_translator.go b/core/services/ocrcommon/block_translator.go index 7bce661e692..d7ceffc5ea7 100644 --- a/core/services/ocrcommon/block_translator.go +++ b/core/services/ocrcommon/block_translator.go @@ -4,8 +4,8 @@ import ( "context" "math/big" - "github.com/smartcontractkit/chainlink/v2/common/config" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -19,9 +19,9 @@ type BlockTranslator interface { // NewBlockTranslator returns the block translator for the given chain func NewBlockTranslator(cfg Config, client evmclient.Client, lggr logger.Logger) BlockTranslator { switch cfg.ChainType() { - case config.ChainArbitrum: + case chaintype.ChainArbitrum: return NewArbitrumBlockTranslator(client, lggr) - case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXLayer, config.ChainZkEvm, config.ChainZkSync: + case "", chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainKroma, chaintype.ChainMetis, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync: fallthrough default: return &l1BlockTranslator{} diff --git a/core/services/ocrcommon/config.go b/core/services/ocrcommon/config.go index 2fcc877610c..b8572ee7e78 100644 --- a/core/services/ocrcommon/config.go +++ b/core/services/ocrcommon/config.go @@ -5,11 +5,11 @@ import ( "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) type Config interface { - ChainType() config.ChainType + ChainType() chaintype.ChainType } func ParseBootstrapPeers(peers []string) (bootstrapPeers []commontypes.BootstrapperLocator, err error) { diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 172e4c1423c..249c3e257fb 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -17,10 +17,10 @@ import ( func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, lggr logger.Logger) (*targets.WriteTarget, error) { // generate ID based on chain selector - name := fmt.Sprintf("write_%v", chain.ID()) + id := fmt.Sprintf("write_%v@1.0.0", chain.ID()) chainName, err := chainselectors.NameFromChainId(chain.ID().Uint64()) if err == nil { - name = fmt.Sprintf("write_%v", chainName) + id = fmt.Sprintf("write_%v@1.0.0", chainName) } // EVM-specific init @@ -74,5 +74,5 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, err } - return targets.NewWriteTarget(lggr, name, cr, cw, config.ForwarderAddress().String()), nil + return targets.NewWriteTarget(lggr, id, cr, cw, config.ForwarderAddress().String()), nil } diff --git a/core/services/workflows/delegate_test.go b/core/services/workflows/delegate_test.go index f7e106796e6..dde01e50665 100644 --- a/core/services/workflows/delegate_test.go +++ b/core/services/workflows/delegate_test.go @@ -6,69 +6,174 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" + "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" ) func TestDelegate_JobSpecValidator(t *testing.T) { t.Parallel() - + validName := "ten bytes!" var tt = []struct { - name string - toml string - valid bool + name string + workflowTomlFn func() string + valid bool }{ { - "valid spec", - ` -type = "workflow" -schemaVersion = 1 -workflowId = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" -workflowOwner = "00000000000000000000000000000000000000aa" -workflowName = "ten bytes!" -`, - true, + "not a hex owner", + func() string { + workflowId := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + workflowOwner := "00000000000000000000000000000000000000aZ" + return testspecs.GenerateWorkflowSpec(workflowId, workflowOwner, "1234567890", "").Toml() + }, + false, }, { - "parse error", - ` -invalid syntax{{{{ -`, + "missing workflow field", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + return testspecs.GenerateWorkflowSpec(id, owner, validName, "").Toml() + }, false, }, + { - "invalid job type", - ` -type = "work flows" -schemaVersion = 1 -`, + "null workflow", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + return testspecs.GenerateWorkflowSpec(id, owner, validName, "{}").Toml() + }, false, }, + { - "invalid name length", - ` -type = "workflow" -schemaVersion = 1 -workflowId = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" -workflowOwner = "00000000000000000000000000000000000000aa" -workflowName = "not ten bytes" -`, + "missing name", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + wf := ` +triggers: [] +consensus: [] +targets: [] +` + return testspecs.GenerateWorkflowSpec(id, owner, "", wf).Toml() + }, false, }, + { - "not a hex owner", - ` -type = "workflow" + "minimal passing workflow", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + wf := ` +triggers: [] +consensus: [] +targets: [] +` + return testspecs.GenerateWorkflowSpec(id, owner, validName, wf).Toml() + }, + true, + }, + + { + "name too long", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + wf := ` +triggers: [] +consensus: [] +targets: [] +` + return testspecs.GenerateWorkflowSpec(id, owner, validName+"1", wf).Toml() + }, + false, + }, + + // Taken from jobs controller test, as we want to fail early without a db / slow test dependency + { + "valid full spec", + func() string { + id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + owner := "00000000000000000000000000000000000000aa" + workflow := ` +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedIds: + - "0x1111111111111111111100000000000000000000000000000000000000000000" + - "0x2222222222222222222200000000000000000000000000000000000000000000" + - "0x3333333333333333333300000000000000000000000000000000000000000000" + +consensus: + - id: "offchain_reporting@2.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_polygon-testnet-mumbai@3.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" + params: ["$(report)"] + abi: "receive(report bytes)" + - id: "write_ethereum-testnet-sepolia@4.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x54e220867af6683aE6DcBF535B4f952cB5116510" + params: ["$(report)"] + abi: "receive(report bytes)" +` + return testspecs.GenerateWorkflowSpec(id, owner, validName, workflow).Toml() + }, + true, + }, + + { + "parse error", + func() string { + return ` +invalid syntax{{{{ +` + }, + false, + }, + + { + "invalid job type", + func() string { + return ` +type = "work flows" schemaVersion = 1 -workflowId = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" -workflowOwner = "00000000000000000000000000000000000000aZ" -workflowName = "0123456789" -`, +` + }, false, }, } for _, tc := range tt { tc := tc t.Run(tc.name, func(t *testing.T) { - _, err := workflows.ValidatedWorkflowSpec(tc.toml) + _, err := workflows.ValidatedWorkflowSpec(tc.workflowTomlFn()) if tc.valid { require.NoError(t, err) } else { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 9fb2a6beacd..47638f71434 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -4,6 +4,7 @@ import ( "context" "crypto/sha256" "encoding/hex" + "errors" "fmt" "sync" "time" @@ -475,7 +476,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow } switch step.Status { - case store.StatusCompleted, store.StatusErrored: + case store.StatusCompleted, store.StatusErrored, store.StatusCompletedEarlyExit: default: workflowCompleted = false } @@ -493,6 +494,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow // We haven't completed the workflow, but should we continue? // If we've been executing for too long, let's time the workflow out and stop here. if state.CreatedAt != nil && e.clock.Since(*state.CreatedAt) > e.maxExecutionDuration { + e.logger.Infow("execution timed out", "executionID", state.ExecutionID) return e.finishExecution(ctx, state.ExecutionID, store.StatusTimeout) } @@ -501,7 +503,18 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow for _, sd := range stepDependents { e.queueIfReady(state, sd) } + case store.StatusCompletedEarlyExit: + e.logger.Infow("execution terminated early", "executionID", state.ExecutionID) + // NOTE: even though this marks the workflow as completed, any branches of the DAG + // that don't depend on the step that signaled for an early exit will still complete. + // This is to ensure that any side effects are executed consistently, since otherwise + // the async nature of the workflow engine would provide no guarantees. + err := e.finishExecution(ctx, state.ExecutionID, store.StatusCompletedEarlyExit) + if err != nil { + return err + } case store.StatusErrored: + e.logger.Infow("execution errored", "executionID", state.ExecutionID) err := e.finishExecution(ctx, state.ExecutionID, store.StatusErrored) if err != nil { return err @@ -568,16 +581,22 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { } inputs, outputs, err := e.executeStep(ctx, l, msg) - if err != nil { + var stepStatus string + switch { + case errors.Is(err, capabilities.ErrStopExecution): + l.Infow("step executed successfully with a termination") + stepStatus = store.StatusCompletedEarlyExit + case err != nil: l.Errorf("error executing step request: %s", err) - stepState.Outputs.Err = err - stepState.Status = store.StatusErrored - } else { + stepStatus = store.StatusErrored + default: l.Infow("step executed successfully", "outputs", outputs) - stepState.Outputs.Value = outputs - stepState.Status = store.StatusCompleted + stepStatus = store.StatusCompleted } + stepState.Status = stepStatus + stepState.Outputs.Value = outputs + stepState.Outputs.Err = err stepState.Inputs = inputs // Let's try and emit the stepUpdate. diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index a25568953a8..ddb08c24316 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -24,7 +24,7 @@ import ( const hardcodedWorkflow = ` triggers: - - id: "mercury-trigger" + - id: "mercury-trigger@1.0.0" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -32,7 +32,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - id: "offchain_reporting" + - id: "offchain_reporting@1.0.0" ref: "evm_median" inputs: observations: @@ -54,14 +54,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - id: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai@1.0.0" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - id: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia@1.0.0" inputs: report: "$(evm_median.outputs.report)" config: @@ -210,10 +210,9 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { target2 := newMockCapability( capabilities.MustNewCapabilityInfo( - "write_ethereum-testnet-sepolia", + "write_ethereum-testnet-sepolia@1.0.0", capabilities.CapabilityTypeTarget, "a write capability targeting ethereum sepolia testnet", - "v1.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -250,7 +249,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { const ( simpleWorkflow = ` triggers: - - id: "mercury-trigger" + - id: "mercury-trigger@1.0.0" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -258,7 +257,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD consensus: - - id: "offchain_reporting" + - id: "offchain_reporting@1.0.0" ref: "evm_median" inputs: observations: @@ -280,7 +279,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - id: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai@1.0.0" inputs: report: "$(evm_median.outputs.report)" config: @@ -293,10 +292,9 @@ targets: func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.CapabilityResponse) { mt := &mockTriggerCapability{ CapabilityInfo: capabilities.MustNewCapabilityInfo( - "mercury-trigger", + "mercury-trigger@1.0.0", capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", - "v1.0.0", ), ch: make(chan capabilities.CapabilityResponse, 10), } @@ -316,10 +314,9 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { mt := &mockTriggerCapability{ CapabilityInfo: capabilities.MustNewCapabilityInfo( - "mercury-trigger", + "mercury-trigger@1.0.0", capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", - "v1.0.0", ), ch: make(chan capabilities.CapabilityResponse, 10), } @@ -329,10 +326,9 @@ func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { func mockFailingConsensus() *mockCapability { return newMockCapability( capabilities.MustNewCapabilityInfo( - "offchain_reporting", + "offchain_reporting@1.0.0", capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", - "v3.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { return capabilities.CapabilityResponse{}, errors.New("fatal consensus error") @@ -340,13 +336,27 @@ func mockFailingConsensus() *mockCapability { ) } +func mockConsensusWithEarlyTermination() *mockCapability { + return newMockCapability( + capabilities.MustNewCapabilityInfo( + "offchain_reporting@1.0.0", + capabilities.CapabilityTypeConsensus, + "an ocr3 consensus capability", + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + return capabilities.CapabilityResponse{ + Err: capabilities.ErrStopExecution, + }, nil + }, + ) +} + func mockConsensus() *mockCapability { return newMockCapability( capabilities.MustNewCapabilityInfo( - "offchain_reporting", + "offchain_reporting@1.0.0", capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", - "v3.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { obs := req.Inputs.Underlying["observations"] @@ -369,10 +379,9 @@ func mockConsensus() *mockCapability { func mockTarget() *mockCapability { return newMockCapability( capabilities.MustNewCapabilityInfo( - "write_polygon-testnet-mumbai", + "write_polygon-testnet-mumbai@1.0.0", capabilities.CapabilityTypeTarget, "a write capability targeting polygon mumbai testnet", - "v1.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -409,10 +418,35 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { assert.Equal(t, state.Steps["evm_median"].Status, store.StatusErrored) } +func TestEngine_GracefulEarlyTermination(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, _ := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensusWithEarlyTermination())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + eng, hooks := newTestEngine(t, reg, simpleWorkflow) + + err := eng.Start(ctx) + require.NoError(t, err) + defer eng.Close() + + eid := getExecutionId(t, eng, hooks) + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompletedEarlyExit) + assert.Nil(t, state.Steps["write_polygon-testnet-mumbai"]) +} + const ( multiStepWorkflow = ` triggers: - - id: "mercury-trigger" + - id: "mercury-trigger@1.0.0" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -420,14 +454,15 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD actions: - - id: "read_chain_action" + - id: "read_chain_action@1.0.0" ref: "read_chain_action" + config: {} inputs: action: - "$(trigger.outputs)" consensus: - - id: "offchain_reporting" + - id: "offchain_reporting@1.0.0" ref: "evm_median" inputs: observations: @@ -450,7 +485,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - id: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai@1.0.0" inputs: report: "$(evm_median.outputs.report)" config: @@ -464,10 +499,9 @@ func mockAction() (*mockCapability, values.Value) { outputs := values.NewString("output") return newMockCapability( capabilities.MustNewCapabilityInfo( - "read_chain_action", + "read_chain_action@1.0.0", capabilities.CapabilityTypeAction, "a read chain action", - "v1.0.0", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { return capabilities.CapabilityResponse{ diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index cf68b0e7117..4b4747c486f 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -21,23 +21,27 @@ func TestParse_Graph(t *testing.T) { name: "basic example", yaml: ` triggers: - - id: "a-trigger" + - id: "a-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -60,28 +64,33 @@ targets: name: "circular relationship", yaml: ` triggers: - - id: "a-trigger" + - id: "a-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) output: $(a-second-action.outputs) - - id: "a-second-action" + - id: "a-second-action@1.0.0" + config: {} ref: "a-second-action" inputs: output: $(an-action.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -92,32 +101,38 @@ targets: name: "indirect circular relationship", yaml: ` triggers: - - id: "a-trigger" + - id: "a-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(a-third-action.outputs) - - id: "a-second-action" + - id: "a-second-action@1.0.0" + config: {} ref: "a-second-action" inputs: output: $(an-action.outputs) - - id: "a-third-action" + - id: "a-third-action@1.0.0" + config: {} ref: "a-third-action" inputs: output: $(a-second-action.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -128,23 +143,27 @@ targets: name: "relationship doesn't exist", yaml: ` triggers: - - id: "a-trigger" + - id: "a-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(missing-action.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -155,23 +174,28 @@ targets: name: "two trigger nodes", yaml: ` triggers: - - id: "a-trigger" - - id: "a-second-trigger" + - id: "a-trigger@1.0.0" + config: {} + - id: "a-second-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -193,21 +217,26 @@ targets: name: "non-trigger step with no dependent refs", yaml: ` triggers: - - id: "a-trigger" - - id: "a-second-trigger" + - id: "a-trigger@1.0.0" + config: {} + - id: "a-second-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: hello: "world" consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -218,21 +247,26 @@ targets: name: "duplicate edge declarations", yaml: ` triggers: - - id: "a-trigger" - - id: "a-second-trigger" + - id: "a-trigger@1.0.0" + config: {} + - id: "a-second-trigger@1.0.0" + config: {} actions: - - id: "an-action" + - id: "an-action@1.0.0" + config: {} ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - id: "a-consensus" + - id: "a-consensus@1.0.0" + config: {} ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) action_output: $(an-action.outputs) targets: - - id: "a-target" + - id: "a-target@1.0.0" + config: {} ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) diff --git a/core/services/workflows/store/models.go b/core/services/workflows/store/models.go index 27604543ede..8b4632b1f83 100644 --- a/core/services/workflows/store/models.go +++ b/core/services/workflows/store/models.go @@ -7,10 +7,11 @@ import ( ) const ( - StatusStarted = "started" - StatusErrored = "errored" - StatusTimeout = "timeout" - StatusCompleted = "completed" + StatusStarted = "started" + StatusErrored = "errored" + StatusTimeout = "timeout" + StatusCompleted = "completed" + StatusCompletedEarlyExit = "completed_early_exit" ) type StepOutput struct { diff --git a/core/store/migrate/migrations/0242_add_account_public_key_to_fms_chain_config.sql b/core/store/migrate/migrations/0242_add_account_public_key_to_fms_chain_config.sql new file mode 100644 index 00000000000..d5b9584d3ec --- /dev/null +++ b/core/store/migrate/migrations/0242_add_account_public_key_to_fms_chain_config.sql @@ -0,0 +1,11 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE feeds_manager_chain_configs +ADD COLUMN account_address_public_key VARCHAR; + +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +ALTER TABLE feeds_manager_chain_configs DROP COLUMN account_address_public_key; + +-- +goose StatementEnd diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 0eadcab108c..88ebdce2934 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -397,7 +397,7 @@ func TestJobController_Create_HappyPath(t *testing.T) { name := "myworkflow" // 10 bytes workflow := ` triggers: - - id: "mercury-trigger" + - id: "mercury-trigger@1.0.0" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -405,7 +405,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - id: "offchain_reporting" + - id: "offchain_reporting@2.0.0" ref: "evm_median" inputs: observations: @@ -427,14 +427,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - id: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai@3.0.0" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - id: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia@4.0.0" inputs: report: "$(evm_median.outputs.report)" config: diff --git a/core/web/resolver/feeds_manager_chain_config.go b/core/web/resolver/feeds_manager_chain_config.go index 6d4e4c88e55..1afcd2b5f0a 100644 --- a/core/web/resolver/feeds_manager_chain_config.go +++ b/core/web/resolver/feeds_manager_chain_config.go @@ -43,6 +43,11 @@ func (r *FeedsManagerChainConfigResolver) AccountAddr() string { return r.cfg.AccountAddress } +// AccountAddrPubKey resolves the chain configs's account address public key. +func (r *FeedsManagerChainConfigResolver) AccountAddrPubKey() *string { + return r.cfg.AccountAddressPublicKey.Ptr() +} + // AdminAddr resolves the chain configs's admin address. func (r *FeedsManagerChainConfigResolver) AdminAddr() string { return r.cfg.AdminAddress diff --git a/core/web/resolver/feeds_manager_chain_config_test.go b/core/web/resolver/feeds_manager_chain_config_test.go index c5dd77c14a1..bd4c1e05aeb 100644 --- a/core/web/resolver/feeds_manager_chain_config_test.go +++ b/core/web/resolver/feeds_manager_chain_config_test.go @@ -15,14 +15,15 @@ import ( func Test_CreateFeedsManagerChainConfig(t *testing.T) { var ( - mgrID = int64(100) - cfgID = int64(1) - chainID = "42" - accountAddr = "0x0000001" - adminAddr = "0x0000002" - forwarderAddr = "0x0000003" - peerID = null.StringFrom("p2p_12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw") - keyBundleID = null.StringFrom("6fdb8235e16e099de91df7ef8a8088e9deea0ed6ae106b133e5d985a8a9e1562") + mgrID = int64(100) + cfgID = int64(1) + chainID = "42" + accountAddr = "0x0000001" + acctAddrPubKey = "0x0000004" + adminAddr = "0x0000002" + forwarderAddr = "0x0000003" + peerID = null.StringFrom("p2p_12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw") + keyBundleID = null.StringFrom("6fdb8235e16e099de91df7ef8a8088e9deea0ed6ae106b133e5d985a8a9e1562") mutation = ` mutation CreateFeedsManagerChainConfig($input: CreateFeedsManagerChainConfigInput!) { @@ -51,6 +52,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { "chainID": chainID, "chainType": "EVM", "accountAddr": accountAddr, + "accountAddrPubKey": acctAddrPubKey, "adminAddr": adminAddr, "fluxMonitorEnabled": false, "ocr1Enabled": true, @@ -75,11 +77,12 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { before: func(ctx context.Context, f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CreateChainConfig", mock.Anything, feeds.ChainConfig{ - FeedsManagerID: mgrID, - ChainType: feeds.ChainTypeEVM, - ChainID: chainID, - AccountAddress: accountAddr, - AdminAddress: adminAddr, + FeedsManagerID: mgrID, + ChainType: feeds.ChainTypeEVM, + ChainID: chainID, + AccountAddress: accountAddr, + AccountAddressPublicKey: null.StringFrom(acctAddrPubKey), + AdminAddress: adminAddr, FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: false, }, @@ -103,11 +106,12 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { }, }).Return(cfgID, nil) f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ - ID: cfgID, - ChainType: feeds.ChainTypeEVM, - ChainID: chainID, - AccountAddress: accountAddr, - AdminAddress: adminAddr, + ID: cfgID, + ChainType: feeds.ChainTypeEVM, + ChainID: chainID, + AccountAddress: accountAddr, + AccountAddressPublicKey: null.StringFrom(acctAddrPubKey), + AdminAddress: adminAddr, FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: false, }, @@ -272,12 +276,13 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { func Test_UpdateFeedsManagerChainConfig(t *testing.T) { var ( - cfgID = int64(1) - peerID = null.StringFrom("p2p_12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw") - keyBundleID = null.StringFrom("6fdb8235e16e099de91df7ef8a8088e9deea0ed6ae106b133e5d985a8a9e1562") - accountAddr = "0x0000001" - adminAddr = "0x0000002" - forwarderAddr = "0x0000003" + cfgID = int64(1) + peerID = null.StringFrom("p2p_12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw") + keyBundleID = null.StringFrom("6fdb8235e16e099de91df7ef8a8088e9deea0ed6ae106b133e5d985a8a9e1562") + accountAddr = "0x0000001" + adminAddr = "0x0000002" + forwarderAddr = "0x0000003" + accountAddrPubKey = "0x0000004" mutation = ` mutation UpdateFeedsManagerChainConfig($id: ID!, $input: UpdateFeedsManagerChainConfigInput!) { @@ -304,6 +309,7 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { "id": "1", "input": map[string]interface{}{ "accountAddr": accountAddr, + "accountAddrPubKey": accountAddrPubKey, "adminAddr": adminAddr, "fluxMonitorEnabled": false, "ocr1Enabled": true, @@ -328,9 +334,10 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { before: func(ctx context.Context, f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateChainConfig", mock.Anything, feeds.ChainConfig{ - ID: cfgID, - AccountAddress: accountAddr, - AdminAddress: adminAddr, + ID: cfgID, + AccountAddress: accountAddr, + AccountAddressPublicKey: null.StringFrom(accountAddrPubKey), + AdminAddress: adminAddr, FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: false, }, @@ -354,9 +361,10 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { }, }).Return(cfgID, nil) f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ - ID: cfgID, - AccountAddress: accountAddr, - AdminAddress: adminAddr, + ID: cfgID, + AccountAddress: accountAddr, + AdminAddress: adminAddr, + AccountAddressPublicKey: null.StringFrom(accountAddrPubKey), FluxMonitorConfig: feeds.FluxMonitorConfig{ Enabled: false, }, diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 25019df9761..08b435e82ce 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -157,6 +157,7 @@ type createFeedsManagerChainConfigInput struct { ChainID string ChainType string AccountAddr string + AccountAddrPubKey *string AdminAddr string FluxMonitorEnabled bool OCR1Enabled bool @@ -203,6 +204,10 @@ func (r *Resolver) CreateFeedsManagerChainConfig(ctx context.Context, args struc }, } + if args.Input.AccountAddrPubKey != nil { + params.AccountAddressPublicKey = null.StringFromPtr(args.Input.AccountAddrPubKey) + } + if args.Input.OCR1Enabled { params.OCR1Config = feeds.OCR1Config{ Enabled: args.Input.OCR1Enabled, @@ -292,6 +297,7 @@ func (r *Resolver) DeleteFeedsManagerChainConfig(ctx context.Context, args struc type updateFeedsManagerChainConfigInput struct { AccountAddr string + AccountAddrPubKey *string AdminAddr string FluxMonitorEnabled bool OCR1Enabled bool @@ -332,6 +338,10 @@ func (r *Resolver) UpdateFeedsManagerChainConfig(ctx context.Context, args struc }, } + if args.Input.AccountAddrPubKey != nil { + params.AccountAddressPublicKey = null.StringFromPtr(args.Input.AccountAddrPubKey) + } + if args.Input.OCR1Enabled { params.OCR1Config = feeds.OCR1Config{ Enabled: args.Input.OCR1Enabled, diff --git a/core/web/schema/type/feeds_manager.graphql b/core/web/schema/type/feeds_manager.graphql index a6301c9ef6b..12e8732c8e0 100644 --- a/core/web/schema/type/feeds_manager.graphql +++ b/core/web/schema/type/feeds_manager.graphql @@ -28,6 +28,7 @@ type FeedsManagerChainConfig { chainID: String! chainType: String! accountAddr: String! + accountAddrPubKey: String adminAddr: String! fluxMonitorJobConfig: FluxMonitorJobConfig! ocr1JobConfig: OCR1JobConfig! @@ -109,6 +110,7 @@ input CreateFeedsManagerChainConfigInput { chainID: String! chainType: String! accountAddr: String! + accountAddrPubKey: String adminAddr: String! fluxMonitorEnabled: Boolean! ocr1Enabled: Boolean! @@ -150,6 +152,7 @@ union DeleteFeedsManagerChainConfigPayload = DeleteFeedsManagerChainConfigSucces input UpdateFeedsManagerChainConfigInput { accountAddr: String! + accountAddrPubKey: String adminAddr: String! fluxMonitorEnabled: Boolean! ocr1Enabled: Boolean! diff --git a/crib/devspace.yaml b/crib/devspace.yaml index a7530d58945..a6d118a3c87 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -132,7 +132,7 @@ deployments: releaseName: "app" chart: name: ${CHAINLINK_CLUSTER_HELM_CHART_URI} - version: "1.1.0" + version: "1.2.2" # for simplicity, we define all the values here # they can be defined the same way in values.yml # devspace merges these "values" with the "values.yaml" before deploy diff --git a/go.mod b/go.mod index 6844bbcd7bf..1af38913bd5 100644 --- a/go.mod +++ b/go.mod @@ -72,9 +72,9 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 @@ -348,4 +348,5 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f + ) diff --git a/go.sum b/go.sum index 1afcb4f9b89..5a354d44172 100644 --- a/go.sum +++ b/go.sum @@ -1171,12 +1171,12 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 h1:53zVcdDxrHG3oewhP7AWOiLtwTozcQ0/wzFTsaTBS5M= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0/go.mod h1:DUZccDEW98n+J1mhdWGO7wr/Njad9p9Fzks839JN7Rs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 h1:nsnLzpBTDAQWkfsOz/qd8BTlb1hUpaow1KmA1tPwTf4= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a h1:/QIQciKjhZy+iBB74WG4pP88O2FwS1KZtSXO5COTTgI= diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 8bb83cc8ee4..90b237ac6a1 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -96,12 +96,6 @@ func WithDbContainerName(name string) ClNodeOption { } } -func WithLogStream(ls *logstream.LogStream) ClNodeOption { - return func(c *ClNode) { - c.LogStream = ls - } -} - func WithImage(image string) ClNodeOption { return func(c *ClNode) { c.ContainerImage = image @@ -124,10 +118,11 @@ func WithPgDBOptions(opts ...test_env.PostgresDbOption) ClNodeOption { } } -func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, opts ...ClNodeOption) (*ClNode, error) { +func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, logStream *logstream.LogStream, opts ...ClNodeOption) (*ClNode, error) { nodeDefaultCName := fmt.Sprintf("%s-%s", "cl-node", uuid.NewString()[0:8]) pgDefaultCName := fmt.Sprintf("pg-%s", nodeDefaultCName) - pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName)) + + pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName), test_env.WithPostgresDbLogStream(logStream)) if err != nil { return nil, err } @@ -137,6 +132,7 @@ func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *ch ContainerImage: imageName, ContainerVersion: imageVersion, Networks: networks, + LogStream: logStream, }, UserEmail: "local@local.com", UserPassword: "localdevpassword", diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index e50c7700f55..c25cac12e67 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -131,7 +131,6 @@ func (te *CLClusterTestEnv) StartMockAdapter() error { return te.MockAdapter.StartContainer() } -// pass config here func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig ctf_config.GlobalTestConfig, opts ...ClNodeOption) error { if te.Cfg != nil && te.Cfg.ClCluster != nil { te.ClCluster = te.Cfg.ClCluster @@ -144,10 +143,10 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i }, }, opts...) } - opts = append(opts, WithSecrets(secretsConfig), WithLogStream(te.LogStream)) + opts = append(opts, WithSecrets(secretsConfig)) te.ClCluster = &ClCluster{} for i := 0; i < count; i++ { - ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, opts...) + ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, te.LogStream, opts...) 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 20a551cd905..5cd700a4567 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -73,7 +73,6 @@ type CLTestEnvBuilder struct { var DefaultAllowedMessages = []testreporters.AllowedLogMessage{ testreporters.NewAllowedLogMessage("Failed to get LINK balance", "Happens only when we deploy LINK token for test purposes. Harmless.", zapcore.ErrorLevel, testreporters.WarnAboutAllowedMsgs_No), testreporters.NewAllowedLogMessage("Error stopping job service", "It's a known issue with lifecycle. There's ongoing work that will fix it.", zapcore.DPanicLevel, testreporters.WarnAboutAllowedMsgs_No), - testreporters.NewAllowedLogMessage("SLOW SQL QUERY", "Known issue in Automation Node Upgrade Test - https://smartcontract-it.atlassian.net/browse/BCF-3245", zapcore.DPanicLevel, testreporters.WarnAboutAllowedMsgs_No), } var DefaultChainlinkNodeLogScannerSettings = ChainlinkNodeLogScannerSettings{ diff --git a/integration-tests/go.mod b/integration-tests/go.mod index dd0e0ed3c44..44b38596857 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -27,8 +27,8 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 - github.com/smartcontractkit/chainlink-testing-framework v1.30.1 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce + github.com/smartcontractkit/chainlink-testing-framework v1.30.2 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c @@ -50,6 +50,7 @@ require ( exclude github.com/hashicorp/consul v1.2.1 replace ( + // Pin K8s versions as their updates are highly disruptive and go mod keeps wanting to update them k8s.io/api => k8s.io/api v0.25.11 k8s.io/client-go => k8s.io/client-go v0.25.11 k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d @@ -376,7 +377,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 75d96085bdb..b0350814045 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1512,20 +1512,20 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 h1:53zVcdDxrHG3oewhP7AWOiLtwTozcQ0/wzFTsaTBS5M= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0/go.mod h1:DUZccDEW98n+J1mhdWGO7wr/Njad9p9Fzks839JN7Rs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 h1:nsnLzpBTDAQWkfsOz/qd8BTlb1hUpaow1KmA1tPwTf4= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a h1:/QIQciKjhZy+iBB74WG4pP88O2FwS1KZtSXO5COTTgI= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a/go.mod h1:QqcZSwLgEIn7YraAIRmomnBMAuVFephiHrIWVlkWbFI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 h1:h1E87+z+JcUEfvbJVF56SnZA/YUFE5ewUE61MaR/Ewg= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696/go.mod h1:OiWUTrrpSLLTMh7FINWjEh6mmDJCVPaC4yEsDCVaWdU= -github.com/smartcontractkit/chainlink-testing-framework v1.30.1 h1:JFoeSuOvdx8Rmfh5Z4KOH0FnjiLw3M2p7T4GLzTPLMk= -github.com/smartcontractkit/chainlink-testing-framework v1.30.1/go.mod h1:oEIggLGWyWfLkjWvuXLol8inUT4YbBb06fJx/S60gQ4= +github.com/smartcontractkit/chainlink-testing-framework v1.30.2 h1:PKAg0nVT6clcTYebm3Q0rhTId+5xE9wYyvFxxSg4+lI= +github.com/smartcontractkit/chainlink-testing-framework v1.30.2/go.mod h1:oEIggLGWyWfLkjWvuXLol8inUT4YbBb06fJx/S60gQ4= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 63c6c3e69cc..adc04c66955 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,8 +16,8 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 - github.com/smartcontractkit/chainlink-testing-framework v1.30.1 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce + github.com/smartcontractkit/chainlink-testing-framework v1.30.2 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c @@ -365,7 +365,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index fd58729101b..fd121a53f06 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1502,20 +1502,20 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0 h1:53zVcdDxrHG3oewhP7AWOiLtwTozcQ0/wzFTsaTBS5M= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240606094423-573049c41fa0/go.mod h1:DUZccDEW98n+J1mhdWGO7wr/Njad9p9Fzks839JN7Rs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580 h1:nsnLzpBTDAQWkfsOz/qd8BTlb1hUpaow1KmA1tPwTf4= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240606130021-a4b7359e1580/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a h1:/QIQciKjhZy+iBB74WG4pP88O2FwS1KZtSXO5COTTgI= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a/go.mod h1:QqcZSwLgEIn7YraAIRmomnBMAuVFephiHrIWVlkWbFI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 h1:h1E87+z+JcUEfvbJVF56SnZA/YUFE5ewUE61MaR/Ewg= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696/go.mod h1:OiWUTrrpSLLTMh7FINWjEh6mmDJCVPaC4yEsDCVaWdU= -github.com/smartcontractkit/chainlink-testing-framework v1.30.1 h1:JFoeSuOvdx8Rmfh5Z4KOH0FnjiLw3M2p7T4GLzTPLMk= -github.com/smartcontractkit/chainlink-testing-framework v1.30.1/go.mod h1:oEIggLGWyWfLkjWvuXLol8inUT4YbBb06fJx/S60gQ4= +github.com/smartcontractkit/chainlink-testing-framework v1.30.2 h1:PKAg0nVT6clcTYebm3Q0rhTId+5xE9wYyvFxxSg4+lI= +github.com/smartcontractkit/chainlink-testing-framework v1.30.2/go.mod h1:oEIggLGWyWfLkjWvuXLol8inUT4YbBb06fJx/S60gQ4= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 7a2215c36f0..659a7f2b2f1 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -12,15 +12,15 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "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/testcontext" + geth_helm "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -29,7 +29,8 @@ import ( ) var ( - baseTOML = `[Feature] + baseTOML = ` +[Feature] LogPoller = true [OCR2] @@ -38,18 +39,27 @@ Enabled = true [P2P] [P2P.V2] AnnounceAddresses = ["0.0.0.0:6690"] -ListenAddresses = ["0.0.0.0:6690"]` - networkTOML = `Enabled = true -FinalityDepth = 200 -LogPollInterval = '1s' +ListenAddresses = ["0.0.0.0:6690"] + ` + finalityDepth = 20 + historyDepth = 30 + reorgBlockCount = 10 // Number of blocks to reorg (less than finalityDepth) + networkTOML = fmt.Sprintf(` +Enabled = true +FinalityDepth = %d [EVM.HeadTracker] -HistoryDepth = 400 +HistoryDepth = %d [EVM.GasEstimator] Mode = 'FixedPrice' -LimitDefault = 5_000_000` - +LimitDefault = 5_000_000 + `, finalityDepth, historyDepth) + upkeepCount = 2 + nodeCount = 6 + nodeFundsAmount = new(big.Float).SetFloat64(2) // Each node will have 2 ETH + defaultUpkeepGasLimit = uint32(2500000) + defaultLinkFunds = int64(9e18) defaultAutomationSettings = map[string]interface{}{ "toml": "", "db": map[string]interface{}{ @@ -67,22 +77,6 @@ LimitDefault = 5_000_000` }, }, } - - defaultReorgEthereumSettings = &reorg.Props{ - NetworkName: "", - NetworkType: "geth-reorg", - Values: map[string]interface{}{ - "geth": map[string]interface{}{ - "genesis": map[string]interface{}{ - "networkId": "1337", - }, - "miner": map[string]interface{}{ - "replicas": 2, - }, - }, - }, - } - defaultOCRRegistryConfig = contracts.KeeperRegistrySettings{ PaymentPremiumPPB: uint32(200000000), FlatFeeMicroLINK: uint32(0), @@ -100,31 +94,17 @@ LimitDefault = 5_000_000` } ) -const ( - defaultUpkeepGasLimit = uint32(2500000) - defaultLinkFunds = int64(9e18) - numberOfUpkeeps = 2 - automationReorgBlocks = 50 - numberOfNodes = 6 -) - /* - * This test verifies that conditional upkeeps automatically recover from chain reorgs - * The blockchain is configured to have two separate miners and one geth node. The test starts - * with happy path where the two miners remain in sync and upkeeps are expected to be performed. - * Then reorg starts and the connection between the two geth miners is severed. This makes the - * chain unstable, however all the CL nodes get the same view of the unstable chain through the - * same geth node. + * This test verifies that conditional upkeeps automatically recover from chain reorgs. * - * Upkeeps are expected to be performed during the reorg as there are only two versions of the - * the chain, on average 1/2 performUpkeeps should go through. + * The test starts with happy path where upkeeps are expected to be performed. + * Then reorg below finality depth happens which makes the chain unstable. * - * The miner nodes are synced back after automationReorgBlocks. The syncing event can cause a - * large reorg from CL node perspective, causing existing performUpkeeps to become staleUpkeeps. - * Automation should be able to recover from this and upkeeps should continue to occur at a - * normal pace after the event. + * Upkeeps are expected to be performed during the reorg. */ func TestAutomationReorg(t *testing.T) { + require.Less(t, reorgBlockCount, finalityDepth, "Reorg block count should be less than finality depth") + t.Parallel() l := logging.GetTestLogger(t) @@ -132,8 +112,8 @@ func TestAutomationReorg(t *testing.T) { "registry_2_0": ethereum.RegistryVersion_2_0, "registry_2_1_conditional": ethereum.RegistryVersion_2_1, "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, - "registry_2_2_conditional": ethereum.RegistryVersion_2_2, - "registry_2_2_logtrigger": ethereum.RegistryVersion_2_2, + "registry_2_2_conditional": ethereum.RegistryVersion_2_2, // Works only on Chainlink Node v2.10.0 or greater + "registry_2_2_logtrigger": ethereum.RegistryVersion_2_2, // Works only on Chainlink Node v2.10.0 or greater } for n, rv := range registryVersions { @@ -148,7 +128,7 @@ func TestAutomationReorg(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(config.Network)[0] - defaultAutomationSettings["replicas"] = numberOfNodes + defaultAutomationSettings["replicas"] = nodeCount defaultAutomationSettings["toml"] = networks.AddNetworkDetailedConfig(baseTOML, config.Pyroscope, networkTOML, network) var overrideFn = func(_ interface{}, target interface{}) { @@ -158,19 +138,17 @@ func TestAutomationReorg(t *testing.T) { cd := chainlink.NewWithOverride(0, defaultAutomationSettings, config.ChainlinkImage, overrideFn) - ethSetting := defaultReorgEthereumSettings - ethSetting.NetworkName = network.Name - testEnvironment := environment. New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("automation-reorg-%d", automationReorgBlocks), + NamespacePrefix: fmt.Sprintf("automation-reorg-%d", reorgBlockCount), TTL: time.Hour * 1, Test: t}). - AddHelm(reorg.New(ethSetting)). - AddChart(blockscout.New(&blockscout.Props{ - Name: "geth-blockscout", - WsURL: network.URL, - HttpURL: network.HTTPURLs[0]})). + // Use Geth blockchain to simulate reorgs + AddHelm(geth_helm.New(&geth_helm.Props{ + NetworkName: network.Name, + Simulated: true, + WsURLs: network.URLs, + })). AddHelm(cd) err = testEnvironment.Run() require.NoError(t, err, "Error setting up test environment") @@ -178,6 +156,9 @@ func TestAutomationReorg(t *testing.T) { if testEnvironment.WillUseRemoteRunner() { return } + gethURL := testEnvironment.URLs["Simulated Geth_http"][0] + require.NotEmpty(t, gethURL, "Geth URL should not be empty") + gethRPCClient := ctf_client.NewRPCClient(gethURL) chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) require.NoError(t, err, "Error connecting to blockchain") @@ -193,9 +174,7 @@ func TestAutomationReorg(t *testing.T) { require.NoError(t, err, "Error tearing down environment") }) - txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) + err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, nodeFundsAmount) require.NoError(t, err, "Error funding Chainlink nodes") linkToken, err := contractDeployer.DeployLinkTokenContract() @@ -210,7 +189,7 @@ func TestAutomationReorg(t *testing.T) { chainClient, ) // Fund the registry with LINK - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) + err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(upkeepCount)))) require.NoError(t, err, "Funding keeper registry contract shouldn't fail") actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, registryVersion) @@ -227,8 +206,18 @@ func TestAutomationReorg(t *testing.T) { require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") // Use the name to determine if this is a log trigger or not - isLogTrigger := name == "registry_2_1_logtrigger" - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, isLogTrigger, false) + isLogTrigger := name == "registry_2_1_logtrigger" || name == "registry_2_2_logtrigger" + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, upkeepCount, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, isLogTrigger, false) + + if isLogTrigger { + for i := 0; i < len(upkeepIDs); i++ { + if err := consumers[i].Start(); err != nil { + l.Error().Msg("Error when starting consumer") + return + } + l.Info().Int("Consumer index", i).Msg("Consumer started") + } + } l.Info().Msg("Waiting for all upkeeps to be performed") @@ -247,20 +236,14 @@ func TestAutomationReorg(t *testing.T) { l.Info().Msg("All upkeeps performed under happy path. Starting reorg") - rc, err := NewReorgController( - &ReorgConfig{ - FromPodLabel: reorg.TXNodesAppLabel, - ToPodLabel: reorg.MinerNodesAppLabel, - Network: chainClient, - Env: testEnvironment, - BlockConsensusThreshold: 3, - Timeout: 1800 * time.Second, - }, - ) - - require.NoError(t, err, "Error getting reorg controller") - rc.ReOrg(automationReorgBlocks) - rc.WaitReorgStarted() + l.Info(). + Str("URL", gethRPCClient.URL). + Int("BlocksBack", reorgBlockCount). + Int("FinalityDepth", finalityDepth). + Int("HistoryDepth", historyDepth). + Msg("Rewinding blocks on chain below finality depth") + err = gethRPCClient.GethSetHead(reorgBlockCount) + require.NoError(t, err, "Error rewinding blocks on chain") l.Info().Msg("Reorg started. Expecting chain to become unstable and upkeeps to still getting performed") @@ -275,23 +258,6 @@ func TestAutomationReorg(t *testing.T) { "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) } }, "5m", "1s").Should(gomega.Succeed()) - - l.Info().Msg("Upkeep performed during unstable chain, waiting for reorg to finish") - 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(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") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "10m", "1s").Should(gomega.Succeed()) }) } } diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 2cae2ec3f45..1783549637b 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -38,7 +38,7 @@ func TestForwarderOCRBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(.1)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index a8d0e1987fe..2651a02fb4d 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -39,7 +39,7 @@ func TestForwarderOCR2Basic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(.1)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 99817562c62..62a79f0347b 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1236,7 +1236,7 @@ func setupKeeperTest(l zerolog.Logger, t *testing.T, config *tc.TestConfig) ( WithTestConfig(config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(5). - WithFunding(big.NewFloat(.5)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 7ca7b01fb36..d0d1e36c8ed 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -156,7 +156,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, WithMockAdapter(). WithCLNodes(clNodeCount). WithCLNodeOptions(test_env.WithNodeEnvVars(testData.env)). - WithFunding(big.NewFloat(.1)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index bef08493962..02d548f4763 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -94,7 +94,7 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(.5)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 3e806fc690b..7090564c42e 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -39,7 +39,7 @@ func TestRunLogBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). - WithFunding(big.NewFloat(.5)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 1cc7bf73d69..abb619e7b0b 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -196,7 +196,7 @@ func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestE WithTestConfig(&config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). - WithFunding(big.NewFloat(.5)). + WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). WithSeth(). Build() diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index f99c434bc4d..397fc2ee792 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -1,33 +1,36 @@ [Logging] -test_log_collect=false +test_log_collect = false [Logging.LogStream] -log_targets=["file"] -log_producer_timeout="10s" -log_producer_retry_limit=10 +log_targets = ["file"] +log_producer_timeout = "10s" +log_producer_retry_limit = 10 [ChainlinkImage] -postgres_version="15.6" -image="public.ecr.aws/chainlink/chainlink" -version="2.9.1" +postgres_version = "15.6" +image = "public.ecr.aws/chainlink/chainlink" +version = "2.12.0" + +[Common] +chainlink_node_funding = 0.5 [Network] -selected_networks=["simulated"] +selected_networks = ["simulated"] [PrivateEthereumNetwork] -ethereum_version="eth1" -execution_layer="geth" +ethereum_version = "eth1" +execution_layer = "geth" [PrivateEthereumNetwork.EthereumChainConfig] -seconds_per_slot=3 -slots_per_epoch=2 -genesis_delay=15 -validator_count=4 -chain_id=1337 -addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] +seconds_per_slot = 3 +slots_per_epoch = 2 +genesis_delay = 15 +validator_count = 4 +chain_id = 1337 +addresses_to_fund = ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] [PrivateEthereumNetwork.EthereumChainConfig.HardForkEpochs] -Deneb=500 +Deneb = 500 [NodeConfig] BaseConfigTOML = """ @@ -144,9 +147,9 @@ gas_price_estimation_tx_priority = "standard" # fallback values transfer_gas_fee = 21_000 -gas_price = 150_000_000_000 #150 gwei +gas_price = 150_000_000_000 #150 gwei gas_fee_cap = 150_000_000_000 #150 gwei -gas_tip_cap = 50_000_000_000 #50 gwei +gas_tip_cap = 50_000_000_000 #50 gwei [[Seth.networks]] name = "Anvil" @@ -405,4 +408,4 @@ gas_price_estimation_enabled = true # how many last blocks to use, when estimating gas for a transaction gas_price_estimation_blocks = 100 # priority of the transaction, can be "fast", "standard" or "slow" (the higher the priority, the higher adjustment factor will be used for gas estimation) [default: "standard"] -gas_price_estimation_tx_priority = "standard" \ No newline at end of file +gas_price_estimation_tx_priority = "standard"