Skip to content

Commit

Permalink
[BCF-2299] ocr2 testing (#9684)
Browse files Browse the repository at this point in the history
* Add integration testing OCRV2 helper functions for forwarders

* Add forwarders enabled flag to ocr2 smoke test setup func

* Add ocr2 with fwds smoke test

* Fix forwarders models definitions to match returned json

* Fix OCR2TaskJobSpec String method to include ForwardingAllowed field

* Change ocr2 fwds smoke test to run for 100 rounds

* Improve ocr2_helpers by removing DeployOCRv2Contracts code duplicates

* Improve ocr2_helpers by removing CreateOCRv2Jobs code duplicates

* Fix fwdrs ocr2 smoke test round val assertion to be of same type
  • Loading branch information
ilija42 authored Jun 22, 2023
1 parent 7fcf57d commit 6dd9bcc
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 28 deletions.
2 changes: 1 addition & 1 deletion core/web/evm_forwarders_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (cc *EVMForwardersController) Index(c *gin.Context, size, page, offset int)

// TrackEVMForwarderRequest is a JSONAPI request for creating an EVM forwarder.
type TrackEVMForwarderRequest struct {
EVMChainID *utils.Big `json:"chainID"`
EVMChainID *utils.Big `json:"evmChainId"`
Address common.Address `json:"address"`
}

Expand Down
17 changes: 7 additions & 10 deletions integration-tests/actions/ocr2_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func DeployOCRv2Contracts(
numberOfContracts int,
linkTokenContract contracts.LinkToken,
contractDeployer contracts.ContractDeployer,
chainlinkWorkerNodes []*client.Chainlink,
transmitters []string,
client blockchain.EVMClient,
) ([]contracts.OffchainAggregatorV2, error) {
var ocrInstances []contracts.OffchainAggregatorV2
Expand All @@ -57,14 +57,9 @@ func DeployOCRv2Contracts(
return nil, fmt.Errorf("error waiting for OCRv2 contract deployments: %w", err)
}

// Gather transmitter and address payees
var transmitters, payees []string
for _, node := range chainlinkWorkerNodes {
addr, err := node.PrimaryEthAddress()
if err != nil {
return nil, fmt.Errorf("error getting node's primary ETH address: %w", err)
}
transmitters = append(transmitters, addr)
// Gather address payees
var payees []string
for _ = range transmitters {
payees = append(payees, client.GetDefaultWallet().Address())
}

Expand Down Expand Up @@ -252,7 +247,7 @@ func GetOracleIdentitiesWithKeyIndex(
return S, oracleIdentities, eg.Wait()
}

// CreateOCRJobs bootstraps the first node and to the other nodes sends ocr jobs that
// CreateOCRv2Jobs bootstraps the first node and to the other nodes sends ocr jobs that
// read from different adapters, to be used in combination with SetAdapterResponses
func CreateOCRv2Jobs(
ocrInstances []contracts.OffchainAggregatorV2,
Expand All @@ -262,6 +257,7 @@ func CreateOCRv2Jobs(
mockServerPath string, // Path on the mock server for the Chainlink nodes to query
mockServerValue int, // Value to get from the mock server when querying the path
chainId uint64, // EVM chain ID
forwardingAllowed bool,
) error {
// Collect P2P ID
bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys()
Expand Down Expand Up @@ -332,6 +328,7 @@ func CreateOCRv2Jobs(
JobType: "offchainreporting2",
MaxTaskDuration: "1m",
ObservationSource: client.ObservationSourceSpecBridge(bta),
ForwardingAllowed: forwardingAllowed,
OCR2OracleSpec: job.OCR2OracleSpec{
PluginType: "median",
Relay: "evm",
Expand Down
25 changes: 13 additions & 12 deletions integration-tests/client/chainlink_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@ func (o *OCR2TaskJobSpec) String() (string, error) {
}{
Name: o.Name,
JobType: o.JobType,
ForwardingAllowed: o.ForwardingAllowed,
MaxTaskDuration: o.MaxTaskDuration,
ContractID: o.OCR2OracleSpec.ContractID,
FeedID: feedID,
Expand Down Expand Up @@ -1294,27 +1295,27 @@ type CLNodesWithKeys struct {
KeysBundle NodeKeysBundle
}

// Forwarders is the model that represents the created Forwarders when read
type Forwarders struct {
Data []ForwarderData `json:"data"`
}

// Forwarder the model that represents the created Forwarder when created
type Forwarder struct {
Data ForwarderData `json:"data"`
}

// Forwarders is the model that represents the created Forwarders when read
type Forwarders struct {
Data []Forwarder `json:"data"`
}

// ForwarderData is the model that represents the created Forwarder when read
type ForwarderData struct {
ID string `json:"id"`
Address string `json:"address"`
ChainID string `json:"chainId"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Type string `json:"type"`
ID string `json:"id"`
Attributes ForwarderAttributes `json:"attributes"`
}

// ForwarderAttributes is the model that represents attributes of a Forwarder
type ForwarderAttributes struct {
Address string `json:"address"`
ChainID string `json:"chainID"`
Address string `json:"address"`
ChainID string `json:"evmChainId"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
3 changes: 3 additions & 0 deletions integration-tests/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Enabled = true
AnnounceAddresses = ["0.0.0.0:6690"]
ListenAddresses = ["0.0.0.0:6690"]`

ForwarderNetworkDetailConfig = `[EVM.Transactions]
ForwardersEnabled = true`

BaseVRFV2NetworkDetailTomlConfig = `BlockBackfillDepth = 500
MinIncomingConfirmations = 3
[EVM.GasEstimator]
Expand Down
111 changes: 111 additions & 0 deletions integration-tests/smoke/forwarders_ocr2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package smoke

import (
"context"
"fmt"
"math/big"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"

"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client"
"github.com/smartcontractkit/chainlink-testing-framework/utils"

"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
)

func TestForwarderOCR2Basic(t *testing.T) {
t.Parallel()
testEnvironment, testNetwork := setupOCR2Test(t, true)
if testEnvironment.WillUseRemoteRunner() {
return
}

chainClient, err := blockchain.NewEVMClient(testNetwork, testEnvironment)
require.NoError(t, err, "Connecting to blockchain nodes shouldn't fail")
contractDeployer, err := contracts.NewContractDeployer(chainClient)
require.NoError(t, err, "Deploying contracts shouldn't fail")
contractLoader, err := contracts.NewContractLoader(chainClient)
require.NoError(t, err, "Loading contracts shouldn't fail")

chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment)
require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail")
bootstrapNode, workerNodes := chainlinkNodes[0], chainlinkNodes[1:]
workerNodeAddresses, err := actions.ChainlinkNodeAddresses(workerNodes)
require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail")
mockServer, err := ctfClient.ConnectMockServer(testEnvironment)
require.NoError(t, err, "Creating mockserver clients shouldn't fail")
t.Cleanup(func() {
err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.ErrorLevel, chainClient)
require.NoError(t, err, "Error tearing down environment")
})
chainClient.ParallelTransactions(true)

linkTokenContract, err := contractDeployer.DeployLinkTokenContract()
require.NoError(t, err, "Deploying Link Token Contract shouldn't fail")

err = actions.FundChainlinkNodes(workerNodes, chainClient, big.NewFloat(.05))
require.NoError(t, err, "Error funding Chainlink nodes")

operators, authorizedForwarders, _ := actions.DeployForwarderContracts(
t, contractDeployer, linkTokenContract, chainClient, len(workerNodes),
)

for i := range workerNodes {
actions.AcceptAuthorizedReceiversOperator(t, operators[i], authorizedForwarders[i], []common.Address{workerNodeAddresses[i]}, chainClient, contractLoader)
require.NoError(t, err, "Accepting Authorized Receivers on Operator shouldn't fail")
actions.TrackForwarder(t, chainClient, authorizedForwarders[i], workerNodes[i])
err = chainClient.WaitForEvents()

require.NoError(t, err, "Error waiting for events")
}

// Gather transmitters
var transmitters []string
for _, forwarderCommonAddress := range authorizedForwarders {
transmitters = append(transmitters, forwarderCommonAddress.Hex())
}

ocrInstances, err := actions.DeployOCRv2Contracts(1, linkTokenContract, contractDeployer, transmitters, chainClient)

require.NoError(t, err, "Error deploying OCRv2 contracts with forwarders")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")

err = actions.CreateOCRv2Jobs(ocrInstances, bootstrapNode, workerNodes, mockServer, "ocr2", 5, chainClient.GetChainID().Uint64(), true)
require.NoError(t, err, "Error creating OCRv2 jobs with forwarders")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for events")

ocrv2Config, err := actions.BuildMedianOCR2Config(workerNodes)
require.NoError(t, err, "Error building OCRv2 config")
ocrv2Config.Transmitters = authorizedForwarders

err = actions.ConfigureOCRv2AggregatorContracts(chainClient, ocrv2Config, ocrInstances)
require.NoError(t, err, "Error configuring OCRv2 aggregator contracts")

err = actions.StartNewOCR2Round(1, ocrInstances, chainClient, time.Minute*10)
require.NoError(t, err)

answer, err := ocrInstances[0].GetLatestAnswer(context.Background())
require.NoError(t, err, "Getting latest answer from OCRv2 contract shouldn't fail")
require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCRw contract to be 5 but got %d", answer.Int64())

for i := 2; i <= 100; i++ {
ocrRoundVal := (5 + i) % 10
err = mockServer.SetValuePath("ocr2", ocrRoundVal)
require.NoError(t, err)
err = actions.StartNewOCR2Round(int64(i), ocrInstances, chainClient, time.Minute*10)
require.NoError(t, err)

answer, err = ocrInstances[0].GetLatestAnswer(context.Background())
require.NoError(t, err, "Error getting latest OCRv2 answer")
require.Equal(t, int64(ocrRoundVal), answer.Int64(), fmt.Sprintf("Expected latest answer from OCRv2 contract to be %d but got %d", ocrRoundVal, answer.Int64()))
}
}
28 changes: 23 additions & 5 deletions integration-tests/smoke/ocr2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (

// Tests a basic OCRv2 median feed
func TestOCRv2Basic(t *testing.T) {
testEnvironment, testNetwork := setupOCR2Test(t)
testEnvironment, testNetwork := setupOCR2Test(t, false)
if testEnvironment.WillUseRemoteRunner() {
return
}
Expand All @@ -56,10 +56,20 @@ func TestOCRv2Basic(t *testing.T) {
err = actions.FundChainlinkNodes(workerNodes, chainClient, big.NewFloat(.05))
require.NoError(t, err, "Error funding Chainlink nodes")

aggregatorContracts, err := actions.DeployOCRv2Contracts(1, linkToken, contractDeployer, workerNodes, chainClient)
// Gather transmitters
var transmitters []string
for _, node := range workerNodes {
addr, err := node.PrimaryEthAddress()
if err != nil {
require.NoError(t, fmt.Errorf("error getting node's primary ETH address: %w", err))
}
transmitters = append(transmitters, addr)
}

aggregatorContracts, err := actions.DeployOCRv2Contracts(1, linkToken, contractDeployer, transmitters, chainClient)
require.NoError(t, err, "Error deploying OCRv2 aggregator contracts")

err = actions.CreateOCRv2Jobs(aggregatorContracts, bootstrapNode, workerNodes, mockServer, "ocr2", 5, chainClient.GetChainID().Uint64())
err = actions.CreateOCRv2Jobs(aggregatorContracts, bootstrapNode, workerNodes, mockServer, "ocr2", 5, chainClient.GetChainID().Uint64(), false)
require.NoError(t, err, "Error creating OCRv2 jobs")

ocrv2Config, err := actions.BuildMedianOCR2Config(workerNodes)
Expand Down Expand Up @@ -90,7 +100,7 @@ func TestOCRv2Basic(t *testing.T) {
)
}

func setupOCR2Test(t *testing.T) (
func setupOCR2Test(t *testing.T, forwardersEnabled bool) (
testEnvironment *environment.Environment,
testNetwork blockchain.EVMNetwork,
) {
Expand All @@ -103,8 +113,16 @@ func setupOCR2Test(t *testing.T) (
WsURLs: testNetwork.URLs,
})
}

var toml string
if forwardersEnabled {
toml = client.AddNetworkDetailedConfig(config.BaseOCR2Config, config.ForwarderNetworkDetailConfig, testNetwork)
} else {
toml = client.AddNetworksConfig(config.BaseOCR2Config, testNetwork)
}

chainlinkChart, err := chainlink.NewDeployment(6, map[string]interface{}{
"toml": client.AddNetworksConfig(config.BaseOCR2Config, testNetwork),
"toml": toml,
})
require.NoError(t, err, "Error creating chainlink deployment")

Expand Down

0 comments on commit 6dd9bcc

Please sign in to comment.