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

VRF-329: add BHS CTF test #11890

Merged
merged 13 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,11 @@ jobs:
os: ubuntu-latest
pyroscope_env: ci-smoke-vrf-evm-simulated
- name: vrfv2
nodes: 3
nodes: 4
os: ubuntu-latest
pyroscope_env: ci-smoke-vrf2-evm-simulated
- name: vrfv2plus
nodes: 3
nodes: 4
os: ubuntu-latest
pyroscope_env: ci-smoke-vrf2plus-evm-simulated
- name: forwarder_ocr
Expand Down
78 changes: 77 additions & 1 deletion integration-tests/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
package actions

import (
"context"
"crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"math/big"
"strings"
"sync"
"testing"
"time"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"

Expand All @@ -26,7 +30,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/logging"
"github.com/smartcontractkit/chainlink-testing-framework/testreporters"
"github.com/smartcontractkit/chainlink-testing-framework/utils/conversions"

"github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/contracts"
)
Expand Down Expand Up @@ -484,3 +488,75 @@ func GetTxFromAddress(tx *types.Transaction) (string, error) {
from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx)
return from.String(), err
}

// todo - move to CTF
func GetTxByHash(ctx context.Context, client blockchain.EVMClient, hash common.Hash) (*types.Transaction, bool, error) {
return client.(*blockchain.EthereumMultinodeClient).
DefaultClient.(*blockchain.EthereumClient).
Client.
TransactionByHash(ctx, hash)
}

// todo - move to CTF
func DecodeTxInputData(abiString string, data []byte) (map[string]interface{}, error) {
jsonABI, err := abi.JSON(strings.NewReader(abiString))
if err != nil {
return nil, err
}
methodSigData := data[:4]
inputsSigData := data[4:]
method, err := jsonABI.MethodById(methodSigData)
if err != nil {
return nil, err
}
inputsMap := make(map[string]interface{})
if err := method.Inputs.UnpackIntoMap(inputsMap, inputsSigData); err != nil {
return nil, err
}
return inputsMap, nil
}

// todo - move to EVMClient
func WaitForBlockNumberToBe(
waitForBlockNumberToBe uint64,
client blockchain.EVMClient,
wg *sync.WaitGroup,
timeout time.Duration,
t testing.TB,
) (uint64, error) {
blockNumberChannel := make(chan uint64)
errorChannel := make(chan error)
testContext, testCancel := context.WithTimeout(context.Background(), timeout)
defer testCancel()

ticker := time.NewTicker(time.Second * 1)
var blockNumber uint64
for {
select {
case <-testContext.Done():
ticker.Stop()
wg.Done()
return blockNumber,
fmt.Errorf("timeout waiting for Block Number to be: %d. Last recorded block number was: %d",
waitForBlockNumberToBe, blockNumber)
case <-ticker.C:
go func() {
currentBlockNumber, err := client.LatestBlockNumber(testcontext.Get(t))
if err != nil {
errorChannel <- err
}
blockNumberChannel <- currentBlockNumber
}()
case blockNumber = <-blockNumberChannel:
if blockNumber == waitForBlockNumberToBe {
ticker.Stop()
wg.Done()
return blockNumber, nil
}
case err := <-errorChannel:
ticker.Stop()
wg.Done()
return 0, err
}
}
}
137 changes: 137 additions & 0 deletions integration-tests/actions/vrf/common/actions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package common

import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/rs/zerolog"

"github.com/smartcontractkit/chainlink-testing-framework/blockchain"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2"
)

func CreateFundAndGetSendingKeys(
client blockchain.EVMClient,
node *VRFNode,
chainlinkNodeFunding float64,
numberOfTxKeysToCreate int,
chainID *big.Int,
) ([]string, []common.Address, error) {
newNativeTokenKeyAddresses, err := CreateAndFundSendingKeys(client, node, chainlinkNodeFunding, numberOfTxKeysToCreate, chainID)
if err != nil {
return nil, nil, err
}
nativeTokenPrimaryKeyAddress, err := node.CLNode.API.PrimaryEthAddress()
if err != nil {
return nil, nil, fmt.Errorf("%s, err %w", ErrNodePrimaryKey, err)
}
allNativeTokenKeyAddressStrings := append(newNativeTokenKeyAddresses, nativeTokenPrimaryKeyAddress)
allNativeTokenKeyAddresses := make([]common.Address, len(allNativeTokenKeyAddressStrings))
for _, addressString := range allNativeTokenKeyAddressStrings {
allNativeTokenKeyAddresses = append(allNativeTokenKeyAddresses, common.HexToAddress(addressString))
}
return allNativeTokenKeyAddressStrings, allNativeTokenKeyAddresses, nil
}

