diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index c8b1d18d0bd..c85c927b8d4 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -384,7 +384,7 @@ func (e *EthereumContractDeployer) DeployFunctionsLoadTestClient(router string) if err != nil { return nil, err } - return &EthereumFunctionsLoadTestClient{ + return &LegacyEthereumFunctionsLoadTestClient{ client: e.client, instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), address: *address, diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go index 38b09687c20..f492adc3286 100644 --- a/integration-tests/contracts/contract_loader.go +++ b/integration-tests/contracts/contract_loader.go @@ -200,7 +200,7 @@ func (e *EthereumContractLoader) LoadFunctionsCoordinator(addr string) (Function if err != nil { return nil, err } - return &EthereumFunctionsCoordinator{ + return &LegacyEthereumFunctionsCoordinator{ client: e.client, instance: instance.(*functions_coordinator.FunctionsCoordinator), address: common.HexToAddress(addr), @@ -218,7 +218,7 @@ func (e *EthereumContractLoader) LoadFunctionsRouter(addr string) (FunctionsRout if err != nil { return nil, err } - return &EthereumFunctionsRouter{ + return &LegacyEthereumFunctionsRouter{ client: e.client, instance: instance.(*functions_router.FunctionsRouter), address: common.HexToAddress(addr), @@ -237,7 +237,7 @@ func (e *EthereumContractLoader) LoadFunctionsLoadTestClient(addr string) (Funct if err != nil { return nil, err } - return &EthereumFunctionsLoadTestClient{ + return &LegacyEthereumFunctionsLoadTestClient{ client: e.client, instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), address: common.HexToAddress(addr), diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index 688a49cf111..e8b2f184ce9 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -2078,18 +2078,18 @@ func (e *EthereumKeeperRegistryCheckUpkeepGasUsageWrapper) Address() string { /* Functions 1_0_0 */ -type EthereumFunctionsRouter struct { +type LegacyEthereumFunctionsRouter struct { address common.Address client blockchain.EVMClient instance *functions_router.FunctionsRouter l zerolog.Logger } -func (e *EthereumFunctionsRouter) Address() string { +func (e *LegacyEthereumFunctionsRouter) Address() string { return e.address.Hex() } -func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { +func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return 0, err @@ -2129,13 +2129,13 @@ func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string return topicsMap["subscriptionId"].(uint64), nil } -type EthereumFunctionsCoordinator struct { +type LegacyEthereumFunctionsCoordinator struct { address common.Address client blockchain.EVMClient instance *functions_coordinator.FunctionsCoordinator } -func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { +func (e *LegacyEthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { opts := &bind.CallOpts{ From: common.HexToAddress(e.client.GetDefaultWallet().Address()), Context: context.Background(), @@ -2143,7 +2143,7 @@ func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { return e.instance.GetThresholdPublicKey(opts) } -func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { +func (e *LegacyEthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { opts := &bind.CallOpts{ From: common.HexToAddress(e.client.GetDefaultWallet().Address()), Context: context.Background(), @@ -2151,17 +2151,17 @@ func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { return e.instance.GetDONPublicKey(opts) } -func (e *EthereumFunctionsCoordinator) Address() string { +func (e *LegacyEthereumFunctionsCoordinator) Address() string { return e.address.Hex() } -type EthereumFunctionsLoadTestClient struct { +type LegacyEthereumFunctionsLoadTestClient struct { address common.Address client blockchain.EVMClient instance *functions_load_test_client.FunctionsLoadTestClient } -func (e *EthereumFunctionsLoadTestClient) Address() string { +func (e *LegacyEthereumFunctionsLoadTestClient) Address() string { return e.address.Hex() } @@ -2180,7 +2180,7 @@ func Bytes32ToSlice(a [32]byte) (r []byte) { return } -func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { +func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { opts := &bind.CallOpts{ From: common.HexToAddress(e.client.GetDefaultWallet().Address()), Context: context.Background(), @@ -2200,7 +2200,7 @@ func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStat }, nil } -func (e *EthereumFunctionsLoadTestClient) ResetStats() error { +func (e *LegacyEthereumFunctionsLoadTestClient) ResetStats() error { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err @@ -2212,7 +2212,7 @@ func (e *EthereumFunctionsLoadTestClient) ResetStats() error { return e.client.ProcessTransaction(tx) } -func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { +func (e *LegacyEthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err @@ -2224,7 +2224,7 @@ func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source strin return e.client.ProcessTransaction(tx) } -func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { +func (e *LegacyEthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err diff --git a/integration-tests/contracts/ethereum_contracts_seth.go b/integration-tests/contracts/ethereum_contracts_seth.go index 30649d41c6a..1d02c77bbe8 100644 --- a/integration-tests/contracts/ethereum_contracts_seth.go +++ b/integration-tests/contracts/ethereum_contracts_seth.go @@ -3,9 +3,12 @@ package contracts import ( "context" "encoding/hex" + "errors" "fmt" "math/big" + "strings" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -19,6 +22,9 @@ import ( ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" @@ -37,11 +43,11 @@ type EthereumOffchainAggregator struct { } func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { - oAbi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() + abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() if err != nil { return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - seth.ContractStore.AddABI("OffChainAggregator", *oAbi) + seth.ContractStore.AddABI("OffChainAggregator", *abi) seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, seth.Client) @@ -959,3 +965,190 @@ func (e *EthereumAPIConsumer) CreateRequestTo( _, err := e.client.Decode(e.consumer.CreateRequestTo(e.client.NewTXOpts(), common.HexToAddress(oracleAddr), jobID, payment, url, path, times)) return err } + +func LoadFunctionsCoordinator(seth *seth.Client, addr string) (FunctionsCoordinator, error) { + abi, err := functions_coordinator.FunctionsCoordinatorMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to get FunctionsCoordinator ABI: %w", err) + } + seth.ContractStore.AddABI("FunctionsCoordinator", *abi) + seth.ContractStore.AddBIN("FunctionsCoordinator", common.FromHex(functions_coordinator.FunctionsCoordinatorMetaData.Bin)) + + instance, err := functions_coordinator.NewFunctionsCoordinator(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to instantiate FunctionsCoordinator instance: %w", err) + } + + return &EthereumFunctionsCoordinator{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err +} + +type EthereumFunctionsCoordinator struct { + address common.Address + client *seth.Client + instance *functions_coordinator.FunctionsCoordinator +} + +func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { + return e.instance.GetThresholdPublicKey(e.client.NewCallOpts()) +} + +func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { + return e.instance.GetDONPublicKey(e.client.NewCallOpts()) +} + +func (e *EthereumFunctionsCoordinator) Address() string { + return e.address.Hex() +} + +func LoadFunctionsRouter(l zerolog.Logger, seth *seth.Client, addr string) (FunctionsRouter, error) { + abi, err := functions_router.FunctionsRouterMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to get FunctionsRouter ABI: %w", err) + } + seth.ContractStore.AddABI("FunctionsRouter", *abi) + seth.ContractStore.AddBIN("FunctionsRouter", common.FromHex(functions_router.FunctionsRouterMetaData.Bin)) + + instance, err := functions_router.NewFunctionsRouter(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to instantiate FunctionsRouter instance: %w", err) + } + + return &EthereumFunctionsRouter{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + l: l, + }, err +} + +type EthereumFunctionsRouter struct { + address common.Address + client *seth.Client + instance *functions_router.FunctionsRouter + l zerolog.Logger +} + +func (e *EthereumFunctionsRouter) Address() string { + return e.address.Hex() +} + +func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { + tx, err := e.client.Decode(e.instance.CreateSubscriptionWithConsumer(e.client.NewTXOpts(), common.HexToAddress(consumer))) + if err != nil { + return 0, err + } + + if tx.Receipt == nil { + return 0, errors.New("transaction did not err, but the receipt is nil") + } + for _, l := range tx.Receipt.Logs { + e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() + } + topicsMap := map[string]interface{}{} + + fabi, err := abi.JSON(strings.NewReader(functions_router.FunctionsRouterABI)) + if err != nil { + return 0, err + } + for _, ev := range fabi.Events { + e.l.Info().Str("EventName", ev.Name).Send() + } + topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} + topicOneHash := []common.Hash{tx.Receipt.Logs[0].Topics[1:][0]} + if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { + return 0, fmt.Errorf("failed to decode topic value, err: %w", err) + } + e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send() + if topicsMap["subscriptionId"] == 0 { + return 0, fmt.Errorf("failed to decode subscription ID after creation") + } + return topicsMap["subscriptionId"].(uint64), nil +} + +func DeployFunctionsLoadTestClient(seth *seth.Client, router string) (FunctionsLoadTestClient, error) { + operatorAbi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) + } + data, err := seth.DeployContract(seth.NewTXOpts(), "FunctionsLoadTestClient", *operatorAbi, common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin), common.HexToAddress(router)) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("FunctionsLoadTestClient instance deployment have failed: %w", err) + } + + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(data.Address, seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) + } + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: data.Address, + }, nil +} + +// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance +func LoadFunctionsLoadTestClient(seth *seth.Client, addr string) (FunctionsLoadTestClient, error) { + abi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) + } + seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) + seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) + + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) + } + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err +} + +type EthereumFunctionsLoadTestClient struct { + address common.Address + client *seth.Client + instance *functions_load_test_client.FunctionsLoadTestClient +} + +func (e *EthereumFunctionsLoadTestClient) Address() string { + return e.address.Hex() +} + +func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { + lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(e.client.NewCallOpts()) + if err != nil { + return nil, err + } + return &EthereumFunctionsLoadStats{ + LastRequestID: string(Bytes32ToSlice(lr)), + LastResponse: string(lbody), + LastError: string(lerr), + Total: total, + Succeeded: succeeded, + Errored: errored, + Empty: empty, + }, nil +} + +func (e *EthereumFunctionsLoadTestClient) ResetStats() error { + _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) + return err +} + +func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequest(e.client.NewTXOpts(), times, source, encryptedSecretsReferences, args, subscriptionId, jobId)) + return err +} + +func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequestWithDONHostedSecrets(e.client.NewTXOpts(), times, source, slotID, slotVersion, args, subscriptionId, donID)) + return err +} diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index d3b82cde33b..49102bcaa66 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -16,7 +16,6 @@ func TestFunctionsLoad(t *testing.T) { ft, err := SetupLocalLoadTestEnv(&generalConfig, &generalConfig) require.NoError(t, err) - ft.EVMClient.ParallelTransactions(false) labels := map[string]string{ "branch": "functions_healthcheck", diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go index be5d148386c..c2d5bd7c2cd 100644 --- a/integration-tests/load/functions/gateway_test.go +++ b/integration-tests/load/functions/gateway_test.go @@ -18,7 +18,6 @@ func TestGatewayLoad(t *testing.T) { require.NoError(t, err) ft, err := SetupLocalLoadTestEnv(&listConfig, &listConfig) require.NoError(t, err) - ft.EVMClient.ParallelTransactions(false) labels := map[string]string{ "branch": "gateway_healthcheck", diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index e6711907592..a6c80279bb9 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -11,21 +11,20 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/seth" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types" + "github.com/smartcontractkit/chainlink/integration-tests/utils" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) type FunctionsTest struct { - EVMClient blockchain.EVMClient - ContractDeployer contracts.ContractDeployer - ContractLoader contracts.ContractLoader + SethClient seth.Client LinkToken contracts.LinkToken Coordinator contracts.FunctionsCoordinator Router contracts.FunctionsRouter @@ -53,42 +52,36 @@ type S4SecretsCfg struct { func SetupLocalLoadTestEnv(globalConfig tc.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] - bc, err := blockchain.NewEVMClientFromNetwork(selectedNetwork, log.Logger) - if err != nil { - return nil, err - } - cd, err := contracts.NewContractDeployer(bc, log.Logger) - if err != nil { - return nil, err - } - - cl, err := contracts.NewContractLoader(bc, log.Logger) + readSethCfg := globalConfig.GetSethConfig() + sethCfg := utils.MergeSethAndEvmNetworkConfigs(log.Logger, selectedNetwork, *readSethCfg) + err := utils.ValidateSethNetworkConfig(sethCfg.Network) if err != nil { return nil, err } + seth, err := seth.NewClientWithConfig(&sethCfg) if err != nil { return nil, err } cfg := functionsConfig.GetFunctionsConfig() - lt, err := cl.LoadLINKToken(*cfg.Common.LINKTokenAddr) + lt, err := contracts.DeployLinkTokenContract(log.Logger, seth) if err != nil { return nil, err } - coord, err := cl.LoadFunctionsCoordinator(*cfg.Common.Coordinator) + coord, err := contracts.LoadFunctionsCoordinator(seth, *cfg.Common.Coordinator) if err != nil { return nil, err } - router, err := cl.LoadFunctionsRouter(*cfg.Common.Router) + router, err := contracts.LoadFunctionsRouter(log.Logger, seth, *cfg.Common.Router) if err != nil { return nil, err } var loadTestClient contracts.FunctionsLoadTestClient if cfg.Common.LoadTestClient != nil && *cfg.Common.LoadTestClient != "" { - loadTestClient, err = cl.LoadFunctionsLoadTestClient(*cfg.Common.LoadTestClient) + loadTestClient, err = contracts.LoadFunctionsLoadTestClient(seth, *cfg.Common.LoadTestClient) } else { - loadTestClient, err = cd.DeployFunctionsLoadTestClient(*cfg.Common.Router) + loadTestClient, err = contracts.DeployFunctionsLoadTestClient(seth, *cfg.Common.Router) } if err != nil { return nil, err @@ -155,9 +148,7 @@ func SetupLocalLoadTestEnv(globalConfig tc.GlobalTestConfig, functionsConfig typ Msg("Set new secret") } return &FunctionsTest{ - EVMClient: bc, - ContractDeployer: cd, - ContractLoader: cl, + SethClient: *seth, LinkToken: lt, Coordinator: coord, Router: router,