Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full integration of threshold plugin with Functions #9765

Merged
merged 9 commits into from
Jul 11, 2023
2 changes: 1 addition & 1 deletion core/scripts/functions/src/generate_ocr2_config_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (g *generateOCR2Config) Run(args []string) {
DefaultAggregationMethod: config.AggregationMethod(cfg.DefaultAggregationMethod),
UniqueReports: cfg.UniqueReports,
ThresholdPluginConfig: &config.ThresholdReportingPluginConfig{
MaxQueryLengthBytes: cfg.ThresholdOffchainConfig.MaxObservationLengthBytes,
MaxQueryLengthBytes: cfg.ThresholdOffchainConfig.MaxQueryLengthBytes,
MaxObservationLengthBytes: cfg.ThresholdOffchainConfig.MaxObservationLengthBytes,
MaxReportLengthBytes: cfg.ThresholdOffchainConfig.MaxReportLengthBytes,
RequestCountLimit: cfg.ThresholdOffchainConfig.RequestCountLimit,
Expand Down
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ require (
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230612131011-369bfb503592 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230622060316-7ce48476dd7d // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230616141813-ca0ecf03ca5c // indirect
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230616062456-5c32c95fc166 // indirect
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230625174811-4934857d1c4a // 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
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1404,8 +1404,8 @@ github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4
github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb/go.mod h1:HNUu4cJekUdsJbwRBCiOybtkPJEfGRELQPe2tkoDEyk=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230616141813-ca0ecf03ca5c h1:B7jWegIHCHXY32qWGwlNalrJYSz4uZh5zAgd2rQ3Iyc=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230616141813-ca0ecf03ca5c/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230616062456-5c32c95fc166 h1:cNH0nQjRfmWj173L8exDkQratcFVQ8AAj8RZ8a+suaI=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230616062456-5c32c95fc166/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230625174811-4934857d1c4a h1:/ZJnNxcdJ75yDJHnKMjd3G9oZ6lcQRvFUdmiR2DPAgQ=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230625174811-4934857d1c4a/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw=
github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ=
github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
Expand Down
22 changes: 21 additions & 1 deletion core/services/ocr2/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,11 @@ func (d *Delegate) newServicesOCR2Functions(
return nil, err
}

thresholdProvider, err := createPluginProvider(functionsRelay.ThresholdPlugin, "FunctionsThresholdRelayer")
if err != nil {
return nil, err
}

s4Provider, err := createPluginProvider(functionsRelay.S4Plugin, "FunctionsS4Relayer")
if err != nil {
return nil, err
Expand Down Expand Up @@ -1002,6 +1007,21 @@ func (d *Delegate) newServicesOCR2Functions(
ReportingPluginFactory: nil, // To be set by NewFunctionsServices
}

thresholdOracleArgs := libocr2.OCR2OracleArgs{
BinaryNetworkEndpointFactory: d.peerWrapper.Peer2,
V2Bootstrappers: bootstrapPeers,
ContractTransmitter: thresholdProvider.ContractTransmitter(),
ContractConfigTracker: thresholdProvider.ContractConfigTracker(),
Database: thresholdOcrDB,
LocalConfig: lc,
Logger: ocrLogger,
MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(spec.ContractID, synchronization.OCR2Threshold),
OffchainConfigDigester: thresholdProvider.OffchainConfigDigester(),
OffchainKeyring: kb,
OnchainKeyring: kb,
ReportingPluginFactory: nil, // To be set by NewFunctionsServices
}

s4OracleArgs := libocr2.OCR2OracleArgs{
BinaryNetworkEndpointFactory: d.peerWrapper.Peer2,
V2Bootstrappers: bootstrapPeers,
Expand Down Expand Up @@ -1045,7 +1065,7 @@ func (d *Delegate) newServicesOCR2Functions(
ThresholdKeyShare: thresholdKeyShare,
}

functionsServices, err := functions.NewFunctionsServices(&functionsOracleArgs, nil, &s4OracleArgs, &functionsServicesConfig)
functionsServices, err := functions.NewFunctionsServices(&functionsOracleArgs, &thresholdOracleArgs, &s4OracleArgs, &functionsServicesConfig)
if err != nil {
return nil, errors.Wrap(err, "error calling NewFunctionsServices")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,96 +1,80 @@
package functions_test

import (
"encoding/hex"
"fmt"
"math/rand"
"sync"
"testing"
"time"

"github.com/onsi/gomega"
"github.com/smartcontractkit/libocr/commontypes"
confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
functionsConfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config"
utils "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/integration_tests/internal"
)

func TestIntegration_Functions_MultipleRequests_Success(t *testing.T) {
var (
// a batch of 8 max-length results uses around 1M gas (assuming 70k gas per client callback - see FunctionsClientExample.sol)
nOracleNodes := 4
nClients := 50
requestLenBytes := 1000
maxGas := 1_300_000
batchSize := 8
nOracleNodes = 4
nClients = 50
requestLenBytes = 1000
maxGas = 1_300_000
batchSize = 8
)

func TestIntegration_Functions_MultipleRequests_Success(t *testing.T) {
// simulated chain with all contracts
owner, b, ticker, oracleContractAddress, oracleContract, clientContracts, registryAddress, registryContract, linkToken := utils.StartNewChainWithContracts(t, nClients)
defer ticker.Stop()

// bootstrap node and job
bootstrapNodePort := uint16(39999)
bootstrapNode := utils.StartNewNode(t, owner, bootstrapNodePort, "bootstrap", b, uint32(maxGas), nil)
utils.AddBootstrapJob(t, bootstrapNode.App, oracleContractAddress)

// oracle nodes with jobs, bridges and mock EAs
var oracles []confighelper2.OracleIdentityExtra
var apps []*cltest.TestApplication
for i := 0; i < nOracleNodes; i++ {
oracleNode := utils.StartNewNode(t, owner, bootstrapNodePort+1+uint16(i), fmt.Sprintf("oracle%d", i), b, uint32(maxGas), []commontypes.BootstrapperLocator{
{PeerID: bootstrapNode.PeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}},
})
apps = append(apps, oracleNode.App)
oracles = append(oracles, oracleNode.OracleIdentity)

ea := utils.StartNewMockEA(t)
defer ea.Close()

_ = utils.AddOCR2Job(t, apps[i], oracleContractAddress, oracleNode.Keybundle.ID(), oracleNode.Transmitter, ea.URL)
}
_, _, oracleIdentities := utils.CreateFunctionsNodes(t, owner, b, oracleContractAddress, 39999, nOracleNodes, maxGas, nil, nil)

// config for registry contract
utils.SetRegistryConfig(t, owner, registryContract, oracleContractAddress)

pluginConfig := functionsConfig.ReportingPluginConfig{
MaxQueryLengthBytes: 10_000,
MaxObservationLengthBytes: 10_000,
MaxReportLengthBytes: 10_000,
MaxRequestBatchSize: uint32(batchSize),
DefaultAggregationMethod: functionsConfig.AggregationMethod_AGGREGATION_MODE,
UniqueReports: true,
}

// config for oracle contract
utils.SetOracleConfig(t, owner, oracleContract, oracles, batchSize)
utils.SetOracleConfig(t, owner, oracleContract, oracleIdentities, batchSize, &pluginConfig)
utils.CommitWithFinality(b)

// set up subscription
subscriptionId := utils.CreateAndFundSubscriptions(t, owner, linkToken, registryAddress, registryContract, clientContracts)
// validate that all client contracts got correct responses to their requests
utils.ClientTestRequests(t, owner, b, linkToken, registryAddress, registryContract, clientContracts, requestLenBytes, utils.DefaultSecretsBytes, 1*time.Minute)
}

// send requests
requestSources := make([][]byte, nClients)
rnd := rand.New(rand.NewSource(666))
for i := 0; i < nClients; i++ {
requestSources[i] = make([]byte, requestLenBytes)
for j := 0; j < requestLenBytes; j++ {
requestSources[i][j] = byte(rnd.Uint32() % 256)
}
_, err := clientContracts[i].Contract.SendRequest(
owner,
hex.EncodeToString(requestSources[i]),
utils.DefaultSecretsBytes,
[]string{utils.DefaultArg1, utils.DefaultArg2},
subscriptionId)
require.NoError(t, err)
func TestIntegration_Functions_MultipleRequests_ThresholdDecryptionSuccess(t *testing.T) {
// simulated chain with all contracts
owner, b, ticker, oracleContractAddress, oracleContract, clientContracts, registryAddress, registryContract, linkToken := utils.StartNewChainWithContracts(t, nClients)
defer ticker.Stop()

_, _, oracleIdentities := utils.CreateFunctionsNodes(t, owner, b, oracleContractAddress, 49999, nOracleNodes, maxGas, utils.ExportedOcr2Keystores, utils.MockThresholdKeyShares)

// config for registry contract
utils.SetRegistryConfig(t, owner, registryContract, oracleContractAddress)

pluginConfig := functionsConfig.ReportingPluginConfig{
MaxQueryLengthBytes: 10_000,
MaxObservationLengthBytes: 10_000,
MaxReportLengthBytes: 10_000,
MaxRequestBatchSize: uint32(batchSize),
DefaultAggregationMethod: functionsConfig.AggregationMethod_AGGREGATION_MODE,
UniqueReports: true,
ThresholdPluginConfig: &functionsConfig.ThresholdReportingPluginConfig{
MaxQueryLengthBytes: 10_000,
MaxObservationLengthBytes: 10_000,
MaxReportLengthBytes: 10_000,
RequestCountLimit: 100,
RequestTotalBytesLimit: 1_000,
RequireLocalRequestCheck: true,
},
}

// config for oracle contract
utils.SetOracleConfig(t, owner, oracleContract, oracleIdentities, batchSize, &pluginConfig)
utils.CommitWithFinality(b)

// validate that all client contracts got correct responses to their requests
var wg sync.WaitGroup
for i := 0; i < nClients; i++ {
ic := i
wg.Add(1)
go func() {
defer wg.Done()
gomega.NewGomegaWithT(t).Eventually(func() [32]byte {
answer, err := clientContracts[ic].Contract.LastResponse(nil)
require.NoError(t, err)
return answer
}, 1*time.Minute, 1*time.Second).Should(gomega.Equal(utils.GetExpectedResponse(requestSources[ic])))
}()
}
wg.Wait()
utils.ClientTestRequests(t, owner, b, linkToken, registryAddress, registryContract, clientContracts, requestLenBytes, utils.DefaultSecretsUrlsBytes, 3*time.Minute)
}
Loading