func CreateAndFundSendingKeys(
client blockchain.EVMClient,
node *VRFNode,
chainlinkNodeFunding float64,
numberOfNativeTokenAddressesToCreate int,
chainID *big.Int,
) ([]string, error) {
var newNativeTokenKeyAddresses []string
for i := 0; i < numberOfNativeTokenAddressesToCreate; i++ {
newTxKey, response, err := node.CLNode.API.CreateTxKey("evm", chainID.String())
if err != nil {
return nil, fmt.Errorf("%s, err %w", ErrNodeNewTxKey, err)
}
if response.StatusCode != 200 {
return nil, fmt.Errorf("error creating transaction key - response code, err %d", response.StatusCode)
}
newNativeTokenKeyAddresses = append(newNativeTokenKeyAddresses, newTxKey.Data.ID)
err = actions.FundAddress(client, newTxKey.Data.ID, big.NewFloat(chainlinkNodeFunding))
if err != nil {
return nil, err
}
}
return newNativeTokenKeyAddresses, nil
}

func SetupBHSNode(
env *test_env.CLClusterTestEnv,
config *testconfig.General,
numberOfTxKeysToCreate int,
chainID *big.Int,
coordinatorAddress string,
BHSAddress string,
txKeyFunding float64,
l zerolog.Logger,
bhsNode *VRFNode,
) error {
bhsTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys(
env.EVMClient,
bhsNode,
txKeyFunding,
numberOfTxKeysToCreate,
chainID,
)
if err != nil {
return err
}
bhsNode.TXKeyAddressStrings = bhsTXKeyAddressStrings
bhsSpec := client.BlockhashStoreJobSpec{
ForwardingAllowed: false,
CoordinatorV2Address: coordinatorAddress,
CoordinatorV2PlusAddress: coordinatorAddress,
BlockhashStoreAddress: BHSAddress,
FromAddresses: bhsTXKeyAddressStrings,
EVMChainID: chainID.String(),
WaitBlocks: *config.BHSJobWaitBlocks,
LookbackBlocks: *config.BHSJobLookBackBlocks,
PollPeriod: config.BHSJobPollPeriod.Duration,
RunTimeout: config.BHSJobRunTimeout.Duration,
}
l.Info().Msg("Creating BHS Job")
bhsJob, err := CreateBHSJob(
bhsNode.CLNode.API,
bhsSpec,
)
if err != nil {
return fmt.Errorf("%s, err %w", "", err)
}
bhsNode.Job = bhsJob
return nil
}

func CreateBHSJob(
chainlinkNode *client.ChainlinkClient,
bhsJobSpecConfig client.BlockhashStoreJobSpec,
) (*client.Job, error) {
jobUUID := uuid.New()
spec := &client.BlockhashStoreJobSpec{
Name: fmt.Sprintf("bhs-%s", jobUUID),
ForwardingAllowed: bhsJobSpecConfig.ForwardingAllowed,
CoordinatorV2Address: bhsJobSpecConfig.CoordinatorV2Address,
CoordinatorV2PlusAddress: bhsJobSpecConfig.CoordinatorV2PlusAddress,
BlockhashStoreAddress: bhsJobSpecConfig.BlockhashStoreAddress,
FromAddresses: bhsJobSpecConfig.FromAddresses,
EVMChainID: bhsJobSpecConfig.EVMChainID,
ExternalJobID: jobUUID.String(),
WaitBlocks: bhsJobSpecConfig.WaitBlocks,
LookbackBlocks: bhsJobSpecConfig.LookbackBlocks,
PollPeriod: bhsJobSpecConfig.PollPeriod,
RunTimeout: bhsJobSpecConfig.RunTimeout,
}

job, err := chainlinkNode.MustCreateJob(spec)
if err != nil {
return nil, fmt.Errorf("%s, err %w", ErrCreatingBHSJob, err)
}
return job, nil
}
27 changes: 27 additions & 0 deletions integration-tests/actions/vrf/common/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package common

