From a65e2386cf6e3212b727d8c1cf013753456a01a5 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Fri, 1 Sep 2023 19:35:15 +0300 Subject: [PATCH] Tt 562 functions + gateway performance tests, chaos suite (#10397) * TT-562 s4 tdh2 setup and tests * chaos suite * update deps * fix wrapper generation * encrypt s4 secrets * bump godeltaprof for go 1.21.0 * uniq IDs for secrets * gateway test for secrets_set * gateway test for secrets_set/secrets_list * more throughput through batch calls * update go.mod * load modes for gateway * finalize docs * decouple from env * update README * update go.sum --- .../testhelpers/FunctionsLoadTestClient.sol | 58 ++++- .../functions_load_test_client.go | 206 +++++++++++----- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- integration-tests/chaos/functions/full.yaml | 232 ++++++++++++++++++ .../contracts/contract_models.go | 6 +- .../contracts/ethereum_contracts.go | 76 +++++- integration-tests/go.mod | 10 +- integration-tests/go.sum | 14 +- integration-tests/load/functions/README.md | 45 +++- integration-tests/load/functions/config.go | 67 ++--- integration-tests/load/functions/config.toml | 51 ++-- .../load/functions/functions_test.go | 79 +++--- integration-tests/load/functions/gateway.go | 227 +++++++++++++++++ .../load/functions/gateway_gun.go | 110 +++++++++ .../load/functions/gateway_test.go | 73 ++++++ .../load/functions/onchain_monitoring.go | 61 +++++ .../load/functions/{gun.go => request_gun.go} | 17 +- integration-tests/load/functions/setup.go | 163 ++++++++++-- integration-tests/networks/known_networks.go | 6 +- 21 files changed, 1297 insertions(+), 212 deletions(-) create mode 100644 integration-tests/chaos/functions/full.yaml create mode 100644 integration-tests/load/functions/gateway.go create mode 100644 integration-tests/load/functions/gateway_gun.go create mode 100644 integration-tests/load/functions/gateway_test.go create mode 100644 integration-tests/load/functions/onchain_monitoring.go rename integration-tests/load/functions/{gun.go => request_gun.go} (65%) diff --git a/contracts/src/v0.8/functions/tests/1_0_0/testhelpers/FunctionsLoadTestClient.sol b/contracts/src/v0.8/functions/tests/1_0_0/testhelpers/FunctionsLoadTestClient.sol index 7aa46e9ba06..047b45e9562 100644 --- a/contracts/src/v0.8/functions/tests/1_0_0/testhelpers/FunctionsLoadTestClient.sol +++ b/contracts/src/v0.8/functions/tests/1_0_0/testhelpers/FunctionsLoadTestClient.sol @@ -13,11 +13,13 @@ contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { uint32 public constant MAX_CALLBACK_GAS = 70_000; - bytes32 public s_lastRequestId; - bytes32 public s_lastResponse; - bytes32 public s_lastError; - uint32 public s_lastResponseLength; - uint32 public s_lastErrorLength; + bytes32 public lastRequestID; + bytes32 public lastResponse; + bytes32 public lastError; + uint32 public totalRequests; + uint32 public totalEmptyResponses; + uint32 public totalSucceededResponses; + uint32 public totalFailedResponses; constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} @@ -29,6 +31,7 @@ contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { * @param subscriptionId Billing ID */ function sendRequest( + uint32 times, string calldata source, bytes calldata encryptedSecretsReferences, string[] calldata args, @@ -39,7 +42,33 @@ contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { req.initializeRequestForInlineJavaScript(source); if (encryptedSecretsReferences.length > 0) req.addSecretsReference(encryptedSecretsReferences); if (args.length > 0) req.setArgs(args); - s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); + uint i = 0; + for (i = 0; i < times; i++) { + lastRequestID = _sendRequest(req.encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); + totalRequests += 1; + } + } + + function resetStats() external onlyOwner { + lastRequestID = ""; + lastResponse = ""; + lastError = ""; + totalRequests = 0; + totalSucceededResponses = 0; + totalFailedResponses = 0; + totalEmptyResponses = 0; + } + + function getStats() public view onlyOwner returns (bytes32, bytes32, bytes32, uint32, uint32, uint32, uint32) { + return ( + lastRequestID, + lastResponse, + lastError, + totalRequests, + totalSucceededResponses, + totalFailedResponses, + totalEmptyResponses + ); } /** @@ -51,11 +80,18 @@ contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { */ function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { // Save only the first 32 bytes of response/error to always fit within MAX_CALLBACK_GAS - s_lastRequestId = requestId; - s_lastResponse = bytesToBytes32(response); - s_lastResponseLength = uint32(response.length); - s_lastError = bytesToBytes32(err); - s_lastErrorLength = uint32(err.length); + lastRequestID = requestId; + lastResponse = bytesToBytes32(response); + lastError = bytesToBytes32(err); + if (response.length == 0) { + totalEmptyResponses += 1; + } + if (err.length != 0) { + totalFailedResponses += 1; + } + if (response.length != 0 && err.length == 0) { + totalSucceededResponses += 1; + } } function bytesToBytes32(bytes memory b) private pure returns (bytes32 out) { diff --git a/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go b/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go index 90d1ac33533..d4f8d1fc7e6 100644 --- a/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go +++ b/core/gethwrappers/functions/generated/functions_load_test_client/functions_load_test_client.go @@ -31,8 +31,8 @@ var ( ) var FunctionsLoadTestClientMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyArgs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySecrets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySource\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoInlineSecrets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyRouterCanFulfill\",\"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\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_CALLBACK_GAS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"handleOracleFulfillment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_lastError\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_lastErrorLength\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_lastRequestId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_lastResponse\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_lastResponseLength\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"source\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedSecretsReferences\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"args\",\"type\":\"string[]\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"jobId\",\"type\":\"bytes32\"}],\"name\":\"sendRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162001a3d38038062001a3d833981016040819052620000349162000180565b6001600160a01b0381166080523380600081620000985760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cb57620000cb81620000d5565b50505050620001b2565b336001600160a01b038216036200012f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019357600080fd5b81516001600160a01b0381168114620001ab57600080fd5b9392505050565b608051611868620001d5600039600081816101c601526109f101526118686000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80636d9809a011610081578063b1e217491161005b578063b1e2174914610182578063f2fde38b1461018b578063f7b4c06f1461019e57600080fd5b80636d9809a01461014857806379ba5097146101525780638da5cb5b1461015a57600080fd5b806342748b2a116100b257806342748b2a146100ff5780634b0795a81461012c5780635fa353e71461013557600080fd5b80630ca76175146100ce5780633944ea3a146100e3575b600080fd5b6100e16100dc3660046112b4565b6101ae565b005b6100ec60035481565b6040519081526020015b60405180910390f35b60055461011790640100000000900463ffffffff1681565b60405163ffffffff90911681526020016100f6565b6100ec60045481565b6100e1610143366004611387565b61022d565b6101176201117081565b6100e1610347565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b6100ec60025481565b6100e161019936600461146b565b610449565b6005546101179063ffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461021d576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61022883838361045d565b505050565b6102356104f2565b61027e6040805161010081019091528060008152602001600081526020016000815260200160608152602001606081526020016060815260200160608152602001606081525090565b6102c089898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506105759050565b85156103085761030887878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506105869050565b83156103225761032261031b85876114a1565b82906105d0565b61033961032e82610613565b8462011170856109ec565b600255505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104516104f2565b61045a81610acb565b50565b600283905561046b82610bc0565b6003558151600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9092169190911790556104ad81610bc0565b600455516005805463ffffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9092169190911790555050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610573576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103c4565b565b6105828260008084610c42565b5050565b80516000036105c1576040517fe889636f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016020830152608090910152565b805160000361060b576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c090910152565b60606000610622610100610cd9565b905061066c6040518060400160405280600c81526020017f636f64654c6f636174696f6e000000000000000000000000000000000000000081525082610cfa90919063ffffffff16565b825161068a90600281111561068357610683611539565b8290610d13565b60408051808201909152600881527f6c616e677561676500000000000000000000000000000000000000000000000060208201526106c9908290610cfa565b60408301516106e090801561068357610683611539565b60408051808201909152600681527f736f757263650000000000000000000000000000000000000000000000000000602082015261071f908290610cfa565b606083015161072f908290610cfa565b60a083015151156107895760408051808201909152601081527f726571756573745369676e6174757265000000000000000000000000000000006020820152610779908290610cfa565b60a0830151610789908290610d48565b60c083015151156108365760408051808201909152600481527f617267730000000000000000000000000000000000000000000000000000000060208201526107d3908290610cfa565b6107dc81610d55565b60005b8360c001515181101561082c5761081c8460c00151828151811061080557610805611568565b602002602001015183610cfa90919063ffffffff16565b610825816115c6565b90506107df565b5061083681610d79565b608083015151156109375760008360200151600281111561085957610859611539565b03610890576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e000000000000000000000000000000000060208201526108cf908290610cfa565b6108e88360200151600281111561068357610683611539565b60408051808201909152600781527f73656372657473000000000000000000000000000000000000000000000000006020820152610927908290610cfa565b6080830151610937908290610d48565b60e083015151156109e45760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152610981908290610cfa565b61098a81610d55565b60005b8360e00151518110156109da576109ca8460e0015182815181106109b3576109b3611568565b602002602001015183610d4890919063ffffffff16565b6109d3816115c6565b905061098d565b506109e481610d79565b515192915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401610a519594939291906115fe565b6020604051808303816000875af1158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a94919061169e565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610b4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103c4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008060209050602083511015610bd5575081515b60005b81811015610c3b57610beb8160086116b7565b848281518110610bfd57610bfd611568565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c9290921791610c34816115c6565b9050610bd8565b5050919050565b8051600003610c7d576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83836002811115610c9057610c90611539565b90816002811115610ca357610ca3611539565b90525060408401828015610cb957610cb9611539565b90818015610cc957610cc9611539565b9052506060909301929092525050565b610ce161116b565b8051610ced9083610d97565b5060006020820152919050565b610d078260038351610e11565b81516102289082610f38565b8151610d209060c2610f60565b506105828282604051602001610d3891815260200190565b6040516020818303038152906040525b610d078260028351610e11565b610d60816004610fc9565b600181602001818151610d7391906116ce565b90525050565b610d84816007610fc9565b600181602001818151610d7391906116e1565b604080518082019091526060815260006020820152610db76020836116f4565b15610ddf57610dc76020836116f4565b610dd29060206116e1565b610ddc90836116ce565b91505b602080840183905260405180855260008152908184010181811015610e0357600080fd5b604052508290505b92915050565b60178167ffffffffffffffff1611610e3e578251610e389060e0600585901b168317610f60565b50505050565b60ff8167ffffffffffffffff1611610e80578251610e67906018611fe0600586901b1617610f60565b508251610e389067ffffffffffffffff83166001610fe0565b61ffff8167ffffffffffffffff1611610ec3578251610eaa906019611fe0600586901b1617610f60565b508251610e389067ffffffffffffffff83166002610fe0565b63ffffffff8167ffffffffffffffff1611610f08578251610eef90601a611fe0600586901b1617610f60565b508251610e389067ffffffffffffffff83166004610fe0565b8251610f1f90601b611fe0600586901b1617610f60565b508251610e389067ffffffffffffffff83166008610fe0565b604080518082019091526060815260006020820152610f5983838451611065565b9392505050565b6040805180820190915260608152600060208201528251516000610f858260016116ce565b905084602001518210610fa657610fa685610fa18360026116b7565b611154565b8451602083820101858153508051821115610fbf578181525b5093949350505050565b815161022890601f611fe0600585901b1617610f60565b604080518082019091526060815260006020820152835151600061100482856116ce565b905085602001518111156110215761102186610fa18360026116b7565b600060016110318661010061184f565b61103b91906116e1565b90508651828101878319825116178152508051831115611059578281525b50959695505050505050565b604080518082019091526060815260006020820152825182111561108857600080fd5b835151600061109784836116ce565b905085602001518111156110b4576110b486610fa18360026116b7565b8551805183820160200191600091808511156110ce578482525b505050602086015b6020861061110e57805182526110ed6020836116ce565b91506110fa6020826116ce565b90506111076020876116e1565b95506110d6565b5181517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208890036101000a0190811690199190911617905250849150509392505050565b81516111608383610d97565b50610e388382610f38565b6040518060400160405280611193604051806040016040528060608152602001600081525090565b8152602001600081525090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611216576112166111a0565b604052919050565b600067ffffffffffffffff831115611238576112386111a0565b61126960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116016111cf565b905082815283838301111561127d57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126112a557600080fd5b610f598383356020850161121e565b6000806000606084860312156112c957600080fd5b83359250602084013567ffffffffffffffff808211156112e857600080fd5b6112f487838801611294565b9350604086013591508082111561130a57600080fd5b5061131786828701611294565b9150509250925092565b60008083601f84011261133357600080fd5b50813567ffffffffffffffff81111561134b57600080fd5b60208301915083602082850101111561136357600080fd5b9250929050565b803567ffffffffffffffff8116811461138257600080fd5b919050565b60008060008060008060008060a0898b0312156113a357600080fd5b883567ffffffffffffffff808211156113bb57600080fd5b6113c78c838d01611321565b909a50985060208b01359150808211156113e057600080fd5b6113ec8c838d01611321565b909850965060408b013591508082111561140557600080fd5b818b0191508b601f83011261141957600080fd5b81358181111561142857600080fd5b8c60208260051b850101111561143d57600080fd5b60208301965080955050505061145560608a0161136a565b9150608089013590509295985092959890939650565b60006020828403121561147d57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f5957600080fd5b600067ffffffffffffffff808411156114bc576114bc6111a0565b8360051b60206114cd8183016111cf565b8681529185019181810190368411156114e557600080fd5b865b8481101561152d578035868111156114ff5760008081fd5b880136601f8201126115115760008081fd5b61151f36823587840161121e565b8452509183019183016114e7565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115f7576115f7611597565b5060010190565b67ffffffffffffffff861681526000602060a08184015286518060a085015260005b8181101561163c5788810183015185820160c001528201611620565b50600060c0828601015260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050611685604083018661ffff169052565b63ffffffff939093166060820152608001529392505050565b6000602082840312156116b057600080fd5b5051919050565b8082028115828204841417610e0b57610e0b611597565b80820180821115610e0b57610e0b611597565b81810381811115610e0b57610e0b611597565b60008261172a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b600181815b8085111561178857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561176e5761176e611597565b8085161561177b57918102915b93841c9390800290611734565b509250929050565b60008261179f57506001610e0b565b816117ac57506000610e0b565b81600181146117c257600281146117cc576117e8565b6001915050610e0b565b60ff8411156117dd576117dd611597565b50506001821b610e0b565b5060208310610133831016604e8410600b841016171561180b575081810a610e0b565b611815838361172f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561184757611847611597565b029392505050565b6000610f59838361179056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EmptyArgs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySecrets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySource\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoInlineSecrets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyRouterCanFulfill\",\"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\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"RequestSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_CALLBACK_GAS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStats\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"handleOracleFulfillment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastError\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastResponse\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resetStats\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"times\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"source\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedSecretsReferences\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"args\",\"type\":\"string[]\"},{\"internalType\":\"uint64\",\"name\":\"subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"jobId\",\"type\":\"bytes32\"}],\"name\":\"sendRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalEmptyResponses\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalFailedResponses\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSucceededResponses\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162001cc238038062001cc2833981016040819052620000349162000180565b6001600160a01b0381166080523380600081620000985760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cb57620000cb81620000d5565b50505050620001b2565b336001600160a01b038216036200012f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019357600080fd5b81516001600160a01b0381168114620001ab57600080fd5b9392505050565b608051611aed620001d56000396000818161027e0152610c220152611aed6000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063724ec8a2116100975780638da5cb5b116100665780638da5cb5b146101c3578063c59d4847146101eb578063c9429e2a14610233578063f2fde38b1461025357600080fd5b8063724ec8a21461019057806379ba509714610198578063887efe94146101a05780638aea61dc146101b357600080fd5b806347c03186116100d357806347c031861461015c5780635c1d92e91461016557806362747e421461017d5780636d9809a01461018657600080fd5b80630ca76175146100fa57806329f0de3f1461010f5780632ab424da1461012b575b600080fd5b61010d6101083660046114e5565b610266565b005b61011860045481565b6040519081526020015b60405180910390f35b6005546101479068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b61011860025481565b60055461014790640100000000900463ffffffff1681565b61011860035481565b6101476201117081565b61010d6102e5565b61010d610326565b61010d6101ae3660046115fd565b610428565b6005546101479063ffffffff1681565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b6101f36105a2565b6040805197885260208801969096529486019390935263ffffffff91821660608601528116608085015290811660a08401521660c082015260e001610122565b600554610147906c01000000000000000000000000900463ffffffff1681565b61010d6102613660046116cc565b610607565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146102d5576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102e083838361061b565b505050565b6102ed610723565b600060028190556003819055600455600580547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610430610723565b6104796040805161010081019091528060008152602001600081526020016000815260200160608152602001606081526020016060815260200160608152602001606081525090565b6104bb89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506107a69050565b85156105035761050387878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506107b79050565b831561051d5761051d6105168587611702565b8290610801565b60005b8a63ffffffff168110156105955761054561053a83610844565b856201117086610c1d565b600255600580546001919060009061056490849063ffffffff166117c9565b92506101000a81548163ffffffff021916908363ffffffff160217905550808061058d906117ed565b915050610520565b5050505050505050505050565b60008060008060008060006105b5610723565b50506002546003546004546005549298919750955063ffffffff8083169550680100000000000000008304811694506c0100000000000000000000000083048116935064010000000090920490911690565b61060f610723565b61061881610cfc565b50565b600283905561062982610df1565b60035561063581610df1565b6004558151600003610682576001600560048282829054906101000a900463ffffffff1661066391906117c9565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b8051156106ca5760016005600c8282829054906101000a900463ffffffff166106ab91906117c9565b92506101000a81548163ffffffff021916908363ffffffff1602179055505b8151158015906106d957508051155b156102e0576001600560088282829054906101000a900463ffffffff1661070091906117c9565b92506101000a81548163ffffffff021916908363ffffffff160217905550505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103a3565b565b6107b38260008084610e73565b5050565b80516000036107f2576040517fe889636f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016020830152608090910152565b805160000361083c576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c090910152565b60606000610853610100610f0a565b905061089d6040518060400160405280600c81526020017f636f64654c6f636174696f6e000000000000000000000000000000000000000081525082610f2b90919063ffffffff16565b82516108bb9060028111156108b4576108b4611825565b8290610f44565b60408051808201909152600881527f6c616e677561676500000000000000000000000000000000000000000000000060208201526108fa908290610f2b565b60408301516109119080156108b4576108b4611825565b60408051808201909152600681527f736f7572636500000000000000000000000000000000000000000000000000006020820152610950908290610f2b565b6060830151610960908290610f2b565b60a083015151156109ba5760408051808201909152601081527f726571756573745369676e61747572650000000000000000000000000000000060208201526109aa908290610f2b565b60a08301516109ba908290610f79565b60c08301515115610a675760408051808201909152600481527f61726773000000000000000000000000000000000000000000000000000000006020820152610a04908290610f2b565b610a0d81610f86565b60005b8360c0015151811015610a5d57610a4d8460c001518281518110610a3657610a36611854565b602002602001015183610f2b90919063ffffffff16565b610a56816117ed565b9050610a10565b50610a6781610faa565b60808301515115610b6857600083602001516002811115610a8a57610a8a611825565b03610ac1576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e00000000000000000000000000000000006020820152610b00908290610f2b565b610b19836020015160028111156108b4576108b4611825565b60408051808201909152600781527f73656372657473000000000000000000000000000000000000000000000000006020820152610b58908290610f2b565b6080830151610b68908290610f79565b60e08301515115610c155760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152610bb2908290610f2b565b610bbb81610f86565b60005b8360e0015151811015610c0b57610bfb8460e001518281518110610be457610be4611854565b602002602001015183610f7990919063ffffffff16565b610c04816117ed565b9050610bbe565b50610c1581610faa565b515192915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401610c82959493929190611883565b6020604051808303816000875af1158015610ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc59190611923565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610d7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103a3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008060209050602083511015610e06575081515b60005b81811015610e6c57610e1c81600861193c565b848281518110610e2e57610e2e611854565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c9290921791610e65816117ed565b9050610e09565b5050919050565b8051600003610eae576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83836002811115610ec157610ec1611825565b90816002811115610ed457610ed4611825565b90525060408401828015610eea57610eea611825565b90818015610efa57610efa611825565b9052506060909301929092525050565b610f1261139c565b8051610f1e9083610fc8565b5060006020820152919050565b610f388260038351611042565b81516102e09082611169565b8151610f519060c2611191565b506107b38282604051602001610f6991815260200190565b6040516020818303038152906040525b610f388260028351611042565b610f918160046111fa565b600181602001818151610fa49190611953565b90525050565b610fb58160076111fa565b600181602001818151610fa49190611966565b604080518082019091526060815260006020820152610fe8602083611979565b1561101057610ff8602083611979565b611003906020611966565b61100d9083611953565b91505b60208084018390526040518085526000815290818401018181101561103457600080fd5b604052508290505b92915050565b60178167ffffffffffffffff161161106f5782516110699060e0600585901b168317611191565b50505050565b60ff8167ffffffffffffffff16116110b1578251611098906018611fe0600586901b1617611191565b5082516110699067ffffffffffffffff83166001611211565b61ffff8167ffffffffffffffff16116110f45782516110db906019611fe0600586901b1617611191565b5082516110699067ffffffffffffffff83166002611211565b63ffffffff8167ffffffffffffffff161161113957825161112090601a611fe0600586901b1617611191565b5082516110699067ffffffffffffffff83166004611211565b825161115090601b611fe0600586901b1617611191565b5082516110699067ffffffffffffffff83166008611211565b60408051808201909152606081526000602082015261118a83838451611296565b9392505050565b60408051808201909152606081526000602082015282515160006111b6826001611953565b9050846020015182106111d7576111d7856111d283600261193c565b611385565b84516020838201018581535080518211156111f0578181525b5093949350505050565b81516102e090601f611fe0600585901b1617611191565b60408051808201909152606081526000602082015283515160006112358285611953565b9050856020015181111561125257611252866111d283600261193c565b6000600161126286610100611ad4565b61126c9190611966565b9050865182810187831982511617815250805183111561128a578281525b50959695505050505050565b60408051808201909152606081526000602082015282518211156112b957600080fd5b83515160006112c88483611953565b905085602001518111156112e5576112e5866111d283600261193c565b8551805183820160200191600091808511156112ff578482525b505050602086015b6020861061133f578051825261131e602083611953565b915061132b602082611953565b9050611338602087611966565b9550611307565b5181517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208890036101000a0190811690199190911617905250849150509392505050565b81516113918383610fc8565b506110698382611169565b60405180604001604052806113c4604051806040016040528060608152602001600081525090565b8152602001600081525090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611447576114476113d1565b604052919050565b600067ffffffffffffffff831115611469576114696113d1565b61149a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601611400565b90508281528383830111156114ae57600080fd5b828260208301376000602084830101529392505050565b600082601f8301126114d657600080fd5b61118a8383356020850161144f565b6000806000606084860312156114fa57600080fd5b83359250602084013567ffffffffffffffff8082111561151957600080fd5b611525878388016114c5565b9350604086013591508082111561153b57600080fd5b50611548868287016114c5565b9150509250925092565b60008083601f84011261156457600080fd5b50813567ffffffffffffffff81111561157c57600080fd5b60208301915083602082850101111561159457600080fd5b9250929050565b60008083601f8401126115ad57600080fd5b50813567ffffffffffffffff8111156115c557600080fd5b6020830191508360208260051b850101111561159457600080fd5b803567ffffffffffffffff811681146115f857600080fd5b919050565b600080600080600080600080600060c08a8c03121561161b57600080fd5b893563ffffffff8116811461162f57600080fd5b985060208a013567ffffffffffffffff8082111561164c57600080fd5b6116588d838e01611552565b909a50985060408c013591508082111561167157600080fd5b61167d8d838e01611552565b909850965060608c013591508082111561169657600080fd5b506116a38c828d0161159b565b90955093506116b6905060808b016115e0565b915060a08a013590509295985092959850929598565b6000602082840312156116de57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461118a57600080fd5b600067ffffffffffffffff8084111561171d5761171d6113d1565b8360051b602061172e818301611400565b86815291850191818101903684111561174657600080fd5b865b8481101561178e578035868111156117605760008081fd5b880136601f8201126117725760008081fd5b61178036823587840161144f565b845250918301918301611748565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8181168382160190808211156117e6576117e661179a565b5092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361181e5761181e61179a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff861681526000602060a08184015286518060a085015260005b818110156118c15788810183015185820160c0015282016118a5565b50600060c0828601015260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505061190a604083018661ffff169052565b63ffffffff939093166060820152608001529392505050565b60006020828403121561193557600080fd5b5051919050565b808202811582820484141761103c5761103c61179a565b8082018082111561103c5761103c61179a565b8181038181111561103c5761103c61179a565b6000826119af577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b600181815b80851115611a0d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119f3576119f361179a565b80851615611a0057918102915b93841c93908002906119b9565b509250929050565b600082611a245750600161103c565b81611a315750600061103c565b8160018114611a475760028114611a5157611a6d565b600191505061103c565b60ff841115611a6257611a6261179a565b50506001821b61103c565b5060208310610133831016604e8410600b8410161715611a90575081810a61103c565b611a9a83836119b4565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611acc57611acc61179a565b029392505050565b600061118a8383611a1556fea164736f6c6343000813000a", } var FunctionsLoadTestClientABI = FunctionsLoadTestClientMetaData.ABI @@ -193,31 +193,81 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) MAXCALLBAC return _FunctionsLoadTestClient.Contract.MAXCALLBACKGAS(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) GetStats(opts *bind.CallOpts) ([32]byte, [32]byte, [32]byte, uint32, uint32, uint32, uint32, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "owner") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "getStats") if err != nil { - return *new(common.Address), err + return *new([32]byte), *new([32]byte), *new([32]byte), *new(uint32), *new(uint32), *new(uint32), *new(uint32), err } - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out1 := *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + out2 := *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + out3 := *abi.ConvertType(out[3], new(uint32)).(*uint32) + out4 := *abi.ConvertType(out[4], new(uint32)).(*uint32) + out5 := *abi.ConvertType(out[5], new(uint32)).(*uint32) + out6 := *abi.ConvertType(out[6], new(uint32)).(*uint32) + + return out0, out1, out2, out3, out4, out5, out6, err + +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) GetStats() ([32]byte, [32]byte, [32]byte, uint32, uint32, uint32, uint32, error) { + return _FunctionsLoadTestClient.Contract.GetStats(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) GetStats() ([32]byte, [32]byte, [32]byte, uint32, uint32, uint32, uint32, error) { + return _FunctionsLoadTestClient.Contract.GetStats(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) LastError(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "lastError") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) Owner() (common.Address, error) { - return _FunctionsLoadTestClient.Contract.Owner(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) LastError() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastError(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) Owner() (common.Address, error) { - return _FunctionsLoadTestClient.Contract.Owner(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) LastError() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastError(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) LastRequestID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "lastRequestID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastError(opts *bind.CallOpts) ([32]byte, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) LastRequestID() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastRequestID(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) LastRequestID() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastRequestID(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) LastResponse(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "s_lastError") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "lastResponse") if err != nil { return *new([32]byte), err @@ -229,17 +279,39 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastError(opts * } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SLastError() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastError(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) LastResponse() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastResponse(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) LastResponse() ([32]byte, error) { + return _FunctionsLoadTestClient.Contract.LastResponse(&_FunctionsLoadTestClient.CallOpts) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FunctionsLoadTestClient.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 (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) Owner() (common.Address, error) { + return _FunctionsLoadTestClient.Contract.Owner(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) SLastError() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastError(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) Owner() (common.Address, error) { + return _FunctionsLoadTestClient.Contract.Owner(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastErrorLength(opts *bind.CallOpts) (uint32, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) TotalEmptyResponses(opts *bind.CallOpts) (uint32, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "s_lastErrorLength") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "totalEmptyResponses") if err != nil { return *new(uint32), err @@ -251,61 +323,61 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastErrorLength( } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SLastErrorLength() (uint32, error) { - return _FunctionsLoadTestClient.Contract.SLastErrorLength(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) TotalEmptyResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalEmptyResponses(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) SLastErrorLength() (uint32, error) { - return _FunctionsLoadTestClient.Contract.SLastErrorLength(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) TotalEmptyResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalEmptyResponses(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastRequestId(opts *bind.CallOpts) ([32]byte, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) TotalFailedResponses(opts *bind.CallOpts) (uint32, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "s_lastRequestId") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "totalFailedResponses") if err != nil { - return *new([32]byte), err + return *new(uint32), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) return out0, err } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SLastRequestId() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastRequestId(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) TotalFailedResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalFailedResponses(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) SLastRequestId() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastRequestId(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) TotalFailedResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalFailedResponses(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastResponse(opts *bind.CallOpts) ([32]byte, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) TotalRequests(opts *bind.CallOpts) (uint32, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "s_lastResponse") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "totalRequests") if err != nil { - return *new([32]byte), err + return *new(uint32), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) return out0, err } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SLastResponse() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastResponse(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) TotalRequests() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalRequests(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) SLastResponse() ([32]byte, error) { - return _FunctionsLoadTestClient.Contract.SLastResponse(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) TotalRequests() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalRequests(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastResponseLength(opts *bind.CallOpts) (uint32, error) { +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) TotalSucceededResponses(opts *bind.CallOpts) (uint32, error) { var out []interface{} - err := _FunctionsLoadTestClient.contract.Call(opts, &out, "s_lastResponseLength") + err := _FunctionsLoadTestClient.contract.Call(opts, &out, "totalSucceededResponses") if err != nil { return *new(uint32), err @@ -317,12 +389,12 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClientCaller) SLastResponseLeng } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SLastResponseLength() (uint32, error) { - return _FunctionsLoadTestClient.Contract.SLastResponseLength(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) TotalSucceededResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalSucceededResponses(&_FunctionsLoadTestClient.CallOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) SLastResponseLength() (uint32, error) { - return _FunctionsLoadTestClient.Contract.SLastResponseLength(&_FunctionsLoadTestClient.CallOpts) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientCallerSession) TotalSucceededResponses() (uint32, error) { + return _FunctionsLoadTestClient.Contract.TotalSucceededResponses(&_FunctionsLoadTestClient.CallOpts) } func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { @@ -349,16 +421,28 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactorSession) Handle return _FunctionsLoadTestClient.Contract.HandleOracleFulfillment(&_FunctionsLoadTestClient.TransactOpts, requestId, response, err) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactor) SendRequest(opts *bind.TransactOpts, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { - return _FunctionsLoadTestClient.contract.Transact(opts, "sendRequest", source, encryptedSecretsReferences, args, subscriptionId, jobId) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactor) ResetStats(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FunctionsLoadTestClient.contract.Transact(opts, "resetStats") +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) ResetStats() (*types.Transaction, error) { + return _FunctionsLoadTestClient.Contract.ResetStats(&_FunctionsLoadTestClient.TransactOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SendRequest(source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { - return _FunctionsLoadTestClient.Contract.SendRequest(&_FunctionsLoadTestClient.TransactOpts, source, encryptedSecretsReferences, args, subscriptionId, jobId) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactorSession) ResetStats() (*types.Transaction, error) { + return _FunctionsLoadTestClient.Contract.ResetStats(&_FunctionsLoadTestClient.TransactOpts) } -func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactorSession) SendRequest(source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { - return _FunctionsLoadTestClient.Contract.SendRequest(&_FunctionsLoadTestClient.TransactOpts, source, encryptedSecretsReferences, args, subscriptionId, jobId) +func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactor) SendRequest(opts *bind.TransactOpts, times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { + return _FunctionsLoadTestClient.contract.Transact(opts, "sendRequest", times, source, encryptedSecretsReferences, args, subscriptionId, jobId) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientSession) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { + return _FunctionsLoadTestClient.Contract.SendRequest(&_FunctionsLoadTestClient.TransactOpts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) +} + +func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactorSession) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) { + return _FunctionsLoadTestClient.Contract.SendRequest(&_FunctionsLoadTestClient.TransactOpts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) } func (_FunctionsLoadTestClient *FunctionsLoadTestClientTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { @@ -938,23 +1022,31 @@ func (_FunctionsLoadTestClient *FunctionsLoadTestClient) Address() common.Addres type FunctionsLoadTestClientInterface interface { MAXCALLBACKGAS(opts *bind.CallOpts) (uint32, error) - Owner(opts *bind.CallOpts) (common.Address, error) + GetStats(opts *bind.CallOpts) ([32]byte, [32]byte, [32]byte, uint32, uint32, uint32, uint32, error) - SLastError(opts *bind.CallOpts) ([32]byte, error) + LastError(opts *bind.CallOpts) ([32]byte, error) - SLastErrorLength(opts *bind.CallOpts) (uint32, error) + LastRequestID(opts *bind.CallOpts) ([32]byte, error) - SLastRequestId(opts *bind.CallOpts) ([32]byte, error) + LastResponse(opts *bind.CallOpts) ([32]byte, error) - SLastResponse(opts *bind.CallOpts) ([32]byte, error) + Owner(opts *bind.CallOpts) (common.Address, error) + + TotalEmptyResponses(opts *bind.CallOpts) (uint32, error) + + TotalFailedResponses(opts *bind.CallOpts) (uint32, error) - SLastResponseLength(opts *bind.CallOpts) (uint32, error) + TotalRequests(opts *bind.CallOpts) (uint32, error) + + TotalSucceededResponses(opts *bind.CallOpts) (uint32, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) HandleOracleFulfillment(opts *bind.TransactOpts, requestId [32]byte, response []byte, err []byte) (*types.Transaction, error) - SendRequest(opts *bind.TransactOpts, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) + ResetStats(opts *bind.TransactOpts) (*types.Transaction, error) + + SendRequest(opts *bind.TransactOpts, times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 818c5bc3d1c..46f10db9d5d 100644 --- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,7 +5,7 @@ functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions functions_client: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca functions_client_example: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsClientExample.bin 25036bdb94a50a81df4222418bf9aa1e0c8540d5834b7e6e639aa63a2a2c8206 functions_coordinator: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsCoordinator.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsCoordinator.bin e453fd45029ff99658d029bfbb8711b748c432323f12585c039a30977e801a79 -functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsLoadTestClient.bin 28f2834dea12b3aefa7c696b64ca5272a1ab5cdf33365c9f7fafdc0b7d5669e8 +functions_load_test_client: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsLoadTestClient.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsLoadTestClient.bin 08b0ba467a0d2913ad146c293cc92ed1e0e5f25398bc8185addf9c4c1a41df2c functions_oracle_events_mock: ../../../contracts/solc/v0.8.6/functions/0_0_0/FunctionsOracleEventsMock.abi ../../../contracts/solc/v0.8.6/functions/0_0_0/FunctionsOracleEventsMock.bin 3ca70f966f8fe751987f0ccb50bebb6aa5be77e4a9f835d1ae99e0e9bfb7d52c functions_router: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsRouter.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsRouter.bin dd1d3527e19d65efe029c4a131ded44dc0ca961e5c4f459743992435431ec478 functions_v1_events_mock: ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsV1EventsMock.abi ../../../contracts/solc/v0.8.19/functions/1_0_0/FunctionsV1EventsMock.bin 0f0ba42e0cc33c7abc8b8fd4fdfce903748a169886dd5f16cfdd56e75bcf708d diff --git a/core/scripts/go.mod b/core/scripts/go.mod index ef70cdc20fe..2a81e2bb05b 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -284,7 +284,7 @@ require ( github.com/prometheus/procfs v0.11.0 // indirect github.com/prometheus/prometheus v0.46.0 // indirect github.com/pyroscope-io/client v0.7.1 // indirect - github.com/pyroscope-io/godeltaprof v0.1.0 // indirect + github.com/pyroscope-io/godeltaprof v0.1.2 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rjeczalik/notify v0.9.3 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 5680f6e6619..708688e5e1f 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1310,8 +1310,8 @@ github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIsc github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= -github.com/pyroscope-io/godeltaprof v0.1.0 h1:UBqtjt0yZi4jTxqZmLAs34XG6ycS3vUTlhEUSq4NHLE= -github.com/pyroscope-io/godeltaprof v0.1.0/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= +github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= +github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/integration-tests/chaos/functions/full.yaml b/integration-tests/chaos/functions/full.yaml new file mode 100644 index 00000000000..9d62f899c62 --- /dev/null +++ b/integration-tests/chaos/functions/full.yaml @@ -0,0 +1,232 @@ +apiVersion: chaos-mesh.org/v1alpha1 +kind: Workflow +metadata: + namespace: chainlink + name: chainlink-flow +spec: + entry: entry + templates: + # root entry + - name: entry + templateType: Serial + deadline: 1h + children: + - killing + - network-delay-internal +# - external-deps-failure + # children chaos group + - name: killing + templateType: Serial + children: + - gateway-kill + - don-minority-kill + - don-majority-kill + - adapters-minority-kill + - adapters-majority-kill + # children chaos group + - name: network-delay-internal + templateType: Serial + children: + - gateway-delay + - don-minority-delay + - don-majority-delay + - adapters-minority-delay + - adapters-majority-delay + # children chaos group + - name: external-deps-failure + templateType: Serial + children: + - ea-url-resolve-failure + + # experiments (killing) + - name: gateway-kill + templateType: PodChaos + deadline: 1m + podChaos: + selector: + namespaces: + - chainlink + labelSelectors: + 'app.kubernetes.io/instance': cln-gateway-staging1-node + mode: one + action: pod-kill + - name: don-minority-kill + templateType: PodChaos + deadline: 1m + podChaos: + selector: + namespaces: + - chainlink + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - clc-ocr2-dr-matic-testnet-nodes-0 + - clc-ocr2-dr-matic-testnet-boot + mode: all + action: pod-kill + - name: don-majority-kill + templateType: PodChaos + deadline: 1m + podChaos: + selector: + namespaces: + - chainlink + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - clc-ocr2-dr-matic-testnet-nodes-1 + - clc-ocr2-dr-matic-testnet-nodes-0 + - clc-ocr2-dr-matic-testnet-boot + mode: all + action: pod-kill + - name: adapters-minority-kill + templateType: PodChaos + deadline: 1m + podChaos: + selector: + namespaces: + - adapters + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - universal-mumbai-0 + mode: all + action: pod-kill + - name: adapters-majority-kill + templateType: PodChaos + deadline: 1m + podChaos: + selector: + namespaces: + - adapters + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - universal-mumbai-1 + - universal-mumbai-0 + mode: all + action: pod-kill + + # TODO: enable when chaosd is installed on all the nodes + # experiments (delays) + - name: gateway-delay + templateType: NetworkChaos + deadline: 1m + networkChaos: + selector: + namespaces: + - chainlink + labelSelectors: + 'app.kubernetes.io/instance': cln-gateway-staging1-node + mode: all + action: delay + delay: + latency: 200ms + correlation: '0' + jitter: 0ms + direction: to + - name: don-minority-delay + templateType: NetworkChaos + deadline: 1m + networkChaos: + selector: + namespaces: + - chainlink + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - clc-ocr2-dr-matic-testnet-nodes-0 + - clc-ocr2-dr-matic-testnet-boot + mode: all + action: delay + delay: + latency: 200ms + correlation: '0' + jitter: 0ms + direction: to + - name: don-majority-delay + templateType: NetworkChaos + deadline: 1m + networkChaos: + selector: + namespaces: + - chainlink + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - clc-ocr2-dr-matic-testnet-nodes-1 + - clc-ocr2-dr-matic-testnet-nodes-0 + - clc-ocr2-dr-matic-testnet-boot + mode: all + action: delay + delay: + latency: 200ms + correlation: '0' + jitter: 0ms + direction: to + - name: adapters-minority-delay + templateType: NetworkChaos + deadline: 1m + networkChaos: + selector: + namespaces: + - adapters + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - universal-mumbai-0 + mode: all + action: delay + delay: + latency: 200ms + correlation: '0' + jitter: 0ms + direction: to + - name: adapters-majority-delay + templateType: NetworkChaos + deadline: 1m + networkChaos: + selector: + namespaces: + - adapters + expressionSelectors: + - key: app.kubernetes.io/instance + operator: In + values: + - universal-mumbai-1 + - universal-mumbai-0 + mode: all + action: delay + delay: + latency: 200ms + correlation: '0' + jitter: 0ms + direction: to + + # experiments (external deps failure) +# - name: ea-url-resolve-failure +# templateType: NetworkChaos +# deadline: 3m +# networkChaos: +# selector: +# namespaces: +# - chainlink +# mode: all +# action: partition +# direction: to +# target: +# selector: +# namespaces: +# - chainlink +# mode: all +# externalTargets: +# - >- +# my-url.com + diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go index 6fd34a9a3fe..941eba73ebf 100644 --- a/integration-tests/contracts/contract_models.go +++ b/integration-tests/contracts/contract_models.go @@ -351,6 +351,8 @@ type AuthorizedForwarder interface { type FunctionsCoordinator interface { Address() string + GetThresholdPublicKey() ([]byte, error) + GetDONPublicKey() ([]byte, error) } type FunctionsRouter interface { @@ -360,5 +362,7 @@ type FunctionsRouter interface { type FunctionsLoadTestClient interface { Address() string - SendRequest(source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error + ResetStats() error + GetStats() (*EthereumFunctionsLoadStats, error) + SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error } diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index 0aebd60560f..8f80ed3896c 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -25,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_client_example" "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" @@ -2113,7 +2112,7 @@ func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string return 0, err } for _, l := range r.Logs { - log.Warn().Interface("Log", common.Bytes2Hex(l.Data)).Send() + log.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() } topicsMap := map[string]interface{}{} @@ -2122,14 +2121,14 @@ func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string return 0, err } for _, ev := range fabi.Events { - log.Warn().Str("EventName", ev.Name).Send() + log.Info().Str("EventName", ev.Name).Send() } topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} topicOneHash := []common.Hash{r.Logs[0].Topics[1:][0]} if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { return 0, errors.Wrap(err, "failed to decode topic value") } - log.Warn().Interface("NewTopicsDecoded", topicsMap).Send() + log.Info().Interface("NewTopicsDecoded", topicsMap).Send() if topicsMap["subscriptionId"] == 0 { return 0, errors.New("failed to decode subscription ID after creation") } @@ -2142,6 +2141,22 @@ type EthereumFunctionsCoordinator struct { instance *functions_coordinator.FunctionsCoordinator } +func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { + opts := &bind.CallOpts{ + From: common.HexToAddress(e.client.GetDefaultWallet().Address()), + Context: context.Background(), + } + return e.instance.GetThresholdPublicKey(opts) +} + +func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { + opts := &bind.CallOpts{ + From: common.HexToAddress(e.client.GetDefaultWallet().Address()), + Context: context.Background(), + } + return e.instance.GetDONPublicKey(opts) +} + func (e *EthereumFunctionsCoordinator) Address() string { return e.address.Hex() } @@ -2156,19 +2171,64 @@ func (e *EthereumFunctionsLoadTestClient) Address() string { return e.address.Hex() } -func (e *EthereumFunctionsLoadTestClient) SendRequest(source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { +type EthereumFunctionsLoadStats struct { + LastRequestID string + LastResponse string + LastError string + Total uint32 + Succeeded uint32 + Errored uint32 + Empty uint32 +} + +func Bytes32ToSlice(a [32]byte) (r []byte) { + r = append(r, a[:]...) + return +} + +func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { + opts := &bind.CallOpts{ + From: common.HexToAddress(e.client.GetDefaultWallet().Address()), + Context: context.Background(), + } + lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(opts) + if err != nil { + return nil, err + } + return &EthereumFunctionsLoadStats{ + LastRequestID: string(Bytes32ToSlice(lr)), + LastResponse: string(Bytes32ToSlice(lbody)), + LastError: string(Bytes32ToSlice(lerr)), + Total: total, + Succeeded: succeeded, + Errored: errored, + Empty: empty, + }, nil +} + +func (e *EthereumFunctionsLoadTestClient) ResetStats() error { opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err } - tx, err := e.instance.SendRequest(opts, source, encryptedSecretsReferences, args, subscriptionId, jobId) + tx, err := e.instance.ResetStats(opts) if err != nil { return err } if err := e.client.ProcessTransaction(tx); err != nil { return err } - revertReason, _, _ := e.client.RevertReasonFromTx(tx.Hash(), functions_client_example.FunctionsClientExampleABI) - log.Debug().Str("RevertReason", revertReason).Send() return nil } + +func (e *EthereumFunctionsLoadTestClient) 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 + } + tx, err := e.instance.SendRequest(opts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) + if err != nil { + return err + } + return e.client.ProcessTransaction(tx) +} diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e1384facb91..bb9bf9cfff0 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -20,11 +20,12 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-env v0.36.0 - github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230828224428-5b8a157a94d0 + github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20230816220705-665e93233ae5 github.com/smartcontractkit/ocr2keepers v0.7.19 github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 + github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230829114801-14bf715f805e github.com/smartcontractkit/wasp v0.3.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.4 @@ -158,12 +159,12 @@ require ( github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/analysis v0.21.4 // indirect github.com/go-openapi/errors v0.20.3 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/spec v0.20.8 // indirect + github.com/go-openapi/spec v0.20.9 // indirect github.com/go-openapi/strfmt v0.21.7 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/go-openapi/validate v0.22.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -386,7 +387,6 @@ require ( github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918 // indirect github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230829114801-14bf715f805e // indirect - github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230829114801-14bf715f805e // indirect github.com/smartcontractkit/wsrpc v0.7.2 // indirect github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 20be19c04f0..87b904bceb4 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1014,8 +1014,9 @@ github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2uj github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -1025,8 +1026,8 @@ github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8en github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= -github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= @@ -1035,8 +1036,9 @@ github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KA github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= @@ -2247,8 +2249,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97ac github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97aca/go.mod h1:RIUJXn7EVp24TL2p4FW79dYjyno23x5mjt1nKN+5WEk= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918 h1:ByVauKFXphRlSNG47lNuxZ9aicu+r8AoNp933VRPpCw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918/go.mod h1:/yp/sqD8Iz5GU5fcercjrw0ivJF7HDcupYg+Gjr7EPg= -github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230828224428-5b8a157a94d0 h1:DvIwUQc3/yWlvuXD/t30aOyX5BPVomM7OQT8ZO9VFFo= -github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230828224428-5b8a157a94d0/go.mod h1:t6FJX3akEfAO31p96ru0ilNPfE9P2UshUlXTIkI58LM= +github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c h1:8/L+5JupikVsMga6z0WBElp1RgRO6BB5BF+QsBsSrOI= +github.com/smartcontractkit/chainlink-testing-framework v1.16.1-0.20230829222228-4afd1b3d385c/go.mod h1:t6FJX3akEfAO31p96ru0ilNPfE9P2UshUlXTIkI58LM= github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472 h1:x3kNwgFlDmbE/n0gTSRMt9GBDfsfGrs4X9b9arPZtFI= github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/functions/README.md b/integration-tests/load/functions/README.md index ec94b9ded0a..6b80137cf48 100644 --- a/integration-tests/load/functions/README.md +++ b/integration-tests/load/functions/README.md @@ -1,12 +1,53 @@ -### Functions Load tests +### Functions & S4 Gateway Load tests -## Usage +## Setup +Export vars ``` +export SELECTED_NETWORKS=MUMBAI +export MUMBAI_KEYS=... +export MUMBAI_URLS=... export LOKI_TOKEN=... export LOKI_URL=... +``` +See more config options in [config.toml](./config.toml) +## Usage + +Soak `1 TX/sec - 40 requests per TX` +``` go test -v -run TestFunctionsLoad/functions_soak_test ``` +Stress `1 TX/sec - 78 requests per TX` (max gas) +``` +go test -v -run TestFunctionsLoad/functions_stress_test +``` +Gateway `secrets_list` test +``` +go test -v -timeout 24h -run TestGatewayLoad/gateway_secrets_list_soak_test +``` +Gateway `secrets_set` test +``` +go test -v -timeout 24h -run TestGatewayLoad/gateway_secrets_set_soak_test +``` + +Chaos suite can be combined with any test, can be found [here](../../chaos/functions/full.yaml) + +Default [dashboard](https://chainlinklabs.grafana.net/d/FunctionsV1/functionsv1?orgId=1&from=now-5m&to=now&var-go_test_name=All&var-gen_name=All&var-branch=All&var-commit=All&var-call_group=All&refresh=5s) + +## Redeploying client and funding a new sub +When contracts got redeployed on `Mumbai` just comment these lines in config +``` +# comment both client and sub to automatically create a new pair +client_addr = "0x64a351fbAa61681A5a7e569Cc5A691150c4D73D2" +subscription_id = 23 +``` +Then insert new client addr and subscription number back + +## Debug +Show more logs +``` +export WASP_LOG_LEVEL=debug +``` ### Dashboards diff --git a/integration-tests/load/functions/config.go b/integration-tests/load/functions/config.go index baba37d2c82..9f0a5bda0c7 100644 --- a/integration-tests/load/functions/config.go +++ b/integration-tests/load/functions/config.go @@ -17,21 +17,26 @@ const ( ) type PerformanceConfig struct { - Soak *Soak `toml:"Soak"` - Load *Load `toml:"Load"` - SoakVolume *SoakVolume `toml:"SoakVolume"` - LoadVolume *LoadVolume `toml:"LoadVolume"` - Common *Common `toml:"Common"` + Soak *Soak `toml:"Soak"` + Stress *Stress `toml:"Stress"` + GatewayListSoak *GatewayListSoak `toml:"GatewayListSoak"` + GatewaySetSoak *GatewaySetSoak `toml:"GatewaySetSoak"` + Common *Common `toml:"Common"` + MumbaiPrivateKey string } type Common struct { Funding - LINKTokenAddr string `toml:"link_token_addr"` - Coordinator string `toml:"coordinator_addr"` - Router string `toml:"router_addr"` - LoadTestClient string `toml:"client_example_addr"` - SubscriptionID uint64 `toml:"subscription_id"` - DONID string `toml:"don_id"` + LINKTokenAddr string `toml:"link_token_addr"` + Coordinator string `toml:"coordinator_addr"` + Router string `toml:"router_addr"` + LoadTestClient string `toml:"client_addr"` + SubscriptionID uint64 `toml:"subscription_id"` + DONID string `toml:"don_id"` + GatewayURL string `toml:"gateway_url"` + Receiver string `toml:"receiver"` + FunctionsCallPayload string `toml:"functions_call_payload"` + Secrets string `toml:"secrets"` } type Funding struct { @@ -40,29 +45,25 @@ type Funding struct { } type Soak struct { - RPS int64 `toml:"rps"` - Duration *models.Duration `toml:"duration"` + RPS int64 `toml:"rps"` + RequestsPerCall uint32 `toml:"requests_per_call"` + Duration *models.Duration `toml:"duration"` } -type SoakVolume struct { - Products int64 `toml:"products"` - Pace *models.Duration `toml:"pace"` - Duration *models.Duration `toml:"duration"` +type Stress struct { + RPS int64 `toml:"rps"` + RequestsPerCall uint32 `toml:"requests_per_call"` + Duration *models.Duration `toml:"duration"` } -type Load struct { - RPSFrom int64 `toml:"rps_from"` - RPSIncrease int64 `toml:"rps_increase"` - RPSSteps int `toml:"rps_steps"` - Duration *models.Duration `toml:"duration"` +type GatewayListSoak struct { + RPS int64 `toml:"rps"` + Duration *models.Duration `toml:"duration"` } -type LoadVolume struct { - ProductsFrom int64 `toml:"products_from"` - ProductsIncrease int64 `toml:"products_increase"` - ProductsSteps int `toml:"products_steps"` - Pace *models.Duration `toml:"pace"` - Duration *models.Duration `toml:"duration"` +type GatewaySetSoak struct { + RPS int64 `toml:"rps"` + Duration *models.Duration `toml:"duration"` } func ReadConfig() (*PerformanceConfig, error) { @@ -76,5 +77,15 @@ func ReadConfig() (*PerformanceConfig, error) { return nil, errors.Wrap(err, ErrUnmarshalPerfConfig) } log.Debug().Interface("PerformanceConfig", cfg).Msg("Parsed performance config") + mpk := os.Getenv("MUMBAI_KEYS") + murls := os.Getenv("MUMBAI_URLS") + snet := os.Getenv("SELECTED_NETWORKS") + if mpk == "" || murls == "" || snet == "" { + return nil, errors.New( + "ensure variables are set:\nMUMBAI_KEYS variable, private keys, comma separated\nSELECTED_NETWORKS=MUMBAI\nMUMBAI_URLS variable, websocket urls, comma separated", + ) + } else { + cfg.MumbaiPrivateKey = mpk + } return cfg, nil } diff --git a/integration-tests/load/functions/config.toml b/integration-tests/load/functions/config.toml index 14cedcd9a5d..a5cf4dbb379 100644 --- a/integration-tests/load/functions/config.toml +++ b/integration-tests/load/functions/config.toml @@ -1,34 +1,35 @@ [Soak] rps = 1 -duration = "1h" +requests_per_call = 40 +duration = "10m" -[Load] -rps_from = 1 -rps_increase = 1 -rps_steps = 10 -duration = "3m" +[Stress] +rps = 1 +requests_per_call = 78 +duration = "10m" -[SoakVolume] -products = 5 -pace = "1s" -duration = "3m" +[GatewayListSoak] +rps = 95 +duration = "10m" -[LoadVolume] -products_from = 1 -products_increase = 1 -products_steps = 10 -pace = "1s" -duration = "3m" +[GatewaySetSoak] +rps = 95 +duration = "10m" [Common] # Polygon Mumbai only for now +receiver = "0x3098B6665589959711A48a6bAe5B7F2908f6a3bE" +don_id = "fun-staging-mumbai-1" +gateway_url = "https://gateway-staging1.main.stage.cldev.sh" link_token_addr = "0x326C977E6efc84E512bB9C30f76E30c160eD06FB" -coordinator_addr = "0x69b4C680209737B877c93327fC2144ec39eaC423" -router_addr = "0xa4Ac8b863A6b4fB064B6bdF87aD61d389d97748d" -client_example_addr = "0x2720cC3a112d33B5C1D40270f7c7BE7CADec1690" -don_id = "functions_staging_mumbai" -# comment it to automatically create and fund a new one -subscription_id = 48 -# not used until we have full DON setup -# node_funds = 10 -sub_funds = 7 \ No newline at end of file +coordinator_addr = "0x6D6a83BB356b7242E88C1A2b290102fde26590D0" +router_addr = "0x2673266D3Cd08b53494B5a92B66DEec7F1408E7A" +# comment both client and sub to automatically create a new pair +client_addr = "0x64a351fbAa61681A5a7e569Cc5A691150c4D73D2" +subscription_id = 23 +sub_funds = 10 + +functions_call_payload = "const response = await Functions.makeHttpRequest({ url: 'http://dummyjson.com/products/1' }); return Functions.encodeUint256(response.data.id)" +#functions_call_payload = "return Functions.encodeUint256(BigInt(secrets.ltsecret))" +# uncomment to upload new secrets to s4 +#secrets = "{\"ltsecret\": \"1\"}" \ No newline at end of file diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index 656c3b80ec1..16311ac440b 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -10,52 +10,69 @@ import ( func TestFunctionsLoad(t *testing.T) { cfg, err := ReadConfig() require.NoError(t, err) - env, functionContracts, err := SetupLocalLoadTestEnv(cfg) + ft, err := SetupLocalLoadTestEnv(cfg) require.NoError(t, err) - env.ParallelTransactions(true) + ft.EVMClient.ParallelTransactions(false) labels := map[string]string{ "branch": "functions_healthcheck", "commit": "functions_healthcheck", } - singleFeedConfig := &wasp.Config{ - T: t, - LoadType: wasp.RPS, - GenName: "gun", - CallTimeout: 2 * time.Minute, - Gun: NewSingleFunctionCallGun( - functionContracts, - "const response = await Functions.makeHttpRequest({ url: 'http://dummyjson.com/products/1' }); return Functions.encodeUint256(response.data.id)", - []byte{}, - []string{}, - cfg.Common.SubscriptionID, - StringToByte32(cfg.Common.DONID), - ), - Labels: labels, - LokiConfig: wasp.NewEnvLokiConfig(), - } + MonitorLoadStats(t, ft, labels) t.Run("functions soak test", func(t *testing.T) { - singleFeedConfig.Schedule = wasp.Plain( - cfg.Soak.RPS, - cfg.Soak.Duration.Duration(), - ) _, err := wasp.NewProfile(). - Add(wasp.NewGenerator(singleFeedConfig)). + Add(wasp.NewGenerator(&wasp.Config{ + T: t, + LoadType: wasp.RPS, + GenName: "functions_soak_gen", + RateLimitUnitDuration: 5 * time.Second, + CallTimeout: 3 * time.Minute, + Schedule: wasp.Plain( + cfg.Soak.RPS, + cfg.Soak.Duration.Duration(), + ), + Gun: NewSingleFunctionCallGun( + ft, + cfg.Soak.RequestsPerCall, + cfg.Common.FunctionsCallPayload, + []byte{}, + []string{}, + cfg.Common.SubscriptionID, + StringToByte32(cfg.Common.DONID), + ), + Labels: labels, + LokiConfig: wasp.NewEnvLokiConfig(), + })). Run(true) require.NoError(t, err) }) - t.Run("functions load test", func(t *testing.T) { - singleFeedConfig.Schedule = wasp.Steps( - cfg.Load.RPSFrom, - cfg.Load.RPSIncrease, - cfg.Load.RPSSteps, - cfg.Load.Duration.Duration(), - ) + t.Run("functions stress test", func(t *testing.T) { _, err = wasp.NewProfile(). - Add(wasp.NewGenerator(singleFeedConfig)). + Add(wasp.NewGenerator(&wasp.Config{ + T: t, + LoadType: wasp.RPS, + GenName: "functions_stress_gen", + RateLimitUnitDuration: 5 * time.Second, + CallTimeout: 3 * time.Minute, + Schedule: wasp.Plain( + cfg.Stress.RPS, + cfg.Stress.Duration.Duration(), + ), + Gun: NewSingleFunctionCallGun( + ft, + cfg.Stress.RequestsPerCall, + cfg.Common.FunctionsCallPayload, + []byte{}, + []string{}, + cfg.Common.SubscriptionID, + StringToByte32(cfg.Common.DONID), + ), + Labels: labels, + LokiConfig: wasp.NewEnvLokiConfig(), + })). Run(true) require.NoError(t, err) }) diff --git a/integration-tests/load/functions/gateway.go b/integration-tests/load/functions/gateway.go new file mode 100644 index 00000000000..12406c79eb1 --- /dev/null +++ b/integration-tests/load/functions/gateway.go @@ -0,0 +1,227 @@ +package loadfunctions + +import ( + "bytes" + "crypto/ecdsa" + "crypto/rand" + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/ecies" + "github.com/go-resty/resty/v2" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" + "github.com/smartcontractkit/chainlink/v2/core/services/s4" + "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" + "time" +) + +type RPCResponse struct { + ID string `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result struct { + Body struct { + DonID string `json:"don_id"` + MessageID string `json:"message_id"` + Method string `json:"method"` + Payload struct { + NodeResponses []struct { + Body struct { + DonID string `json:"don_id"` + MessageID string `json:"message_id"` + Method string `json:"method"` + Payload struct { + Success bool `json:"success"` + } `json:"payload"` + Receiver string `json:"receiver"` + } `json:"body"` + Signature string `json:"signature"` + } `json:"node_responses"` + Success bool `json:"success"` + } `json:"payload"` + Receiver string `json:"receiver"` + } `json:"body"` + Signature string `json:"signature"` + } `json:"result"` +} + +func UploadS4Secrets(rc *resty.Client, s4Cfg *S4SecretsCfg) error { + key, err := crypto.HexToECDSA(s4Cfg.PrivateKey) + if err != nil { + return err + } + address := crypto.PubkeyToAddress(key.PublicKey) + var payloadJSON []byte + if s4Cfg.Method == functions.MethodSecretsSet { + envelope := s4.Envelope{ + Address: address.Bytes(), + SlotID: s4Cfg.S4SetSlotID, + Version: s4Cfg.S4SetVersion, + Payload: []byte(s4Cfg.S4SetPayload), + Expiration: time.Now().UnixMilli() + s4Cfg.S4SetExpirationPeriod, + } + signature, err := envelope.Sign(key) + if err != nil { + return err + } + + s4SetPayload := functions.SecretsSetRequest{ + SlotID: envelope.SlotID, + Version: envelope.Version, + Expiration: envelope.Expiration, + Payload: []byte(s4Cfg.S4SetPayload), + Signature: signature, + } + + payloadJSON, err = json.Marshal(s4SetPayload) + if err != nil { + return err + } + } + + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: s4Cfg.MessageID, + Method: s4Cfg.Method, + DonId: s4Cfg.DonID, + Payload: json.RawMessage(payloadJSON), + }, + } + + err = msg.Sign(key) + if err != nil { + return err + } + codec := api.JsonRPCCodec{} + rawMsg, err := codec.EncodeRequest(msg) + if err != nil { + return err + } + var result *RPCResponse + resp, err := rc.R(). + SetBody(rawMsg). + Post(s4Cfg.GatewayURL) + if err != nil { + return err + } + if resp.StatusCode() != 200 { + return fmt.Errorf("status code was %d, expected 200", resp.StatusCode()) + } + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return err + } + log.Debug().Interface("Result", result).Msg("S4 secrets_set response result") + for _, nodeResponse := range result.Result.Body.Payload.NodeResponses { + if !nodeResponse.Body.Payload.Success { + return fmt.Errorf("node response was not succesful") + } + } + return nil +} + +func ListS4Secrets(rc *resty.Client, s4Cfg *S4SecretsCfg) error { + key, err := crypto.HexToECDSA(s4Cfg.PrivateKey) + if err != nil { + return err + } + + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: s4Cfg.MessageID, + Method: s4Cfg.Method, + DonId: s4Cfg.DonID, + Receiver: s4Cfg.RecieverAddr, + }, + } + + err = msg.Sign(key) + if err != nil { + return err + } + codec := api.JsonRPCCodec{} + rawMsg, err := codec.EncodeRequest(msg) + if err != nil { + return err + } + msgdec, err := codec.DecodeRequest(rawMsg) + if err != nil { + return err + } + log.Debug().Interface("Request", msgdec).Msg("Sending RPC request") + var result map[string]interface{} + resp, err := rc.R(). + SetBody(rawMsg). + Post(s4Cfg.GatewayURL) + if err != nil { + return err + } + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return err + } + log.Debug().Interface("Result", result).Msg("S4 secrets_list response result") + if resp.StatusCode() != 200 { + return fmt.Errorf("status code was %d, expected 200", resp.StatusCode()) + } + return nil +} + +func ParseTDH2Key(data []byte) (*tdh2easy.PublicKey, error) { + pk := &tdh2easy.PublicKey{} + if err := pk.Unmarshal(data); err != nil { + return nil, err + } + return pk, nil +} + +func EncryptS4Secrets(deployerPk *ecdsa.PrivateKey, tdh2Pk *tdh2easy.PublicKey, donKey []byte, msgJSON string) (string, error) { + // 65 bytes PublicKey format, should start with 0x04 to be processed by crypto.UnmarshalPubkey() + b := make([]byte, 1) + b[0] = 0x04 + donKey = bytes.Join([][]byte{b, donKey}, nil) + donPubKey, err := crypto.UnmarshalPubkey(donKey) + if err != nil { + return "", errors.Wrap(err, "failed to unmarshal DON key") + } + eciesDONPubKey := ecies.ImportECDSAPublic(donPubKey) + signature, err := deployerPk.Sign(rand.Reader, []byte(msgJSON), nil) + if err != nil { + return "", errors.Wrap(err, "failed to sign the msg with Ethereum key") + } + signedSecrets, err := json.Marshal(struct { + Signature []byte `json:"signature"` + Message string `json:"message"` + }{ + Signature: signature, + Message: msgJSON, + }) + if err != nil { + return "", errors.Wrap(err, "failed to marshal signed secrets") + } + ct, err := ecies.Encrypt(rand.Reader, eciesDONPubKey, signedSecrets, nil, nil) + if err != nil { + return "", errors.Wrap(err, "failed to encrypt with DON key") + } + ct0xFormat, err := json.Marshal(map[string]interface{}{"0x0": base64.StdEncoding.EncodeToString(ct)}) + if err != nil { + return "", errors.Wrap(err, "failed to marshal DON key encrypted format") + } + ctTDH2Format, err := tdh2easy.Encrypt(tdh2Pk, ct0xFormat) + if err != nil { + return "", errors.Wrap(err, "failed to encrypt with TDH2 public key") + } + tdh2Message, err := ctTDH2Format.Marshal() + if err != nil { + return "", errors.Wrap(err, "failed to marshal TDH2 encrypted msg") + } + finalMsg, err := json.Marshal(map[string]interface{}{ + "encryptedSecrets": "0x" + hex.EncodeToString(tdh2Message), + }) + if err != nil { + return "", errors.Wrap(err, "failed to marshal secrets msg") + } + return string(finalMsg), nil +} diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go new file mode 100644 index 00000000000..5677e79b105 --- /dev/null +++ b/integration-tests/load/functions/gateway_gun.go @@ -0,0 +1,110 @@ +package loadfunctions + +import ( + "crypto/ecdsa" + "fmt" + "github.com/go-resty/resty/v2" + "github.com/rs/zerolog/log" + "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" + "github.com/smartcontractkit/wasp" + "math/rand" + "os" + "strconv" + "time" +) + +/* SingleFunctionCallGun is a gun that constantly requests randomness for one feed */ + +type GatewaySecretsSetGun struct { + Cfg *PerformanceConfig + Resty *resty.Client + SlotID uint + Method string + EthereumPrivateKey *ecdsa.PrivateKey + ThresholdPublicKey *tdh2easy.PublicKey + DONPublicKey []byte +} + +func NewGatewaySecretsSetGun(cfg *PerformanceConfig, method string, pKey *ecdsa.PrivateKey, tdh2PubKey *tdh2easy.PublicKey, donPubKey []byte) *GatewaySecretsSetGun { + return &GatewaySecretsSetGun{ + Cfg: cfg, + Resty: resty.New(), + Method: method, + EthereumPrivateKey: pKey, + ThresholdPublicKey: tdh2PubKey, + DONPublicKey: donPubKey, + } +} + +func callSetSecrets(m *GatewaySecretsSetGun) *wasp.CallResult { + randNum := strconv.Itoa(rand.Intn(100000)) + randSlot := uint(rand.Intn(5)) + version := uint64(time.Now().UnixNano()) + expiration := int64(60 * 60 * 1000) + secret := fmt.Sprintf("{\"ltsecret\": \"%s\"}", randNum) + log.Debug(). + Uint("SlotID", randSlot). + Str("MessageID", randNum). + Uint64("Version", version). + Int64("Expiration", expiration). + Str("Secret", secret). + Msg("Sending S4 envelope") + secrets, err := EncryptS4Secrets( + m.EthereumPrivateKey, + m.ThresholdPublicKey, + m.DONPublicKey, + secret, + ) + if err != nil { + return &wasp.CallResult{Error: err.Error(), Failed: true} + } + if err := UploadS4Secrets(m.Resty, &S4SecretsCfg{ + GatewayURL: fmt.Sprintf("%s/user", m.Cfg.Common.GatewayURL), + PrivateKey: os.Getenv("MUMBAI_KEYS"), + MessageID: randNum, + Method: "secrets_set", + DonID: m.Cfg.Common.DONID, + S4SetSlotID: randSlot, + S4SetVersion: version, + S4SetExpirationPeriod: expiration, + S4SetPayload: secrets, + }); err != nil { + return &wasp.CallResult{Error: err.Error(), Failed: true} + } + return &wasp.CallResult{} +} + +func callSecretsList(m *GatewaySecretsSetGun) *wasp.CallResult { + randNum := strconv.Itoa(rand.Intn(100000)) + randSlot := uint(rand.Intn(5)) + version := uint64(time.Now().UnixNano()) + expiration := int64(60 * 60 * 1000) + if err := ListS4Secrets(m.Resty, &S4SecretsCfg{ + GatewayURL: fmt.Sprintf("%s/user", m.Cfg.Common.GatewayURL), + RecieverAddr: m.Cfg.Common.Receiver, + PrivateKey: os.Getenv("MUMBAI_KEYS"), + MessageID: randNum, + Method: m.Method, + DonID: m.Cfg.Common.DONID, + S4SetSlotID: randSlot, + S4SetVersion: version, + S4SetExpirationPeriod: expiration, + }); err != nil { + return &wasp.CallResult{Error: err.Error(), Failed: true} + } + return &wasp.CallResult{} +} + +// Call implements example gun call, assertions on response bodies should be done here +func (m *GatewaySecretsSetGun) Call(_ *wasp.Generator) *wasp.CallResult { + var res *wasp.CallResult + switch m.Method { + case "secrets_set": + res = callSetSecrets(m) + case "secrets_list": + res = callSecretsList(m) + default: + panic("gateway gun must use either 'secrets_set' or 'list' methods") + } + return res +} diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go new file mode 100644 index 00000000000..946afdd711a --- /dev/null +++ b/integration-tests/load/functions/gateway_test.go @@ -0,0 +1,73 @@ +package loadfunctions + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" + "github.com/smartcontractkit/wasp" + "github.com/stretchr/testify/require" + "testing" +) + +func TestGatewayLoad(t *testing.T) { + cfg, err := ReadConfig() + require.NoError(t, err) + ft, err := SetupLocalLoadTestEnv(cfg) + require.NoError(t, err) + ft.EVMClient.ParallelTransactions(false) + + labels := map[string]string{ + "branch": "gateway_healthcheck", + "commit": "gateway_healthcheck", + } + + secretsListCfg := &wasp.Config{ + LoadType: wasp.RPS, + GenName: functions.MethodSecretsList, + Schedule: wasp.Plain( + cfg.GatewayListSoak.RPS, + cfg.GatewayListSoak.Duration.Duration(), + ), + Gun: NewGatewaySecretsSetGun( + cfg, + functions.MethodSecretsList, + ft.EthereumPrivateKey, + ft.ThresholdPublicKey, + ft.DONPublicKey, + ), + Labels: labels, + LokiConfig: wasp.NewEnvLokiConfig(), + } + + secretsSetCfg := &wasp.Config{ + LoadType: wasp.RPS, + GenName: functions.MethodSecretsSet, + Schedule: wasp.Plain( + cfg.GatewaySetSoak.RPS, + cfg.GatewaySetSoak.Duration.Duration(), + ), + Gun: NewGatewaySecretsSetGun( + cfg, + functions.MethodSecretsSet, + ft.EthereumPrivateKey, + ft.ThresholdPublicKey, + ft.DONPublicKey, + ), + Labels: labels, + LokiConfig: wasp.NewEnvLokiConfig(), + } + + t.Run("gateway secrets list soak test", func(t *testing.T) { + secretsListCfg.T = t + _, err := wasp.NewProfile(). + Add(wasp.NewGenerator(secretsListCfg)). + Run(true) + require.NoError(t, err) + }) + + t.Run("gateway secrets set soak test", func(t *testing.T) { + secretsListCfg.T = t + _, err := wasp.NewProfile(). + Add(wasp.NewGenerator(secretsSetCfg)). + Run(true) + require.NoError(t, err) + }) +} diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go new file mode 100644 index 00000000000..0a8b4cef46a --- /dev/null +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -0,0 +1,61 @@ +package loadfunctions + +import ( + "github.com/rs/zerolog/log" + "github.com/smartcontractkit/wasp" + "testing" + "time" +) + +/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ + +const ( + LokiTypeLabel = "functions_contracts_load_summary" + ErrMetrics = "failed to get Functions load test metrics" + ErrLokiClient = "failed to create Loki client for monitoring" + ErrLokiPush = "failed to push monitoring metrics to Loki" +) + +type LoadStats struct { + Succeeded uint32 + Errored uint32 + Empty uint32 +} + +func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string) { + go func() { + updatedLabels := make(map[string]string) + for k, v := range labels { + updatedLabels[k] = v + } + updatedLabels["type"] = LokiTypeLabel + updatedLabels["go_test_name"] = t.Name() + updatedLabels["gen_name"] = "performance" + lc, err := wasp.NewLokiClient(wasp.NewEnvLokiConfig()) + if err != nil { + log.Error().Err(err).Msg(ErrLokiClient) + return + } + if err := ft.LoadTestClient.ResetStats(); err != nil { + log.Error().Err(err).Msg("failed to reset load test client stats") + } + for { + time.Sleep(5 * time.Second) + stats, err := ft.LoadTestClient.GetStats() + if err != nil { + log.Error().Err(err).Msg(ErrMetrics) + } + log.Info(). + Hex("LastReqID", []byte(stats.LastRequestID)). + Str("LastResponse", stats.LastResponse). + Str("LastError", stats.LastError). + Uint32("Total", stats.Total). + Uint32("Succeeded", stats.Succeeded). + Uint32("Errored", stats.Errored). + Uint32("Empty", stats.Empty).Msg("On-chain stats for load test client") + if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), stats); err != nil { + log.Error().Err(err).Msg(ErrLokiPush) + } + } + }() +} diff --git a/integration-tests/load/functions/gun.go b/integration-tests/load/functions/request_gun.go similarity index 65% rename from integration-tests/load/functions/gun.go rename to integration-tests/load/functions/request_gun.go index 358e0acb986..5cbff36179e 100644 --- a/integration-tests/load/functions/gun.go +++ b/integration-tests/load/functions/request_gun.go @@ -7,7 +7,8 @@ import ( /* SingleFunctionCallGun is a gun that constantly requests randomness for one feed */ type SingleFunctionCallGun struct { - contracts *Contracts + ft *FunctionsTest + times uint32 source string encryptedSecretsReferences []byte args []string @@ -15,9 +16,10 @@ type SingleFunctionCallGun struct { jobId [32]byte } -func NewSingleFunctionCallGun(contracts *Contracts, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) *SingleFunctionCallGun { +func NewSingleFunctionCallGun(ft *FunctionsTest, times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) *SingleFunctionCallGun { return &SingleFunctionCallGun{ - contracts: contracts, + ft: ft, + times: times, source: source, encryptedSecretsReferences: encryptedSecretsReferences, args: args, @@ -28,7 +30,14 @@ func NewSingleFunctionCallGun(contracts *Contracts, source string, encryptedSecr // Call implements example gun call, assertions on response bodies should be done here func (m *SingleFunctionCallGun) Call(l *wasp.Generator) *wasp.CallResult { - err := m.contracts.LoadTestClient.SendRequest(m.source, m.encryptedSecretsReferences, m.args, m.subscriptionId, m.jobId) + err := m.ft.LoadTestClient.SendRequest( + m.times, + m.source, + m.encryptedSecretsReferences, + m.args, + m.subscriptionId, + m.jobId, + ) if err != nil { return &wasp.CallResult{Error: err.Error(), Failed: true} } diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index cd8038c41ba..0433b5beb61 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -1,64 +1,173 @@ package loadfunctions import ( + "crypto/ecdsa" + "fmt" + "github.com/ethereum/go-ethereum/crypto" + "github.com/go-resty/resty/v2" "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + "github.com/smartcontractkit/chainlink/integration-tests/networks" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" "math/big" + mrand "math/rand" + "os" + "strconv" + "time" ) -type Contracts struct { - LinkToken contracts.LinkToken - Coordinator contracts.FunctionsCoordinator - Router contracts.FunctionsRouter - LoadTestClient contracts.FunctionsLoadTestClient +type FunctionsTest struct { + EVMClient blockchain.EVMClient + ContractDeployer contracts.ContractDeployer + ContractLoader contracts.ContractLoader + LinkToken contracts.LinkToken + Coordinator contracts.FunctionsCoordinator + Router contracts.FunctionsRouter + LoadTestClient contracts.FunctionsLoadTestClient + EthereumPrivateKey *ecdsa.PrivateKey + EthereumPublicKey *ecdsa.PublicKey + ThresholdPublicKey *tdh2easy.PublicKey + DONPublicKey []byte + ThresholdPublicKeyBytes []byte + ThresholdEncryptedSecrets string } -func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*test_env.CLClusterTestEnv, *Contracts, error) { - env, err := test_env.NewCLTestEnvBuilder(). - Build() +type S4SecretsCfg struct { + GatewayURL string + PrivateKey string + RecieverAddr string + MessageID string + Method string + DonID string + S4SetSlotID uint + S4SetVersion uint64 + S4SetExpirationPeriod int64 + S4SetPayload string +} + +func SetupLocalLoadTestEnv(cfg *PerformanceConfig) (*FunctionsTest, error) { + bc, err := blockchain.NewEVMClientFromNetwork(networks.SelectedNetwork) + if err != nil { + return nil, err + } + cd, err := contracts.NewContractDeployer(bc) + if err != nil { + return nil, err + } + + cl, err := contracts.NewContractLoader(bc) if err != nil { - return env, nil, err + return nil, err } - env.EVMClient.GetNonceSetting() - lt, err := env.ContractLoader.LoadLINKToken(cfg.Common.LINKTokenAddr) if err != nil { - return env, nil, err + return nil, err } - coord, err := env.ContractLoader.LoadFunctionsCoordinator(cfg.Common.Coordinator) + lt, err := cl.LoadLINKToken(cfg.Common.LINKTokenAddr) if err != nil { - return env, nil, err + return nil, err } - router, err := env.ContractLoader.LoadFunctionsRouter(cfg.Common.Router) + coord, err := cl.LoadFunctionsCoordinator(cfg.Common.Coordinator) if err != nil { - return env, nil, err + return nil, err } - loadTestClient, err := env.ContractLoader.LoadFunctionsLoadTestClient(cfg.Common.LoadTestClient) + router, err := cl.LoadFunctionsRouter(cfg.Common.Router) if err != nil { - return env, nil, err + return nil, err + } + var loadTestClient contracts.FunctionsLoadTestClient + if cfg.Common.LoadTestClient != "" { + loadTestClient, err = cl.LoadFunctionsLoadTestClient(cfg.Common.LoadTestClient) + } else { + loadTestClient, err = cd.DeployFunctionsLoadTestClient(cfg.Common.Router) + } + if err != nil { + return nil, err } if cfg.Common.SubscriptionID == 0 { log.Info().Msg("Creating new subscription") subID, err := router.CreateSubscriptionWithConsumer(loadTestClient.Address()) if err != nil { - return env, nil, errors.Wrap(err, "failed to create a new subscription") + return nil, errors.Wrap(err, "failed to create a new subscription") } encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint64"}]`, subID) if err != nil { - return env, nil, errors.Wrap(err, "failed to encode subscription ID for funding") + return nil, errors.Wrap(err, "failed to encode subscription ID for funding") } _, err = lt.TransferAndCall(router.Address(), big.NewInt(0).Mul(cfg.Common.Funding.SubFunds, big.NewInt(1e18)), encodedSubId) if err != nil { - return env, nil, errors.Wrap(err, "failed to transferAndCall router, LINK funding") + return nil, errors.Wrap(err, "failed to transferAndCall router, LINK funding") } cfg.Common.SubscriptionID = subID } - return env, &Contracts{ - LinkToken: lt, - Coordinator: coord, - Router: router, - LoadTestClient: loadTestClient, + pKey, pubKey, err := parseEthereumPrivateKey(os.Getenv("MUMBAI_KEYS")) + if err != nil { + return nil, errors.Wrap(err, "failed to load Ethereum private key") + } + tpk, err := coord.GetThresholdPublicKey() + if err != nil { + return nil, errors.Wrap(err, "failed to get Threshold public key") + } + log.Info().Hex("ThresholdPublicKeyBytesHex", tpk).Msg("Loaded coordinator keys") + donPubKey, err := coord.GetDONPublicKey() + if err != nil { + return nil, errors.Wrap(err, "failed to get DON public key") + } + log.Info().Hex("DONPublicKeyHex", donPubKey).Msg("Loaded coordinator keys") + tdh2pk, err := ParseTDH2Key(tpk) + if err != nil { + return nil, errors.Wrap(err, "failed to unmarshal tdh2 public key") + } + var encryptedSecrets string + if cfg.Common.Secrets != "" { + encryptedSecrets, err = EncryptS4Secrets(pKey, tdh2pk, donPubKey, cfg.Common.Secrets) + if err != nil { + return nil, errors.Wrap(err, "failed to generate tdh2 secrets") + } + if err := UploadS4Secrets(resty.New(), &S4SecretsCfg{ + GatewayURL: fmt.Sprintf("%s/user", cfg.Common.GatewayURL), + PrivateKey: cfg.MumbaiPrivateKey, + MessageID: strconv.Itoa(mrand.Intn(100000-1) + 1), + Method: "secrets_set", + DonID: cfg.Common.DONID, + S4SetSlotID: uint(mrand.Intn(5)), + S4SetVersion: uint64(time.Now().UnixNano()), + S4SetExpirationPeriod: 60 * 60 * 1000, + S4SetPayload: encryptedSecrets, + }); err != nil { + return nil, errors.Wrap(err, "failed to upload secrets to S4") + } + } + return &FunctionsTest{ + EVMClient: bc, + ContractDeployer: cd, + ContractLoader: cl, + LinkToken: lt, + Coordinator: coord, + Router: router, + LoadTestClient: loadTestClient, + EthereumPrivateKey: pKey, + EthereumPublicKey: pubKey, + ThresholdPublicKey: tdh2pk, + ThresholdPublicKeyBytes: tpk, + ThresholdEncryptedSecrets: encryptedSecrets, + DONPublicKey: donPubKey, }, nil } + +func parseEthereumPrivateKey(pk string) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) { + pKey, err := crypto.HexToECDSA(pk) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert Ethereum key from hex") + } + + publicKey := pKey.Public() + pubKey, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return nil, nil, errors.Wrap(err, "failed to get public key from Ethereum private key") + } + log.Info().Str("Address", crypto.PubkeyToAddress(*pubKey).Hex()).Msg("Parsed private key for address") + return pKey, pubKey, nil +} diff --git a/integration-tests/networks/known_networks.go b/integration-tests/networks/known_networks.go index 1fdd35e93c2..41148ba2043 100644 --- a/integration-tests/networks/known_networks.go +++ b/integration-tests/networks/known_networks.go @@ -300,11 +300,11 @@ var ( ChainID: 80001, Simulated: false, ChainlinkTransactionLimit: 5000, - Timeout: blockchain.JSONStrDuration{Duration: time.Minute}, + Timeout: blockchain.JSONStrDuration{Duration: 3 * time.Minute}, MinimumConfirmations: 1, - GasEstimationBuffer: 1000, + GasEstimationBuffer: 100000, FinalityDepth: 550, - DefaultGasLimit: 6000000, + DefaultGasLimit: 8000000, } AvalancheMainnet blockchain.EVMNetwork = blockchain.EVMNetwork{