Skip to content

Commit

Permalink
simulation config file
Browse files Browse the repository at this point in the history
  • Loading branch information
KuphJr committed Sep 9, 2023
1 parent e31d1c6 commit f2ace7f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 10 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -548,13 +548,25 @@ The `localFunctionsTestnet` function takes the following values as arguments.

```
const localFunctionsTestnet = await startLocalFunctionsTestnet(
secrets?: Record<string, string>, // Secrets which can be accessed by the JavaScript code during request execution
simulationConfigPath?: string // Absolute path to config file which exports simulation config parameters
options?: ServerOptions, // Ganache server options
port?: number, // Defaults to 8545
)
```

Observe that `localFunctionsTestnet` takes in a secrets object as an optional argument. This is because the local testnet does not have the ability to access or decrypt encrypted secrets provided within the request transaction. Instead, you can provide secrets as an argument here which can be accessed by the JavaScript code during request executions. Secrets specified as an argument to `localFunctionsTestnet` will be made accessible within the JavaScript code regardless of the `secretsLocation` or `encryptedSecretsReference` values sent in the request transaction.
Observe that `localFunctionsTestnet` takes in a `simulationConfigPath` string as an optional argument. The primary reason for this is because the local testnet does not have the ability to access or decrypt encrypted secrets provided within request transactions. Instead, you can export an object named `secrets` from a TypeScript or JavaScript file and provide the absolute path to that file as the `simulationConfigPath` argument. When the JavaScript code is executed during the request, secrets specified in that file will be made accessible within the JavaScript code regardless of the `secretsLocation` or `encryptedSecretsReference` values sent in the request transaction. This config file can also contain other simulation config parameters. An example of this config file is shown below.

```
export const secrets: { test: 'hello world' } // `secrets` object which can be accessed by the JavaScript code during request execution (can only contain string values)
export const maxOnChainResponseBytes = 256 // Maximum size of the returned value in bytes (defaults to 256)
export const maxExecutionTimeMs = 10000 // Maximum execution duration (defaults to 10_000ms)
export const maxMemoryUsageMb = 128 // Maximum RAM usage (defaults to 128mb)
export const numAllowedQueries = 5 // Maximum number of HTTP requests (defaults to 5)
export const maxQueryDurationMs = 9000// Maximum duration of each HTTP request (defaults to 9_000ms)
export const maxQueryUrlLength = 2048 // Maximum HTTP request URL length (defaults to 2048)
export const maxQueryRequestBytes = 2048 // Maximum size of outgoing HTTP request payload (defaults to 2048 == 2 KB)
export const maxQueryResponseBytes = 2097152 // Maximum size of incoming HTTP response payload (defaults to 2_097_152 == 2 MB)
```

`localFunctionsTestnet` returns a promise which resolves to the following type.

Expand Down
27 changes: 21 additions & 6 deletions src/localFunctionsTestnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import type {
} from './types'

export const startLocalFunctionsTestnet = async (
secrets?: Record<string, string>,
simulationConfigPath?: string,
options?: ServerOptions,
port = 8545,
): Promise<LocalFunctionsTestnet> => {
Expand Down Expand Up @@ -83,7 +83,12 @@ export const startLocalFunctionsTestnet = async (
callbackGasLimit,
commitment,
}
handleOracleRequest(requestEvent, contracts.functionsMockCoordinatorContract, admin, secrets)
handleOracleRequest(
requestEvent,
contracts.functionsMockCoordinatorContract,
admin,
simulationConfigPath,
)
},
)

Expand Down Expand Up @@ -137,10 +142,10 @@ const handleOracleRequest = async (
requestEventData: RequestEventData,
mockCoordinator: Contract,
admin: Wallet,
secrets: Record<string, string> = {},
simulationConfigPath?: string,
) => {
const requestData = await buildRequestDataObject(requestEventData.data)
const response = await simulateDONExecution(requestData, secrets)
const response = await simulateDONExecution(requestData, simulationConfigPath)

const errorHexstring = response.errorString
? '0x' + Buffer.from(response.errorString.toString()).toString('hex')
Expand All @@ -164,15 +169,25 @@ const handleOracleRequest = async (

const simulateDONExecution = async (
requestData: FunctionsRequestParams,
secrets: Record<string, string>,
simulationConfigPath?: string,
): Promise<{ responseBytesHexstring?: string; errorString?: string }> => {
const simulationConfig = simulationConfigPath ? require(simulationConfigPath) : {}

// Perform the simulation numberOfSimulatedNodeExecution times
const simulations = [...Array(numberOfSimulatedNodeExecutions)].map(() =>
simulateScript({
source: requestData.source,
secrets,
secrets: simulationConfig.secrets, // Secrets are taken from simulationConfig, not request data included in transaction
args: requestData.args,
bytesArgs: requestData.bytesArgs,
maxOnChainResponseBytes: simulationConfig.maxOnChainResponseBytes,
maxExecutionTimeMs: simulationConfig.maxExecutionTimeMs,
maxMemoryUsageMb: simulationConfig.maxMemoryUsageMb,
numAllowedQueries: simulationConfig.numAllowedQueries,
maxQueryDurationMs: simulationConfig.maxQueryDurationMs,
maxQueryUrlLength: simulationConfig.maxQueryUrlLength,
maxQueryRequestBytes: simulationConfig.maxQueryRequestBytes,
maxQueryResponseBytes: simulationConfig.maxQueryResponseBytes,
}),
)
const responses = await Promise.all(simulations)
Expand Down
1 change: 0 additions & 1 deletion src/simulateScript/Functions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// This file is copied from https://github.com/smartcontractkit/universal-adapter-sandbox/blob/main/src/Functions.ts
import axios from 'axios'
import type { AxiosResponse, AxiosError } from 'axios'
import { safePow } from './safePow'
Expand Down
4 changes: 3 additions & 1 deletion test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { startLocalFunctionsTestnet } from '../../src'
import { FunctionsClientExampleSource } from '../../src/v1_contract_sources'

import path from 'path'

import { Wallet, providers, ContractFactory, utils } from 'ethers'

import type { GetFunds } from '../../src'
Expand All @@ -25,7 +27,7 @@ export const setupLocalTestnet = async (
getFunds: GetFunds
}> => {
const localFunctionsTestnet = await startLocalFunctionsTestnet(
{ test: 'hello world' },
path.join(__dirname, 'testSimulationConfig.ts'),
{
logging: {
debug: false,
Expand Down
1 change: 1 addition & 0 deletions test/utils/testSimulationConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const secrets = { test: 'hello world' }

0 comments on commit f2ace7f

Please sign in to comment.