From f71416d275bdb54cfa17c1081bf4d291ad1d218d Mon Sep 17 00:00:00 2001 From: gheorghestrimtu Date: Wed, 20 Oct 2021 18:57:07 +0300 Subject: [PATCH] OCRSetupInputs multiple contracts (#117) * OCRSetupInputs multiple contracts * fix * lint * PR changes --- suite/chaos/chaos_ocr_test.go | 3 +- suite/contracts/contracts_ocr_test.go | 3 +- suite/steps/alerts_steps.go | 24 ++-- suite/testcommon/ocr.go | 198 ++++++++++++++------------ 4 files changed, 126 insertions(+), 102 deletions(-) diff --git a/suite/chaos/chaos_ocr_test.go b/suite/chaos/chaos_ocr_test.go index 05de67105..9957cf71e 100644 --- a/suite/chaos/chaos_ocr_test.go +++ b/suite/chaos/chaos_ocr_test.go @@ -19,7 +19,8 @@ var _ = XDescribeTable("OCR chaos tests @chaos-ocr", func( i := &testcommon.OCRSetupInputs{} Context("Runs OCR test with a chaos modifier", func() { testcommon.DeployOCRForEnv(i, envInit) - testcommon.SetupOCRTest(i) + testcommon.FundNodes(i) + testcommon.DeployOCRContracts(i, 1) testcommon.SendOCRJobs(i) _, err := i.SuiteSetup.Environment().ApplyChaos(chaosSpec) Expect(err).ShouldNot(HaveOccurred()) diff --git a/suite/contracts/contracts_ocr_test.go b/suite/contracts/contracts_ocr_test.go index 9fd5891c0..653113d12 100644 --- a/suite/contracts/contracts_ocr_test.go +++ b/suite/contracts/contracts_ocr_test.go @@ -14,7 +14,8 @@ var _ = Describe("OCR Feed @ocr", func() { ) { i := &testcommon.OCRSetupInputs{} testcommon.DeployOCRForEnv(i, envInit) - testcommon.SetupOCRTest(i) + testcommon.FundNodes(i) + testcommon.DeployOCRContracts(i, 1) testcommon.SendOCRJobs(i) testcommon.CheckRound(i) By("Printing gas stats", func() { diff --git a/suite/steps/alerts_steps.go b/suite/steps/alerts_steps.go index cc4f48630..dbc0f7868 100644 --- a/suite/steps/alerts_steps.go +++ b/suite/steps/alerts_steps.go @@ -1,20 +1,26 @@ package steps import ( + "fmt" . "github.com/onsi/gomega" "github.com/smartcontractkit/integrations-framework/client" + "github.com/smartcontractkit/integrations-framework/contracts" ) -// GetMockserverInitializerDataForOTPE crates mocked weiwatchers data needed for otpe -func GetMockserverInitializerDataForOTPE(offChainAggregatorInstanceAddress string, chainlinkNodes []client.Chainlink) interface{} { - contractInfo := client.ContractInfoJSON{ - ContractVersion: 4, - Path: "test", - Status: "live", - ContractAddress: offChainAggregatorInstanceAddress, - } +// GetMockserverInitializerDataForOTPE creates mocked weiwatchers data needed for otpe +func GetMockserverInitializerDataForOTPE(OCRInstances []contracts.OffchainAggregator, chainlinkNodes []client.Chainlink) interface{} { + var contractsInfo []client.ContractInfoJSON + + for index, OCRInstance := range OCRInstances { + contractInfo := client.ContractInfoJSON{ + ContractVersion: 4, + Path: fmt.Sprintf("contract_%d", index), + Status: "live", + ContractAddress: OCRInstance.Address(), + } - contractsInfo := []client.ContractInfoJSON{contractInfo} + contractsInfo = append(contractsInfo, contractInfo) + } contractsInitializer := client.HttpInitializer{ Request: client.HttpRequest{Path: "/contracts.json"}, diff --git a/suite/testcommon/ocr.go b/suite/testcommon/ocr.go index 6d8f7f11d..4681b41cf 100644 --- a/suite/testcommon/ocr.go +++ b/suite/testcommon/ocr.go @@ -25,7 +25,7 @@ type OCRSetupInputs struct { NetworkInfo actions.NetworkInfo ChainlinkNodes []client.Chainlink DefaultWallet client.BlockchainWallet - OCRInstance contracts.OffchainAggregator + OCRInstances []contracts.OffchainAggregator Mockserver *client.MockserverClient } @@ -50,83 +50,88 @@ func DeployOCRForEnv(i *OCRSetupInputs, envInit environment.K8sEnvSpecInit) { }) } -// SetupOCRTest setup for an ocr test -func SetupOCRTest(i *OCRSetupInputs) { - By("Funding nodes and deploying OCR contract", func() { - ethAmount, err := i.NetworkInfo.Deployer.CalculateETHForTXs(i.NetworkInfo.Wallets.Default(), i.NetworkInfo.Network.Config(), 2) - Expect(err).ShouldNot(HaveOccurred()) - err = actions.FundChainlinkNodes( - i.ChainlinkNodes, - i.NetworkInfo.Client, - i.DefaultWallet, - ethAmount, - big.NewFloat(2), - ) - Expect(err).ShouldNot(HaveOccurred()) - - // Deploy and config OCR contract - deployer, err := contracts.NewContractDeployer(i.NetworkInfo.Client) - Expect(err).ShouldNot(HaveOccurred()) +// DeployOCRContracts deploys and funds a certain number of offchain aggregator contracts +func DeployOCRContracts(i *OCRSetupInputs, nrOfOCRContracts int) { + deployer, err := contracts.NewContractDeployer(i.NetworkInfo.Client) + Expect(err).ShouldNot(HaveOccurred()) - i.OCRInstance, err = deployer.DeployOffChainAggregator(i.DefaultWallet, contracts.DefaultOffChainAggregatorOptions()) + for nr := 0; nr < nrOfOCRContracts; nr++ { + OCRInstance, err := deployer.DeployOffChainAggregator(i.DefaultWallet, contracts.DefaultOffChainAggregatorOptions()) Expect(err).ShouldNot(HaveOccurred()) - err = i.OCRInstance.SetConfig( + err = OCRInstance.SetConfig( i.DefaultWallet, i.ChainlinkNodes[1:], contracts.DefaultOffChainAggregatorConfig(len(i.ChainlinkNodes[1:])), ) Expect(err).ShouldNot(HaveOccurred()) - err = i.OCRInstance.Fund(i.DefaultWallet, nil, big.NewFloat(2)) + err = OCRInstance.Fund(i.DefaultWallet, nil, big.NewFloat(2)) Expect(err).ShouldNot(HaveOccurred()) err = i.NetworkInfo.Client.WaitForEvents() Expect(err).ShouldNot(HaveOccurred()) - }) + i.OCRInstances = append(i.OCRInstances, OCRInstance) + } +} + +// FundNodes funds all chainlink nodes +func FundNodes(i *OCRSetupInputs) { + ethAmount, err := i.NetworkInfo.Deployer.CalculateETHForTXs(i.NetworkInfo.Wallets.Default(), i.NetworkInfo.Network.Config(), 2) + Expect(err).ShouldNot(HaveOccurred()) + err = actions.FundChainlinkNodes( + i.ChainlinkNodes, + i.NetworkInfo.Client, + i.DefaultWallet, + ethAmount, + big.NewFloat(2), + ) + Expect(err).ShouldNot(HaveOccurred()) } // SendOCRJobs bootstraps the first node and to the other nodes sends ocr jobs that // read from different adapters func SendOCRJobs(i *OCRSetupInputs) { By("Sending OCR jobs to chainlink nodes", func() { - bootstrapNode := i.ChainlinkNodes[0] - bootstrapP2PIds, err := bootstrapNode.ReadP2PKeys() - Expect(err).ShouldNot(HaveOccurred()) - bootstrapP2PId := bootstrapP2PIds.Data[0].Attributes.PeerID - bootstrapSpec := &client.OCRBootstrapJobSpec{ - ContractAddress: i.OCRInstance.Address(), - P2PPeerID: bootstrapP2PId, - IsBootstrapPeer: true, - } - _, err = bootstrapNode.CreateJob(bootstrapSpec) - Expect(err).ShouldNot(HaveOccurred()) - - for index := 1; index < len(i.ChainlinkNodes); index++ { - nodeP2PIds, err := i.ChainlinkNodes[index].ReadP2PKeys() - Expect(err).ShouldNot(HaveOccurred()) - nodeP2PId := nodeP2PIds.Data[0].Attributes.PeerID - nodeTransmitterAddress, err := i.ChainlinkNodes[index].PrimaryEthAddress() + for OCRInstanceIndex, OCRInstance := range i.OCRInstances { + bootstrapNode := i.ChainlinkNodes[0] + bootstrapP2PIds, err := bootstrapNode.ReadP2PKeys() Expect(err).ShouldNot(HaveOccurred()) - nodeOCRKeys, err := i.ChainlinkNodes[index].ReadOCRKeys() - Expect(err).ShouldNot(HaveOccurred()) - nodeOCRKeyId := nodeOCRKeys.Data[0].ID - - bta := client.BridgeTypeAttributes{ - Name: fmt.Sprintf("node_%d", index), - URL: fmt.Sprintf("%s/node_%d", i.Mockserver.Config.ClusterURL, index), + bootstrapP2PId := bootstrapP2PIds.Data[0].Attributes.PeerID + bootstrapSpec := &client.OCRBootstrapJobSpec{ + ContractAddress: OCRInstance.Address(), + P2PPeerID: bootstrapP2PId, + IsBootstrapPeer: true, } - - err = i.ChainlinkNodes[index].CreateBridge(&bta) + _, err = bootstrapNode.CreateJob(bootstrapSpec) Expect(err).ShouldNot(HaveOccurred()) - ocrSpec := &client.OCRTaskJobSpec{ - ContractAddress: i.OCRInstance.Address(), - P2PPeerID: nodeP2PId, - P2PBootstrapPeers: []client.Chainlink{bootstrapNode}, - KeyBundleID: nodeOCRKeyId, - TransmitterAddress: nodeTransmitterAddress, - ObservationSource: client.ObservationSourceSpecBridge(bta), + for nodeIndex := 1; nodeIndex < len(i.ChainlinkNodes); nodeIndex++ { + nodeP2PIds, err := i.ChainlinkNodes[nodeIndex].ReadP2PKeys() + Expect(err).ShouldNot(HaveOccurred()) + nodeP2PId := nodeP2PIds.Data[0].Attributes.PeerID + nodeTransmitterAddress, err := i.ChainlinkNodes[nodeIndex].PrimaryEthAddress() + Expect(err).ShouldNot(HaveOccurred()) + nodeOCRKeys, err := i.ChainlinkNodes[nodeIndex].ReadOCRKeys() + Expect(err).ShouldNot(HaveOccurred()) + nodeOCRKeyId := nodeOCRKeys.Data[0].ID + + bta := client.BridgeTypeAttributes{ + Name: fmt.Sprintf("node_%d_contract_%d", nodeIndex, OCRInstanceIndex), + URL: fmt.Sprintf("%s/node_%d_contract_%d", i.Mockserver.Config.ClusterURL, nodeIndex, OCRInstanceIndex), + } + + err = i.ChainlinkNodes[nodeIndex].CreateBridge(&bta) + Expect(err).ShouldNot(HaveOccurred()) + + ocrSpec := &client.OCRTaskJobSpec{ + ContractAddress: OCRInstance.Address(), + P2PPeerID: nodeP2PId, + P2PBootstrapPeers: []client.Chainlink{bootstrapNode}, + KeyBundleID: nodeOCRKeyId, + TransmitterAddress: nodeTransmitterAddress, + ObservationSource: client.ObservationSourceSpecBridge(bta), + } + _, err = i.ChainlinkNodes[nodeIndex].CreateJob(ocrSpec) + Expect(err).ShouldNot(HaveOccurred()) } - _, err = i.ChainlinkNodes[index].CreateJob(ocrSpec) - Expect(err).ShouldNot(HaveOccurred()) } }) } @@ -145,9 +150,11 @@ func CheckRound(i *OCRSetupInputs) { StartNewRound(i, 1) // Check answer is as expected - answer, err := i.OCRInstance.GetLatestAnswer(context.Background()) - Expect(err).ShouldNot(HaveOccurred()) - Expect(answer.Int64()).Should(Equal(int64(5)), "Latest answer from OCR is not as expected") + for _, OCRInstance := range i.OCRInstances { + answer, err := OCRInstance.GetLatestAnswer(context.Background()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(answer.Int64()).Should(Equal(int64(5)), "Latest answer from OCR is not as expected") + } // Change adapters answer to 10 adapterResults = []int{} @@ -160,26 +167,29 @@ func CheckRound(i *OCRSetupInputs) { StartNewRound(i, 2) // Check answer is as expected - answer, err = i.OCRInstance.GetLatestAnswer(context.Background()) - Expect(err).ShouldNot(HaveOccurred()) - Expect(answer.Int64()).Should(Equal(int64(10)), "Latest answer from OCR is not as expected") + for _, OCRInstance := range i.OCRInstances { + answer, err := OCRInstance.GetLatestAnswer(context.Background()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(answer.Int64()).Should(Equal(int64(10)), "Latest answer from OCR is not as expected") + } }) } // StartNewRound requests a new round from the ocr contract and waits for confirmation func StartNewRound(i *OCRSetupInputs, roundNr int64) { roundTimeout := time.Minute * 2 + for _, OCRInstance := range i.OCRInstances { + err := OCRInstance.RequestNewRound(i.DefaultWallet) + Expect(err).ShouldNot(HaveOccurred()) + err = i.SuiteSetup.DefaultNetwork().Client.WaitForEvents() + Expect(err).ShouldNot(HaveOccurred()) - err := i.OCRInstance.RequestNewRound(i.DefaultWallet) - Expect(err).ShouldNot(HaveOccurred()) - err = i.SuiteSetup.DefaultNetwork().Client.WaitForEvents() - Expect(err).ShouldNot(HaveOccurred()) - - // Wait for the second round - ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(i.OCRInstance, big.NewInt(roundNr), roundTimeout) - i.SuiteSetup.DefaultNetwork().Client.AddHeaderEventSubscription(i.OCRInstance.Address(), ocrRound) - err = i.SuiteSetup.DefaultNetwork().Client.WaitForEvents() - Expect(err).ShouldNot(HaveOccurred()) + // Wait for the second round + ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(OCRInstance, big.NewInt(roundNr), roundTimeout) + i.SuiteSetup.DefaultNetwork().Client.AddHeaderEventSubscription(OCRInstance.Address(), ocrRound) + err = i.SuiteSetup.DefaultNetwork().Client.WaitForEvents() + Expect(err).ShouldNot(HaveOccurred()) + } } // SetAdapterResults sets the mock responses in mockserver that are read by chainlink nodes @@ -189,24 +199,29 @@ func SetAdapterResults(i *OCRSetupInputs, results []int) { log.Info().Interface("New Adapter results", results).Msg("Setting new values") - for index := 1; index < len(i.ChainlinkNodes); index++ { - pathSelector := client.PathSelector{Path: fmt.Sprintf("/node_%d", index)} - err := i.Mockserver.ClearExpectation(pathSelector) - Expect(err).ShouldNot(HaveOccurred()) - } + for OCRInstanceIndex := range i.OCRInstances { + for nodeIndex := 1; nodeIndex < len(i.ChainlinkNodes); nodeIndex++ { + pathSelector := client.PathSelector{Path: fmt.Sprintf("/node_%d_contract_%d", nodeIndex, OCRInstanceIndex)} + err := i.Mockserver.ClearExpectation(pathSelector) + Expect(err).ShouldNot(HaveOccurred()) + } + } var initializers []client.HttpInitializer - for index := 1; index < len(i.ChainlinkNodes); index++ { - adResp := client.AdapterResponse{ - Id: "", - Data: client.AdapterResult{Result: results[index-1]}, - Error: nil, - } - nodesInitializer := client.HttpInitializer{ - Request: client.HttpRequest{Path: fmt.Sprintf("/node_%d", index)}, - Response: client.HttpResponse{Body: adResp}, + + for OCRInstanceIndex := range i.OCRInstances { + for nodeIndex := 1; nodeIndex < len(i.ChainlinkNodes); nodeIndex++ { + adResp := client.AdapterResponse{ + Id: "", + Data: client.AdapterResult{Result: results[nodeIndex-1]}, + Error: nil, + } + nodesInitializer := client.HttpInitializer{ + Request: client.HttpRequest{Path: fmt.Sprintf("/node_%d_contract_%d", nodeIndex, OCRInstanceIndex)}, + Response: client.HttpResponse{Body: adResp}, + } + initializers = append(initializers, nodesInitializer) } - initializers = append(initializers, nodesInitializer) } err := i.Mockserver.PutExpectations(initializers) @@ -214,15 +229,16 @@ func SetAdapterResults(i *OCRSetupInputs, results []int) { } // NewOCRSetupInputForObservability deploys and setups env and clients for testing observability -func NewOCRSetupInputForObservability(i *OCRSetupInputs, nodeCount int, rules map[string]*os.File) { +func NewOCRSetupInputForObservability(i *OCRSetupInputs, nodeCount int, contractCount int, rules map[string]*os.File) { DeployOCRForEnv( i, environment.NewChainlinkClusterForObservabilityTesting(nodeCount), ) - SetupOCRTest(i) + FundNodes(i) + DeployOCRContracts(i, contractCount) err := i.Mockserver.PutExpectations(steps.GetMockserverInitializerDataForOTPE( - i.OCRInstance.Address(), + i.OCRInstances, i.ChainlinkNodes, )) Expect(err).ShouldNot(HaveOccurred())