const (
ErrNodePrimaryKey = "error getting node's primary ETH key"
ErrNodeNewTxKey = "error creating node's EVM transaction key"
ErrCreatingProvingKeyHash = "error creating a keyHash from the proving key"
ErrRegisteringProvingKey = "error registering a proving key on Coordinator contract"
ErrRegisterProvingKey = "error registering proving keys"
ErrEncodingProvingKey = "error encoding proving key"
ErrDeployBlockHashStore = "error deploying blockhash store"
ErrDeployCoordinator = "error deploying VRF CoordinatorV2"
ErrABIEncodingFunding = "error Abi encoding subscriptionID"
ErrSendingLinkToken = "error sending Link token"
ErrCreatingBHSJob = "error creating BHS job"
ErrParseJob = "error parsing job definition"
ErrSetVRFCoordinatorConfig = "error setting config for VRF Coordinator contract"
ErrCreateVRFSubscription = "error creating VRF Subscription"
ErrAddConsumerToSub = "error adding consumer to VRF Subscription"
ErrFundSubWithLinkToken = "error funding subscription with Link tokens"
ErrRestartCLNode = "error restarting CL node"
ErrWaitTXsComplete = "error waiting for TXs to complete"
ErrRequestRandomness = "error requesting randomness"
ErrLoadingCoordinator = "error loading coordinator contract"

ErrWaitRandomWordsRequestedEvent = "error waiting for RandomWordsRequested event"
ErrWaitRandomWordsFulfilledEvent = "error waiting for RandomWordsFulfilled event"
)
69 changes: 69 additions & 0 deletions integration-tests/actions/vrf/common/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package common

import (
"math/big"
"time"

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

type VRFEncodedProvingKey [2]*big.Int

// VRFV2PlusKeyData defines a jobs into and proving key info
type VRFKeyData struct {
VRFKey *client.VRFKey
EncodedProvingKey VRFEncodedProvingKey
KeyHash [32]byte
}

type VRFNodeType int

const (
VRF VRFNodeType = iota + 1
BHS
)

func (n VRFNodeType) String() string {
return [...]string{"VRF", "BHS"}[n-1]
}

func (n VRFNodeType) Index() int {
return int(n)
}

type VRFNode struct {
CLNode *test_env.ClNode
Job *client.Job
TXKeyAddressStrings []string
}

type VRFContracts struct {
CoordinatorV2 contracts.VRFCoordinatorV2
CoordinatorV2Plus contracts.VRFCoordinatorV2_5
VRFOwner contracts.VRFOwner
BHS contracts.BlockHashStore
VRFV2Consumer []contracts.VRFv2LoadTestConsumer
VRFV2PlusConsumer []contracts.VRFv2PlusLoadTestConsumer
}

type VRFOwnerConfig struct {
OwnerAddress string
UseVRFOwner bool
}

type VRFJobSpecConfig struct {
ForwardingAllowed bool
CoordinatorAddress string
FromAddresses []string
EVMChainID string
MinIncomingConfirmations int
PublicKey string
BatchFulfillmentEnabled bool
BatchFulfillmentGasMultiplier float64
EstimateGasMultiplier float64
PollPeriod time.Duration
RequestTimeout time.Duration
VRFOwnerConfig *VRFOwnerConfig
}
10 changes: 10 additions & 0 deletions integration-tests/actions/vrf/vrfv2/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package vrfv2

const (
ErrCreatingVRFv2Key = "error creating VRFv2 key"
ErrDeployVRFV2Wrapper = "error deploying VRFV2Wrapper"
ErrCreateVRFV2Jobs = "error creating VRF V2 Jobs"
ErrDeployVRFV2Contracts = "error deploying VRFV2 contracts"
ErrCreatingVRFv2Job = "error creating VRFv2 job"
ErrAdvancedConsumer = "error deploying VRFv2 Advanced Consumer"
)
Loading
Loading