diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml index b5519fbad0e..ddd4e28e461 100644 --- a/.github/actions/setup-go/action.yml +++ b/.github/actions/setup-go/action.yml @@ -34,6 +34,7 @@ runs: with: go-version-file: ${{ inputs.go-version-file }} cache: false + check-latest: true - name: Get branch name if: ${{ inputs.only-modules == 'false' }} diff --git a/.github/workflows/find-new-flaky-tests.yml b/.github/workflows/find-new-flaky-tests.yml index 0cdfb2b3091..a685f4f5e70 100644 --- a/.github/workflows/find-new-flaky-tests.yml +++ b/.github/workflows/find-new-flaky-tests.yml @@ -95,7 +95,6 @@ jobs: - name: Set up Go 1.21.9 uses: actions/setup-go@v5.0.2 with: - go-version: '1.21.9' cache: false - name: Install flakeguard diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 1034a8fe834..ea0016014a7 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -148,7 +148,7 @@ jobs: - name: Lint Go uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 with: - version: v1.59.1 + version: v1.62.0 # We already cache these directories in setup-go skip-pkg-cache: true skip-build-cache: true diff --git a/.tool-versions b/.tool-versions index 70b6d01ce14..49f7ef749d1 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,4 @@ -golang 1.22.8 +golang 1.23.3 mockery 2.46.3 nodejs 20.13.1 pnpm 9.4.0 diff --git a/core/chainlink.Dockerfile b/core/chainlink.Dockerfile index 753172a1a9f..82858f3437c 100644 --- a/core/chainlink.Dockerfile +++ b/core/chainlink.Dockerfile @@ -1,5 +1,5 @@ # Build image: Chainlink binary -FROM golang:1.22-bullseye as buildgo +FROM golang:1.23-bullseye as buildgo RUN go version WORKDIR /chainlink @@ -31,7 +31,7 @@ RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds | xargs RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana | xargs -I % ln -s % /chainlink-solana # Build image: Plugins -FROM golang:1.22-bullseye as buildplugins +FROM golang:1.23-bullseye as buildplugins RUN go version WORKDIR /chainlink-feeds diff --git a/core/cmd/admin_commands.go b/core/cmd/admin_commands.go index 7bde0ec23fb..0af851d2c06 100644 --- a/core/cmd/admin_commands.go +++ b/core/cmd/admin_commands.go @@ -374,6 +374,7 @@ func (s *Shell) Profile(c *cli.Context) error { } respContent := string(b) // taken from pprof.Profile https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/pprof/pprof.go#L133 + // note: no longer triggers as of 1.23 if strings.Contains(respContent, "profile duration exceeds server's WriteTimeout") { errs <- fmt.Errorf("%w: %s", ErrProfileTooLong, respContent) } else { diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index f4661a58e82..0bf5067d364 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -463,36 +463,6 @@ func TestShell_ChangePassword(t *testing.T) { require.Contains(t, err.Error(), "Unauthorized") } -func TestShell_Profile_InvalidSecondsParam(t *testing.T) { - t.Parallel() - - app := startNewApplicationV2(t, nil) - u := cltest.NewUserWithSession(t, app.AuthenticationProvider()) - enteredStrings := []string{u.Email, cltest.Password} - prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: enteredStrings} - - client := app.NewAuthenticatingShell(prompter) - - set := flag.NewFlagSet("test", 0) - flagSetApplyFromAction(client.RemoteLogin, set, "") - - require.NoError(t, set.Set("file", "../internal/fixtures/apicredentials")) - require.NoError(t, set.Set("bypass-version-check", "true")) - - c := cli.NewContext(nil, set, nil) - err := client.RemoteLogin(c) - require.NoError(t, err) - - // pick a value larger than the default http service write timeout - d := app.Config.WebServer().HTTPWriteTimeout() + 2*time.Second - set.Uint("seconds", uint(d.Seconds()), "") - tDir := t.TempDir() - set.String("output_dir", tDir, "") - err = client.Profile(cli.NewContext(nil, set, nil)) - wantErr := cmd.ErrProfileTooLong - require.ErrorAs(t, err, &wantErr) -} - func TestShell_Profile(t *testing.T) { t.Parallel() diff --git a/core/platform/monitoring.go b/core/platform/monitoring.go index 30221db240c..b5e12ace80c 100644 --- a/core/platform/monitoring.go +++ b/core/platform/monitoring.go @@ -1,5 +1,10 @@ package platform +import ( + "iter" + "slices" +) + // Observability keys const ( KeyCapabilityID = "capabilityID" @@ -12,4 +17,13 @@ const ( KeyStepRef = "stepRef" ) -var OrderedLabelKeys = []string{KeyStepRef, KeyStepID, KeyTriggerID, KeyCapabilityID, KeyWorkflowExecutionID, KeyWorkflowID} +func LabelKeysSorted() iter.Seq[string] { + return slices.Values([]string{ + KeyStepRef, + KeyStepID, + KeyTriggerID, + KeyCapabilityID, + KeyWorkflowExecutionID, + KeyWorkflowID, + }) +} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 8d0bd34b6c3..b8439a14f46 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/core/scripts -go 1.22.8 +go 1.23 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ diff --git a/core/services/keystore/keys/ocrkey/key_bundle.go b/core/services/keystore/keys/ocrkey/key_bundle.go deleted file mode 100644 index a73d8d5bd1e..00000000000 --- a/core/services/keystore/keys/ocrkey/key_bundle.go +++ /dev/null @@ -1,259 +0,0 @@ -package ocrkey - -import ( - "crypto/ecdsa" - "crypto/ed25519" - cryptorand "crypto/rand" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "log" - "time" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/pkg/errors" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" - "golang.org/x/crypto/curve25519" - - "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -type ( - // KeyBundle represents the bundle of keys needed for OCR - KeyBundle struct { - ID models.Sha256Hash - onChainSigning *onChainPrivateKey - offChainSigning *offChainPrivateKey - offChainEncryption *[curve25519.ScalarSize]byte - } - - // EncryptedKeyBundle holds an encrypted KeyBundle - EncryptedKeyBundle struct { - ID models.Sha256Hash - OnChainSigningAddress OnChainSigningAddress - OffChainPublicKey OffChainPublicKey - ConfigPublicKey ConfigPublicKey - EncryptedPrivateKeys []byte - CreatedAt time.Time - UpdatedAt time.Time - DeletedAt *time.Time - } -) - -func (ekb EncryptedKeyBundle) GetID() string { - return ekb.ID.String() -} - -func (ekb *EncryptedKeyBundle) SetID(value string) error { - var result models.Sha256Hash - decodedString, err := hex.DecodeString(value) - - if err != nil { - return err - } - - copy(result[:], decodedString[:32]) - ekb.ID = result - return nil -} - -// New makes a new set of OCR key bundles from cryptographically secure entropy -func New() (*KeyBundle, error) { - return NewFrom(cryptorand.Reader, cryptorand.Reader, cryptorand.Reader) -} - -// NewFrom makes a new set of OCR key bundles from cryptographically secure entropy -func NewFrom(onChainSigning io.Reader, offChainSigning io.Reader, offChainEncryption io.Reader) (*KeyBundle, error) { - ecdsaKey, err := ecdsa.GenerateKey(curve, onChainSigning) - if err != nil { - return nil, err - } - onChainPriv := (*onChainPrivateKey)(ecdsaKey) - - _, offChainPriv, err := ed25519.GenerateKey(offChainSigning) - if err != nil { - return nil, err - } - var encryptionPriv [curve25519.ScalarSize]byte - _, err = offChainEncryption.Read(encryptionPriv[:]) - if err != nil { - return nil, err - } - k := &KeyBundle{ - onChainSigning: onChainPriv, - offChainSigning: (*offChainPrivateKey)(&offChainPriv), - offChainEncryption: &encryptionPriv, - } - marshalledPrivK, err := json.Marshal(k) - if err != nil { - return nil, err - } - k.ID = sha256.Sum256(marshalledPrivK) - return k, nil -} - -// SignOnChain returns an ethereum-style ECDSA secp256k1 signature on msg. -func (pk *KeyBundle) SignOnChain(msg []byte) (signature []byte, err error) { - return pk.onChainSigning.Sign(msg) -} - -// SignOffChain returns an EdDSA-Ed25519 signature on msg. -func (pk *KeyBundle) SignOffChain(msg []byte) (signature []byte, err error) { - return pk.offChainSigning.Sign(msg) -} - -// ConfigDiffieHellman returns the shared point obtained by multiplying someone's -// public key by a secret scalar ( in this case, the offChainEncryption key.) -func (pk *KeyBundle) ConfigDiffieHellman(base *[curve25519.PointSize]byte) ( - sharedPoint *[curve25519.PointSize]byte, err error, -) { - p, err := curve25519.X25519(pk.offChainEncryption[:], base[:]) - if err != nil { - return nil, err - } - sharedPoint = new([ed25519.PublicKeySize]byte) - copy(sharedPoint[:], p) - return sharedPoint, nil -} - -// PublicKeyAddressOnChain returns public component of the keypair used in -// SignOnChain -func (pk *KeyBundle) PublicKeyAddressOnChain() ocrtypes.OnChainSigningAddress { - return ocrtypes.OnChainSigningAddress(pk.onChainSigning.Address()) -} - -// PublicKeyOffChain returns the public component of the keypair used in SignOffChain -func (pk *KeyBundle) PublicKeyOffChain() ocrtypes.OffchainPublicKey { - return ocrtypes.OffchainPublicKey(pk.offChainSigning.PublicKey()) -} - -// PublicKeyConfig returns the public component of the keypair used in ConfigKeyShare -func (pk *KeyBundle) PublicKeyConfig() [curve25519.PointSize]byte { - rv, err := curve25519.X25519(pk.offChainEncryption[:], curve25519.Basepoint) - if err != nil { - log.Println("failure while computing public key: " + err.Error()) - } - var rvFixed [curve25519.PointSize]byte - copy(rvFixed[:], rv) - return rvFixed -} - -// Encrypt combines the KeyBundle into a single json-serialized -// bytes array and then encrypts -func (pk *KeyBundle) Encrypt(auth string, scryptParams utils.ScryptParams) (*EncryptedKeyBundle, error) { - return pk.encrypt(auth, scryptParams) -} - -// encrypt combines the KeyBundle into a single json-serialized -// bytes array and then encrypts, using the provided scrypt params -// separated into a different function so that scryptParams can be -// weakened in tests -func (pk *KeyBundle) encrypt(auth string, scryptParams utils.ScryptParams) (*EncryptedKeyBundle, error) { - marshalledPrivK, err := json.Marshal(&pk) - if err != nil { - return nil, err - } - cryptoJSON, err := keystore.EncryptDataV3( - marshalledPrivK, - []byte(adulteratedPassword(auth)), - scryptParams.N, - scryptParams.P, - ) - if err != nil { - return nil, errors.Wrapf(err, "could not encrypt ocr key") - } - encryptedPrivKeys, err := json.Marshal(&cryptoJSON) - if err != nil { - return nil, errors.Wrapf(err, "could not encode cryptoJSON") - } - return &EncryptedKeyBundle{ - ID: pk.ID, - OnChainSigningAddress: pk.onChainSigning.Address(), - OffChainPublicKey: pk.offChainSigning.PublicKey(), - ConfigPublicKey: pk.PublicKeyConfig(), - EncryptedPrivateKeys: encryptedPrivKeys, - }, nil -} - -// Decrypt returns the PrivateKeys in e, decrypted via auth, or an error -func (ekb *EncryptedKeyBundle) Decrypt(auth string) (*KeyBundle, error) { - var cryptoJSON keystore.CryptoJSON - err := json.Unmarshal(ekb.EncryptedPrivateKeys, &cryptoJSON) - if err != nil { - return nil, errors.Wrapf(err, "invalid cryptoJSON for OCR key bundle") - } - marshalledPrivK, err := keystore.DecryptDataV3(cryptoJSON, adulteratedPassword(auth)) - if err != nil { - return nil, errors.Wrapf(err, "could not decrypt OCR key bundle") - } - var pk KeyBundle - err = json.Unmarshal(marshalledPrivK, &pk) - if err != nil { - return nil, errors.Wrapf(err, "could not unmarshal OCR key bundle") - } - return &pk, nil -} - -// MarshalJSON marshals the private keys into json -func (pk *KeyBundle) MarshalJSON() ([]byte, error) { - rawKeyData := keyBundleRawData{ - EcdsaD: *pk.onChainSigning.D, - Ed25519PrivKey: []byte(*pk.offChainSigning), - OffChainEncryption: *pk.offChainEncryption, - } - return json.Marshal(&rawKeyData) -} - -// UnmarshalJSON constructs KeyBundle from raw json -func (pk *KeyBundle) UnmarshalJSON(b []byte) (err error) { - var rawKeyData keyBundleRawData - err = json.Unmarshal(b, &rawKeyData) - if err != nil { - return err - } - ecdsaDSize := len(rawKeyData.EcdsaD.Bytes()) - if ecdsaDSize > curve25519.PointSize { - return errors.Wrapf(ErrScalarTooBig, "got %d byte ecdsa scalar", ecdsaDSize) - } - - publicKey := ecdsa.PublicKey{Curve: curve} - publicKey.X, publicKey.Y = curve.ScalarBaseMult(rawKeyData.EcdsaD.Bytes()) - privateKey := ecdsa.PrivateKey{ - PublicKey: publicKey, - D: &rawKeyData.EcdsaD, - } - onChainSigning := onChainPrivateKey(privateKey) - offChainSigning := offChainPrivateKey(rawKeyData.Ed25519PrivKey) - pk.onChainSigning = &onChainSigning - pk.offChainSigning = &offChainSigning - pk.offChainEncryption = &rawKeyData.OffChainEncryption - pk.ID = sha256.Sum256(b) - return nil -} - -// String reduces the risk of accidentally logging the private key -func (pk KeyBundle) String() string { - addressOnChain := pk.PublicKeyAddressOnChain() - return fmt.Sprintf( - "KeyBundle{PublicKeyAddressOnChain: %s, PublicKeyOffChain: %s}", - hex.EncodeToString(addressOnChain[:]), - hex.EncodeToString(pk.PublicKeyOffChain()), - ) -} - -// GoString reduces the risk of accidentally logging the private key -func (pk KeyBundle) GoString() string { - return pk.String() -} - -// GoString reduces the risk of accidentally logging the private key -func (pk KeyBundle) ToV2() KeyV2 { - return KeyV2{ - OnChainSigning: pk.onChainSigning, - OffChainSigning: pk.offChainSigning, - OffChainEncryption: pk.offChainEncryption, - } -} diff --git a/core/services/keystore/keys/ocrkey/key_bundle_test.go b/core/services/keystore/keys/ocrkey/key_bundle_test.go deleted file mode 100644 index fe9391735a1..00000000000 --- a/core/services/keystore/keys/ocrkey/key_bundle_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package ocrkey_test - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -func assertKeyBundlesNotEqual(t *testing.T, pk1 ocrkey.KeyV2, pk2 ocrkey.KeyV2) { - assert.NotEqual(t, pk1.ID(), pk2.ID()) - assert.NotEqual(t, pk1.ExportedOnChainSigning().X, pk2.ExportedOnChainSigning().X) - assert.NotEqual(t, pk1.ExportedOnChainSigning().Y, pk2.ExportedOnChainSigning().Y) - assert.NotEqual(t, pk1.ExportedOnChainSigning().D, pk2.ExportedOnChainSigning().D) - assert.NotEqual(t, pk1.ExportedOffChainSigning().PublicKey(), pk2.ExportedOffChainSigning().PublicKey()) - assert.NotEqual(t, pk1.ExportedOffChainEncryption(), pk2.ExportedOffChainEncryption()) -} - -func TestOCRKeys_New(t *testing.T) { - t.Parallel() - pk1, err := ocrkey.NewV2() - require.NoError(t, err) - pk2, err := ocrkey.NewV2() - require.NoError(t, err) - pk3, err := ocrkey.NewV2() - require.NoError(t, err) - assertKeyBundlesNotEqual(t, pk1, pk2) - assertKeyBundlesNotEqual(t, pk1, pk3) - assertKeyBundlesNotEqual(t, pk2, pk3) -} - -func TestOCRKeys_NewBundleIDMatchesOld(t *testing.T) { - t.Parallel() - oldKey, err := ocrkey.New() - require.NoError(t, err) - newKey := oldKey.ToV2() - require.Equal(t, oldKey.ID.String(), newKey.ID()) -} - -func TestOCRKeys_Raw_Key(t *testing.T) { - t.Parallel() - key := ocrkey.MustNewV2XXXTestingOnly(big.NewInt(1)) - require.Equal(t, key.ID(), key.Raw().Key().ID()) -} - -func TestOCRKeys_BundleSetID(t *testing.T) { - t.Parallel() - - k, err := ocrkey.New() - require.NoError(t, err) - ek, err := k.Encrypt("test", utils.FastScryptParams) - require.NoError(t, err) - - oldId := ek.GetID() - err = ek.SetID("48656c6c6f20476f7068657221") - require.NoError(t, err) - - assert.NotEqual(t, oldId, ek.GetID()) - - err = ek.SetID("invalid id") - assert.Error(t, err) -} - -func TestOCRKeys_BundleDecrypt(t *testing.T) { - t.Parallel() - - k, err := ocrkey.New() - require.NoError(t, err) - ek, err := k.Encrypt("test", utils.FastScryptParams) - require.NoError(t, err) - - _, err = ek.Decrypt("wrongpass") - assert.Error(t, err) - - dk, err := ek.Decrypt("test") - require.NoError(t, err) - - dk.GoString() - assert.Equal(t, k.GoString(), dk.GoString()) - assert.Equal(t, k.ID.String(), dk.ID.String()) -} - -func TestOCRKeys_BundleMarshalling(t *testing.T) { - t.Parallel() - - k, err := ocrkey.New() - require.NoError(t, err) - k2, err := ocrkey.New() - require.NoError(t, err) - - mk, err := k.MarshalJSON() - require.NoError(t, err) - - err = k2.UnmarshalJSON(mk) - require.NoError(t, err) - - assert.Equal(t, k.String(), k2.String()) -} diff --git a/core/services/keystore/keys/ocrkey/key_v2_test.go b/core/services/keystore/keys/ocrkey/key_v2_test.go new file mode 100644 index 00000000000..3fd2417b704 --- /dev/null +++ b/core/services/keystore/keys/ocrkey/key_v2_test.go @@ -0,0 +1,38 @@ +package ocrkey_test + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" +) + +func assertKeyBundlesNotEqual(t *testing.T, pk1 ocrkey.KeyV2, pk2 ocrkey.KeyV2) { + assert.NotEqual(t, pk1.ID(), pk2.ID()) + assert.NotEqual(t, pk1.ExportedOnChainSigning().X, pk2.ExportedOnChainSigning().X) + assert.NotEqual(t, pk1.ExportedOnChainSigning().Y, pk2.ExportedOnChainSigning().Y) + assert.NotEqual(t, pk1.ExportedOnChainSigning().D, pk2.ExportedOnChainSigning().D) + assert.NotEqual(t, pk1.ExportedOffChainSigning().PublicKey(), pk2.ExportedOffChainSigning().PublicKey()) + assert.NotEqual(t, pk1.ExportedOffChainEncryption(), pk2.ExportedOffChainEncryption()) +} + +func TestOCRKeys_New(t *testing.T) { + t.Parallel() + pk1, err := ocrkey.NewV2() + require.NoError(t, err) + pk2, err := ocrkey.NewV2() + require.NoError(t, err) + pk3, err := ocrkey.NewV2() + require.NoError(t, err) + assertKeyBundlesNotEqual(t, pk1, pk2) + assertKeyBundlesNotEqual(t, pk1, pk3) + assertKeyBundlesNotEqual(t, pk2, pk3) +} +func TestOCRKeys_Raw_Key(t *testing.T) { + t.Parallel() + key := ocrkey.MustNewV2XXXTestingOnly(big.NewInt(1)) + require.Equal(t, key.ID(), key.Raw().Key().ID()) +} diff --git a/core/services/keystore/keys/ocrkey/off_chan_private_key_test.go b/core/services/keystore/keys/ocrkey/off_chan_private_key_test.go deleted file mode 100644 index 0c0f6a96957..00000000000 --- a/core/services/keystore/keys/ocrkey/off_chan_private_key_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package ocrkey - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestOCRKeys_OffChainPrivateKey(t *testing.T) { - t.Parallel() - - k, err := New() - require.NoError(t, err) - - sig, err := k.offChainSigning.Sign([]byte("hello world")) - - assert.NoError(t, err) - assert.NotEmpty(t, sig) -} diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index b958e171c0c..23af3ed3d28 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -1294,7 +1294,7 @@ func (e *workflowError) Error() string { } // prefix the error with the labels - for _, label := range platform.OrderedLabelKeys { + for label := range platform.LabelKeysSorted() { // This will silently ignore any labels that are not present in the map // are we ok with this? if value, ok := e.labels[label]; ok { diff --git a/deployment/go.mod b/deployment/go.mod index 6320167168b..d67615f736f 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/deployment -go 1.22.8 +go 1.23 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ diff --git a/go.mod b/go.mod index 23db187326b..e7c1468bfbc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/v2 -go 1.22.8 +go 1.23 require ( github.com/Depado/ginprom v1.8.0 diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index e85f4cdc4e5..5d980451979 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -1,4 +1,4 @@ -golang 1.22.8 +golang 1.23.3 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 76e6cbd4185..53283967976 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -350,12 +350,13 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa return nil, err } - var gasLimit int64 - gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) + gasLimit, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) if err != nil { - gasLimit = client.Cfg.Network.TransferGasFee - } else { - gasLimit = int64(gasLimitRaw) + transferGasFee := client.Cfg.Network.TransferGasFee + if transferGasFee < 0 { + return nil, fmt.Errorf("negative transfer gas fee: %d", transferGasFee) + } + gasLimit = uint64(transferGasFee) } gasPrice := big.NewInt(0) @@ -363,14 +364,17 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa gasTipCap := big.NewInt(0) if payload.GasLimit != nil { - gasLimit = *payload.GasLimit + if *payload.GasLimit < 0 { + return nil, fmt.Errorf("negative gas limit: %d", *payload.GasLimit) + } + gasLimit = uint64(*payload.GasLimit) } if client.Cfg.Network.EIP1559DynamicFees { // if any of the dynamic fees are not set, we need to either estimate them or read them from config if payload.GasFeeCap == nil || payload.GasTipCap == nil { // estimation or config reading happens here - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + txOptions := client.NewTXOpts(seth.WithGasLimit(gasLimit)) gasFeeCap = txOptions.GasFeeCap gasTipCap = txOptions.GasTipCap } @@ -385,7 +389,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa } } else { if payload.GasPrice == nil { - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + txOptions := client.NewTXOpts(seth.WithGasLimit(gasLimit)) gasPrice = txOptions.GasPrice } else { gasPrice = payload.GasPrice @@ -399,7 +403,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Nonce: nonce, To: &payload.ToAddress, Value: payload.Amount, - Gas: uint64(gasLimit), + Gas: gasLimit, GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, } @@ -408,7 +412,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Nonce: nonce, To: &payload.ToAddress, Value: payload.Amount, - Gas: uint64(gasLimit), + Gas: gasLimit, GasPrice: gasPrice, } } @@ -429,7 +433,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Str("To", payload.ToAddress.Hex()). Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). + Uint64("Gas Limit", gasLimit). Str("Gas Price", gasPrice.String()). Str("Gas Fee Cap", gasFeeCap.String()). Str("Gas Tip Cap", gasTipCap.String()). @@ -449,7 +453,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Str("TxHash", signedTx.Hash().String()). Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). + Uint64("Gas Limit", gasLimit). Str("Gas Price", gasPrice.String()). Str("Gas Fee Cap", gasFeeCap.String()). Str("Gas Tip Cap", gasTipCap.String()). @@ -1038,7 +1042,7 @@ func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, net } latestBlockNumber := header.Number.Uint64() finalizedBlockNumber := latestBlockNumber - network.FinalityDepth - return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) + return client.Client.HeaderByNumber(ctx, new(big.Int).SetUint64(finalizedBlockNumber)) } // SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses @@ -1241,7 +1245,7 @@ func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClien endBlock, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get end block") - total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) + total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, new(big.Int).SetUint64(startBlock), new(big.Int).SetUint64(endBlock), registry, registryVersion) require.NoError(t, err, "Failed to get staleness data") if stale > 0 || reverted > 0 { logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 1f17634e58d..25033201dd1 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "strings" "testing" @@ -642,10 +643,15 @@ func calculateOCR2ConfigArgs(a *AutomationTest, S []int, oracleIdentities []conf MaxUpkeepBatchSize: a.PluginConfig.MaxUpkeepBatchSize, }) + rMax := a.PublicConfig.RMax + if rMax > math.MaxUint8 { + panic(fmt.Errorf("rmax overflows uint8: %d", rMax)) + } + return ocr2.ContractSetConfigArgsForTests( a.PublicConfig.DeltaProgress, a.PublicConfig.DeltaResend, a.PublicConfig.DeltaRound, a.PublicConfig.DeltaGrace, - a.PublicConfig.DeltaStage, uint8(a.PublicConfig.RMax), + a.PublicConfig.DeltaStage, uint8(rMax), S, oracleIdentities, offC, nil, a.PublicConfig.MaxDurationQuery, a.PublicConfig.MaxDurationObservation, diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 0966e0b486e..1562e363f8c 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -670,15 +670,14 @@ Distribute your funds across multiple private keys and update your configuration func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { concurrency := client.Cfg.GetMaxConcurrency() - var msg string - if client.Cfg.IsSimulatedNetwork() { - msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) - } else { - msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) - } - if concurrency < minConcurrency { - return 0, fmt.Errorf(msg) + var err error + if client.Cfg.IsSimulatedNetwork() { + err = fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) + } else { + err = fmt.Errorf(INSUFFICIENT_STATIC_KEYS, concurrency) + } + return 0, err } return concurrency, nil diff --git a/integration-tests/actions/refund.go b/integration-tests/actions/refund.go index 0eb83e736e5..e9910928c6c 100644 --- a/integration-tests/actions/refund.go +++ b/integration-tests/actions/refund.go @@ -5,6 +5,7 @@ import ( "crypto/ecdsa" "encoding/json" "fmt" + "math" "math/big" "regexp" "strconv" @@ -343,6 +344,9 @@ func returnAllFundsIfPossible(log zerolog.Logger, sethClient *seth.Client, fromP if err != nil { gasLimit = sethClient.Cfg.Network.TransferGasFee } else { + if gasLimitRaw > math.MaxInt64 { + return fmt.Errorf("gas limit overflows int64: %d", gasLimitRaw) + } gasLimit = int64(gasLimitRaw) } diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 3d3a549458a..c997bb837c7 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -105,7 +105,7 @@ func SetupVRFV2_5Environment( return nil, nil, nil, err } l.Info().Str("Coordinator", vrfContracts.CoordinatorV2Plus.Address()).Msg("Registering Proving Key") - provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, vrfContracts.CoordinatorV2Plus, uint64(assets.GWei(*configGeneral.CLNodeMaxGasPriceGWei).Int64())) + provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, vrfContracts.CoordinatorV2Plus, assets.GWei(*configGeneral.CLNodeMaxGasPriceGWei).ToInt().Uint64()) if err != nil { return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrRegisteringProvingKey, err) } diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index c24ae2ecd54..d0587dad789 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -631,7 +631,11 @@ func (ccipModule *CCIPCommon) UpdateTokenPricesAtRegularInterval(ctx context.Con aggregators = append(aggregators, contract) } go func(aggregators []*contracts.MockAggregator) { - rand.NewSource(uint64(time.Now().UnixNano())) + now := time.Now().UnixNano() + if now < 0 { + panic(fmt.Errorf("negative timestamp: %d", now)) + } + rand.NewSource(uint64(now)) ticker := time.NewTicker(interval) for { select { @@ -1661,7 +1665,11 @@ func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx co if err != nil { return nil, fmt.Errorf("error while getting average source block time. Error: %w", err) } - filterFromBlock := latestBlock - uint64(timeframe.Duration()/avgBlockTime) + blocks := timeframe.Duration() / avgBlockTime + if blocks < 0 { + return nil, fmt.Errorf("negative blocks: %d", blocks) + } + filterFromBlock := latestBlock - uint64(blocks) //nolint:gosec // G115 false positive onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(sourceCCIP.OnRamp.EthAddress.Hex()), sourceCCIP.Common.ChainClient.Backend()) @@ -1678,7 +1686,7 @@ func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx co _ = iterator.Close() }() if iterator.Next() { - hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(iterator.Event.Raw.BlockNumber))) + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(iterator.Event.Raw.BlockNumber)) if err != nil { return nil, fmt.Errorf("error getting header for block: %d, Error: %w", iterator.Event.Raw.BlockNumber, err) } @@ -4157,7 +4165,7 @@ func (c *CCIPTestEnv) SetUpNodeKeysAndFund( nodeFund *big.Float, chains []blockchain.EVMClient, ) error { - if c.CLNodes == nil || len(c.CLNodes) == 0 { + if len(c.CLNodes) == 0 { return fmt.Errorf("no chainlink nodes to setup") } var chainlinkNodes []*nodeclient.ChainlinkClient diff --git a/integration-tests/ccip-tests/actions/reorg_helpers.go b/integration-tests/ccip-tests/actions/reorg_helpers.go index 017b8ffab69..2ce9639613b 100644 --- a/integration-tests/ccip-tests/actions/reorg_helpers.go +++ b/integration-tests/ccip-tests/actions/reorg_helpers.go @@ -27,16 +27,16 @@ type ReorgConfig struct { // DstGethHTTPURL dest chain Geth HTTP URL DstGethHTTPURL string // SrcFinalityDepth source chain finality depth - SrcFinalityDepth uint64 + SrcFinalityDepth int // DstGethHTTPURL dest chain finality depth - DstFinalityDepth uint64 + DstFinalityDepth int // FinalityDelta blocks to rewind below or above finality FinalityDelta int } // Validate validates ReorgConfig params func (rc *ReorgConfig) Validate() error { - if rc.FinalityDelta >= int(rc.SrcFinalityDepth) || rc.FinalityDelta >= int(rc.DstFinalityDepth) { + if rc.FinalityDelta >= rc.SrcFinalityDepth || rc.FinalityDelta >= rc.DstFinalityDepth { return fmt.Errorf( "finality delta can't be higher than source or dest chain finality, delta: %d, src: %d, dst: %d", rc.FinalityDelta, rc.SrcFinalityDepth, rc.DstFinalityDepth, diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 83fe12a60a6..15b5ed8cd0d 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -2241,7 +2241,11 @@ func (a *MockAggregator) UpdateRoundData(answer *big.Int, minP, maxP *int) error // if answer is nil, we calculate the answer with random percentage (within the provided range) of latest answer if answer == nil { - rand.Seed(uint64(time.Now().UnixNano())) + now := time.Now().UnixNano() + if now < 0 { + return fmt.Errorf("negative timestamp: %d", now) + } + rand.Seed(uint64(now)) randomNumber := rand.Intn(pointer.GetInt(maxP)-pointer.GetInt(minP)+1) + pointer.GetInt(minP) // answer = previous round answer + (previous round answer * random percentage) answer = new(big.Int).Add(a.Answer, new(big.Int).Div(new(big.Int).Mul(a.Answer, big.NewInt(int64(randomNumber))), big.NewInt(100))) diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index 08054459481..a729bd5daec 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -2,6 +2,7 @@ package smoke import ( "fmt" + "math" "math/big" "testing" "time" @@ -874,8 +875,8 @@ func TestSmokeCCIPReorgBelowFinality(t *testing.T) { require.NoError(t, err, "Send requests failed") rs := SetupReorgSuite(t, &log, setUpOutput) // run below finality reorg in both source and destination chain - blocksBackSrc := int(rs.Cfg.SrcFinalityDepth) - rs.Cfg.FinalityDelta - blocksBackDst := int(rs.Cfg.DstFinalityDepth) - rs.Cfg.FinalityDelta + blocksBackSrc := rs.Cfg.SrcFinalityDepth - rs.Cfg.FinalityDelta + blocksBackDst := rs.Cfg.DstFinalityDepth - rs.Cfg.FinalityDelta rs.RunReorg(rs.DstClient, blocksBackSrc, "Source", 2*time.Second) rs.RunReorg(rs.DstClient, blocksBackDst, "Destination", 2*time.Second) time.Sleep(1 * time.Minute) @@ -930,10 +931,10 @@ func performAboveFinalityReorgAndValidate(t *testing.T, network string) { logPollerName := "" if network == "Destination" { logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.DestChain.GetChainID()) - rs.RunReorg(rs.DstClient, int(rs.Cfg.DstFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + rs.RunReorg(rs.DstClient, rs.Cfg.DstFinalityDepth+rs.Cfg.FinalityDelta, network, 2*time.Second) } else { logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.SourceChain.GetChainID()) - rs.RunReorg(rs.SrcClient, int(rs.Cfg.SrcFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + rs.RunReorg(rs.SrcClient, rs.Cfg.SrcFinalityDepth+rs.Cfg.FinalityDelta, network, 2*time.Second) } clNodes := setUpOutput.Env.CLNodes // assert every node is detecting the reorg (LogPollInterval is set as 1s for faster detection) @@ -1123,17 +1124,25 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter // SetupReorgSuite defines the setup required to perform re-org step func SetupReorgSuite(t *testing.T, lggr *zerolog.Logger, setupOutput *testsetups.CCIPTestSetUpOutputs) *actions.ReorgSuite { - var finalitySrc uint64 - var finalityDst uint64 + var finalitySrc int + var finalityDst int if setupOutput.Cfg.SelectedNetworks[0].FinalityTag { finalitySrc = 10 } else { - finalitySrc = setupOutput.Cfg.SelectedNetworks[0].FinalityDepth + finalityDepth := setupOutput.Cfg.SelectedNetworks[0].FinalityDepth + if finalityDepth > math.MaxInt { + t.Fatalf("source finality depth overflows int: %d", finalityDepth) + } + finalitySrc = int(finalityDepth) } if setupOutput.Cfg.SelectedNetworks[1].FinalityTag { finalityDst = 10 } else { - finalityDst = setupOutput.Cfg.SelectedNetworks[1].FinalityDepth + finalityDepth := setupOutput.Cfg.SelectedNetworks[1].FinalityDepth + if finalityDepth > math.MaxInt { + t.Fatalf("destination finality depth overflows int: %d", finalityDepth) + } + finalityDst = int(finalityDepth) } var srcGethHTTPURL, dstGethHTTPURL string if setupOutput.Env.LocalCluster != nil { diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index 725b1e90a4f..4caa8a9ac00 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -584,7 +584,7 @@ func (c *ChainlinkDeployment) Validate() error { if c.NoOfNodes == nil { return errors.New("chainlink config is invalid, NoOfNodes should be specified") } - if c.Nodes != nil && len(c.Nodes) > 0 { + if len(c.Nodes) > 0 { noOfNodes := pointer.GetInt(c.NoOfNodes) if noOfNodes != len(c.Nodes) { return errors.New("chainlink config is invalid, NoOfNodes and Nodes length mismatch") diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index eee424d50d1..52901c4161a 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -3,6 +3,7 @@ package testsetups import ( "context" "fmt" + "math" "math/big" "math/rand" "os" @@ -234,6 +235,9 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { var chainIDs []int64 existingChainIDs := make(map[uint64]struct{}) for _, net := range c.SelectedNetworks { + if net.ChainID < 0 { + return fmt.Errorf("negative chain ID: %d", net.ChainID) + } existingChainIDs[uint64(net.ChainID)] = struct{}{} } for _, id := range chainselectors.TestChainIds() { @@ -241,6 +245,9 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { if _, exists := existingChainIDs[id]; exists { continue } + if id > math.MaxInt64 { + return fmt.Errorf("chain ID overflows int64: %d", id) + } chainIDs = append(chainIDs, int64(id)) } for i := 0; i < c.TestGroupInput.NoOfNetworks-actualNoOfNetworks; i++ { @@ -300,7 +307,7 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { var newNetworkPairs []NetworkPair denselyConnectedNetworks := make(map[string]struct{}) // if densely connected networks are provided, choose all the network pairs containing the networks mentioned in the list for DenselyConnectedNetworkChainIds - if c.TestGroupInput.DenselyConnectedNetworkChainIds != nil && len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { + if len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { for _, n := range c.TestGroupInput.DenselyConnectedNetworkChainIds { denselyConnectedNetworks[n] = struct{}{} } diff --git a/integration-tests/ccip-tests/testsetups/test_helpers.go b/integration-tests/ccip-tests/testsetups/test_helpers.go index 4a480cdaa40..28464120263 100644 --- a/integration-tests/ccip-tests/testsetups/test_helpers.go +++ b/integration-tests/ccip-tests/testsetups/test_helpers.go @@ -182,6 +182,9 @@ func NewLocalDevEnvironmentWithRMN( func MustNetworksToRPCMap(evmNetworks []*blockchain.EVMNetwork) map[uint64]string { rpcs := make(map[uint64]string) for _, network := range evmNetworks { + if network.ChainID < 0 { + panic(fmt.Errorf("negative chain ID: %d", network.ChainID)) + } sel, err := chainsel.SelectorFromChainId(uint64(network.ChainID)) if err != nil { panic(err) @@ -495,6 +498,9 @@ func FundNodes(t *testing.T, lggr zerolog.Logger, env *test_env.CLClusterTestEnv require.NoError(t, err, "Error getting seth client for network %s", evmNetwork.Name) require.Greater(t, len(sethClient.PrivateKeys), 0, seth.ErrNoKeyLoaded) privateKey := sethClient.PrivateKeys[0] + if evmNetwork.ChainID < 0 { + t.Fatalf("negative chain ID: %d", evmNetwork.ChainID) + } for _, node := range nodes { nodeAddr, ok := node.AccountAddr[uint64(evmNetwork.ChainID)] require.True(t, ok, "Account address not found for chain %d", evmNetwork.ChainID) @@ -544,6 +550,9 @@ func CreateChainConfigFromNetworks( if len(privateEthereumNetworks) == 0 { for _, net := range evmNetworks { chainId := net.ChainID + if chainId < 0 { + t.Fatalf("negative chain ID: %d", chainId) + } chainName, err := chainsel.NameFromChainId(uint64(chainId)) require.NoError(t, err, "Error getting chain name") pvtKeyStr, exists := networkPvtKeys[chainId] @@ -576,6 +585,9 @@ func CreateChainConfigFromNetworks( require.NoError(t, err) deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(int64(chainId))) require.NoError(t, err) + if chainId < 0 { + t.Fatalf("negative chain ID: %d", chainId) + } chains = append(chains, devenv.ChainConfig{ ChainID: uint64(chainId), ChainName: chainName, diff --git a/integration-tests/ccip-tests/types/config/node/core.go b/integration-tests/ccip-tests/types/config/node/core.go index 5c9defbbb51..404719e31e1 100644 --- a/integration-tests/ccip-tests/types/config/node/core.go +++ b/integration-tests/ccip-tests/types/config/node/core.go @@ -3,6 +3,7 @@ package node import ( "bytes" "fmt" + "math" "math/big" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" @@ -54,6 +55,9 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork, commonChainConfig *evmcfg } } if evmConfig.Chain.FinalityDepth == nil && network.FinalityDepth > 0 { + if network.FinalityDepth > math.MaxUint32 { + panic(fmt.Errorf("finality depth overflows uint32: %d", network.FinalityDepth)) + } evmConfig.Chain.FinalityDepth = ptr.Ptr(uint32(network.FinalityDepth)) } if evmConfig.Chain.FinalityTagEnabled == nil && network.FinalityTag { diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index 3e18fe177f0..1a4624c2dd3 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -2809,14 +2809,14 @@ type AutomationConsumerBenchmarkUpkeepObserver struct { firstBlockNum uint64 // Records the number of the first block that came in lastBlockNum uint64 // Records the number of the last block that came in - blockRange int64 // How many blocks to watch upkeeps for + blockRange uint64 // How many blocks to watch upkeeps for upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results upkeepIndex int64 firstEligibleBuffer int64 // State variables, changes as we get blocks - blocksSinceSubscription int64 // How many blocks have passed since subscribing + blocksSinceSubscription uint64 // How many blocks have passed since subscribing blocksSinceEligible int64 // How many blocks have come in since upkeep has been eligible for check countEligible int64 // Number of times the upkeep became eligible countMissed int64 // Number of times we missed SLA for performing upkeep @@ -2832,7 +2832,7 @@ func NewAutomationConsumerBenchmarkUpkeepObserver( contract AutomationConsumerBenchmark, registry KeeperRegistry, upkeepID *big.Int, - blockRange int64, + blockRange uint64, upkeepSLA int64, metricsReporter *testreporters.KeeperBenchmarkTestReporter, upkeepIndex int64, @@ -2906,7 +2906,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader o.blocksSinceEligible = 0 } - isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleBuffer)) + isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), new(big.Int).SetUint64(o.blockRange), big.NewInt(o.firstEligibleBuffer)) if err != nil { return false, err } @@ -2924,7 +2924,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader o.blocksSinceEligible++ } - if o.blocksSinceSubscription >= o.blockRange || int64(o.lastBlockNum-o.firstBlockNum) >= o.blockRange { + if o.blocksSinceSubscription >= o.blockRange || o.lastBlockNum-o.firstBlockNum >= o.blockRange { if o.blocksSinceEligible > 0 { if o.blocksSinceEligible > o.upkeepSLA { o.l.Warn(). @@ -2953,7 +2953,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader Str("Upkeep_ID", o.upkeepID.String()). Str("Contract_Address", o.instance.Address()). Int64("Upkeeps_Performed", upkeepCount.Int64()). - Int64("Total_Blocks_Watched", o.blocksSinceSubscription). + Uint64("Total_Blocks_Watched", o.blocksSinceSubscription). Str("Registry_Address", o.registry.Address()). Msg("Finished Watching for Upkeeps") diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 610c3e29e1e..cdce826f2c2 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -2,6 +2,7 @@ package test_env import ( "fmt" + "math" "os" "path/filepath" "slices" @@ -279,10 +280,16 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { processFn := func(log logstream.LogContent, count *int) error { countSoFar := count + if *countSoFar < 0 { + return fmt.Errorf("negative count: %d", *countSoFar) + } newCount, err := testreporters.ScanLogLine(b.l, string(log.Content), b.chainlinkNodeLogScannerSettings.FailingLogLevel, uint(*countSoFar), b.chainlinkNodeLogScannerSettings.Threshold, b.chainlinkNodeLogScannerSettings.AllowedMessages) if err != nil { return err } + if newCount > math.MaxInt { + return fmt.Errorf("new count overflows int: %d", newCount) + } *count = int(newCount) return nil } @@ -494,7 +501,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) if b.isEVM { - if b.evmNetworkOption != nil && len(b.evmNetworkOption) > 0 { + if len(b.evmNetworkOption) > 0 { for _, fn := range b.evmNetworkOption { fn(&networkConfig) } diff --git a/integration-tests/go.mod b/integration-tests/go.mod index ddcd3ae65fa..3f1939c86b1 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/integration-tests -go 1.22.8 +go 1.23 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ diff --git a/integration-tests/load/functions/gateway.go b/integration-tests/load/functions/gateway.go index ac5f895ac18..59443ac6e30 100644 --- a/integration-tests/load/functions/gateway.go +++ b/integration-tests/load/functions/gateway.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "math" "time" "github.com/ethereum/go-ethereum/crypto" @@ -119,6 +120,9 @@ func UploadS4Secrets(rc *resty.Client, s4Cfg *S4SecretsCfg) (uint8, uint64, erro return 0, 0, fmt.Errorf("node response was not successful") } } + if envelope.SlotID > math.MaxUint8 { + return 0, 0, fmt.Errorf("slot ID overflows uint8: %d", envelope.SlotID) + } return uint8(envelope.SlotID), envelope.Version, nil } diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index 38eddd3163e..5dd2aee4f06 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -41,14 +41,20 @@ func NewGatewaySecretsSetGun(cfg types.FunctionsTestConfig, method string, pKey func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) - randSlot := uint(rand.Intn(5)) - version := uint64(time.Now().UnixNano()) + randSlot := rand.Intn(5) + if randSlot < 0 { + panic(fmt.Errorf("negative rand slot: %d", randSlot)) + } + version := time.Now().UnixNano() + if version < 0 { + panic(fmt.Errorf("negative timestamp: %d", version)) + } expiration := int64(60 * 60 * 1000) secret := fmt.Sprintf("{\"ltsecret\": \"%s\"}", randNum) log.Debug(). - Uint("SlotID", randSlot). + Int("SlotID", randSlot). Str("MessageID", randNum). - Uint64("Version", version). + Int64("Version", version). Int64("Expiration", expiration). Str("Secret", secret). Msg("Sending S4 envelope") @@ -73,8 +79,8 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { MessageID: randNum, Method: "secrets_set", DonID: *cfg.Common.DONID, - S4SetSlotID: randSlot, - S4SetVersion: version, + S4SetSlotID: uint(randSlot), + S4SetVersion: uint64(version), S4SetExpirationPeriod: expiration, S4SetPayload: secrets, }) @@ -86,8 +92,14 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) - randSlot := uint(rand.Intn(5)) - version := uint64(time.Now().UnixNano()) + randSlot := rand.Intn(5) + if randSlot < 0 { + panic(fmt.Errorf("negative rand slot: %d", randSlot)) + } + version := time.Now().UnixNano() + if version < 0 { + panic(fmt.Errorf("negative timestamp: %d", version)) + } expiration := int64(60 * 60 * 1000) network := m.Cfg.GetNetworkConfig().SelectedNetworks[0] if len(m.Cfg.GetNetworkConfig().WalletKeys[network]) < 1 { @@ -101,8 +113,8 @@ func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { MessageID: randNum, Method: m.Method, DonID: *cfg.Common.DONID, - S4SetSlotID: randSlot, - S4SetVersion: version, + S4SetSlotID: uint(randSlot), + S4SetVersion: uint64(version), S4SetExpirationPeriod: expiration, }); err != nil { return &wasp.Response{Error: err.Error(), Failed: true} diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 46c2c12921a..f018655a54e 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -123,14 +123,22 @@ func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsCo if err != nil { return nil, fmt.Errorf("failed to generate tdh2 secrets: %w", err) } + randInt := mrand.Intn(5) + if randInt < 0 { + return nil, fmt.Errorf("negative random int: %d", randInt) + } + now := time.Now().UnixNano() + if now < 0 { + return nil, fmt.Errorf("negative timestamp: %d", now) + } slotID, slotVersion, err := UploadS4Secrets(resty.New(), &S4SecretsCfg{ GatewayURL: *cfg.Common.GatewayURL, PrivateKey: selectedNetwork.PrivateKeys[0], MessageID: strconv.Itoa(mrand.Intn(100000-1) + 1), Method: "secrets_set", DonID: *cfg.Common.DONID, - S4SetSlotID: uint(mrand.Intn(5)), - S4SetVersion: uint64(time.Now().UnixNano()), + S4SetSlotID: uint(randInt), + S4SetVersion: uint64(now), S4SetExpirationPeriod: 60 * 60 * 1000, S4SetPayload: encryptedSecrets, }) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c548b6d9159..a6cfd5bddb9 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/load-tests -go 1.22.8 +go 1.23 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -28,6 +28,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.1 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c ) require ( @@ -38,57 +39,6 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect dario.cat/mergo v1.0.1 // indirect - github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect - github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect - github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect - github.com/aws/smithy-go v1.22.0 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect - github.com/cloudwego/base64x v0.1.4 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect - github.com/coder/websocket v1.8.12 // indirect - github.com/go-viper/mapstructure/v2 v2.1.0 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect - github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect - github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect - go.opentelemetry.io/otel/log v0.6.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - k8s.io/apimachinery v0.31.2 // indirect -) - -// avoids ambigious imports of indirect dependencies -exclude github.com/hashicorp/consul v1.2.1 - -require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect @@ -121,9 +71,24 @@ require ( github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect + github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect + github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect github.com/aws/jsii-runtime-go v1.104.0 // indirect + github.com/aws/smithy-go v1.22.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect @@ -131,11 +96,13 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect @@ -145,12 +112,15 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.37.5 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect @@ -236,6 +206,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect github.com/goccy/go-json v0.10.2 // indirect @@ -245,12 +216,14 @@ require ( github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -342,6 +315,7 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -407,6 +381,9 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.10.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect @@ -422,17 +399,22 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.29 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect + github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.1 // indirect @@ -485,10 +467,21 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect @@ -499,7 +492,6 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/crypto v0.28.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect @@ -517,6 +509,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -525,6 +518,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.31.2 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/apimachinery v0.31.2 // indirect k8s.io/cli-runtime v0.31.2 // indirect k8s.io/client-go v0.31.2 // indirect k8s.io/component-base v0.31.2 // indirect @@ -539,9 +533,12 @@ require ( sigs.k8s.io/kustomize/api v0.17.2 // indirect sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect; indirect nhooyr.io/websocket v1.8.7 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) +// avoids ambigious imports of indirect dependencies +exclude github.com/hashicorp/consul v1.2.1 + replace ( // geth wants v2.3.4 but that is incompatible with github.com/cometbft/cometbft v0.37.5 which when bumped is incompatible with github.com/cosmos/cosmos-sdk // This line can be removed after these imports are bumped or removed. diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 20a20b40834..9a680e5bd99 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,6 +4,7 @@ import ( "math/rand" "github.com/rs/zerolog" + "golang.org/x/exp/constraints" "github.com/smartcontractkit/chainlink-testing-framework/wasp" @@ -123,9 +124,9 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { if randBool() && requestCountPerTX > deviation { - requestCountPerTX -= uint16(randInRange(0, int(deviation))) + requestCountPerTX -= randInRange(0, deviation) } else { - requestCountPerTX += uint16(randInRange(0, int(deviation))) + requestCountPerTX += randInRange(0, deviation) } return requestCountPerTX } @@ -133,6 +134,7 @@ func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { func randBool() bool { return rand.Intn(2) == 1 } -func randInRange(min int, max int) int { - return rand.Intn(max-min+1) + min + +func randInRange[I constraints.Integer](lower, upper I) I { + return I(rand.Intn(int(upper-lower)+1)) + lower } diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 4aac3927518..f6a194ab6ce 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -5,6 +5,7 @@ import ( "math/rand" "github.com/rs/zerolog" + "golang.org/x/exp/constraints" "github.com/smartcontractkit/chainlink-testing-framework/wasp" @@ -131,13 +132,13 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { if actions.RandBool() && requestCountPerTX > deviation { - requestCountPerTX -= uint16(randInRange(0, int(deviation))) + requestCountPerTX -= randInRange(0, deviation) } else { - requestCountPerTX += uint16(randInRange(0, int(deviation))) + requestCountPerTX += randInRange(0, deviation) } return requestCountPerTX } -func randInRange(min int, max int) int { - return rand.Intn(max-min+1) + min +func randInRange[I constraints.Integer](lower, upper I) I { + return I(rand.Intn(int(upper-lower)+1)) + lower } diff --git a/integration-tests/smoke/ccip_rmn_test.go b/integration-tests/smoke/ccip_rmn_test.go index e8e81688239..76f5ef3e02a 100644 --- a/integration-tests/smoke/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip_rmn_test.go @@ -209,6 +209,9 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { }) if rmnNodeInfo.isSigner { + if rmnNodeInfo.id < 0 { + t.Fatalf("node id is negative: %d", rmnNodeInfo.id) + } rmnRemoteSigners = append(rmnRemoteSigners, rmn_remote.RMNRemoteSigner{ OnchainPublicKey: rmn.RMN.EVMOnchainPublicKey, NodeIndex: uint64(rmnNodeInfo.id), @@ -218,6 +221,9 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { var rmnHomeSourceChains []rmn_home.RMNHomeSourceChain for remoteChainIdx, remoteF := range tc.homeChainConfig.f { + if remoteF < 0 { + t.Fatalf("negative remote F: %d", remoteF) + } // configure remote chain details on the home contract rmnHomeSourceChains = append(rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ ChainSelector: chainSelectors[remoteChainIdx], @@ -289,6 +295,9 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { remoteSel := chainSelectors[remoteCfg.chainIdx] chState, ok := onChainState.Chains[remoteSel] require.True(t, ok) + if remoteCfg.f < 0 { + t.Fatalf("negative F: %d", remoteCfg.f) + } rmnRemoteConfig := rmn_remote.RMNRemoteConfig{ RmnHomeContractConfigDigest: activeDigest, Signers: rmnRemoteSigners, diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 0cc7d9fafe4..3f2f4dadae8 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -100,7 +100,10 @@ func TestForwarderOCR2Basic(t *testing.T) { err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") - err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) + if sethClient.ChainID < 0 { + t.Errorf("negative chain ID: %d", sethClient.ChainID) + } + err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) //nolint:gosec // G115 false positive require.NoError(t, err, "Error creating OCRv2 jobs with forwarders") err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index b5891e7a3e8..edf8c228a07 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -3,6 +3,7 @@ package smoke import ( "context" "fmt" + "math" "math/big" "testing" "time" @@ -130,6 +131,9 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") + if sb > math.MaxInt64 { + t.Fatalf("start block overflows int64: %d", sb) + } startBlock := int64(sb) l.Info().Int64("Starting Block", startBlock).Msg("STARTING EVENT EMISSION") @@ -163,6 +167,9 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli chaosError := <-chaosDoneCh require.NoError(t, chaosError, "Error encountered during chaos experiment") + if eb > math.MaxInt64 { + t.Fatalf("end block overflows int64: %d", eb) + } // use ridciuously high end block so that we don't have to find out the block number of the last block in which logs were emitted // as that's not trivial to do (i.e. just because chain was at block X when log emission ended it doesn't mean all events made it to that block) endBlock := int64(eb) + 10000 @@ -205,6 +212,9 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") + if sb > math.MaxInt64 { + t.Fatalf("start block overflows int64: %d", sb) + } startBlock := int64(sb) l.Info().Int64("Starting Block", startBlock).Msg("STARTING EVENT EMISSION") @@ -219,6 +229,9 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { eb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") + if eb > math.MaxInt64 { + t.Fatalf("end block overflows int64: %d", eb) + } endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), *evmNetwork, cfg) require.NoError(t, err, "Error getting end block to wait for") @@ -282,7 +295,7 @@ type logPollerEnvironment struct { // deploying registry and log emitter contracts and registering log triggered upkeeps func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfig, logScannerSettings test_env.ChainlinkNodeLogScannerSettings) logPollerEnvironment { cfg := testConfig.LogPoller - if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 { + if len(cfg.General.EventsToEmit) == 0 { l.Warn().Msg("No events to emit specified, using all events from log emitter contract") for _, event := range logpoller.EmitterABI.Events { cfg.General.EventsToEmit = append(cfg.General.EventsToEmit, event) diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 325c88f979a..a011dfdffc6 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -125,7 +125,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.DeleteBridges(nodeClients) require.NoError(t, err) - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) //nolint:gosec // G115 false positive require.NoError(t, err, "Error creating OCRv2 jobs") err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) @@ -195,7 +195,10 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, aggregatorContracts, err := actions.SetupOCRv2Contracts(l, sethClient, config.OCR2, common.HexToAddress(linkContract.Address()), transmitters, ocrOffChainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) + if sethClient.ChainID < 0 { + t.Errorf("negative chain ID: %d", sethClient.ChainID) + } + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) //nolint:gosec // G115 false positive require.NoError(t, err, "Error creating OCRv2 jobs") if !config.OCR2.UseExistingOffChainAggregatorsContracts() || (config.OCR2.UseExistingOffChainAggregatorsContracts() && config.OCR2.ConfigureExistingOffChainAggregatorsContracts()) { diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 3c9beec5ddb..1e2c4711527 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -2,6 +2,7 @@ package smoke import ( "fmt" + "math" "math/big" "os" "strconv" @@ -167,7 +168,7 @@ func TestVRFv2Basic(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(status.RandomWords)) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -322,7 +323,7 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest) // Check random word count - require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(consumerStatus.RandomWords)) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -773,7 +774,7 @@ func TestVRFOwner(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(status.RandomWords)) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -943,14 +944,18 @@ func TestVRFV2WithBHS(t *testing.T) { ) require.NoError(t, err, "error requesting randomness") randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") + blocks := *configCopy.VRFv2.General.BHSJobWaitBlocks + if blocks < 0 { + t.Fatalf("negative blocks: %d", blocks) + } var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+uint64(*configCopy.VRFv2.General.BHSJobWaitBlocks), + randRequestBlockNumber+uint64(blocks), sethClient, &wg, nil, @@ -996,7 +1001,7 @@ func TestVRFV2WithBHS(t *testing.T) { } var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { - randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting blockhash for a blocknumber which was stored in BHS contract") }, "2m", "1s").Should(gomega.Succeed()) l.Info(). @@ -1268,6 +1273,9 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + if randRequestCount > math.MaxUint16 { + t.Fatalf("rand request count overflows uint16: %d", randRequestCount) + } configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert @@ -1389,7 +1397,10 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) + if randRequestCount > math.MaxUint16 { + t.Fatalf("rand request count overflows uint16: %d", randRequestCount) + } + configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) //nolint:gosec // G115 false positive // test and assert _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index df0917fd4fb..a57230f1a0c 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -2,6 +2,7 @@ package smoke import ( "fmt" + "math" "math/big" "os" "strings" @@ -156,7 +157,7 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, *configCopy.VRFv2Plus.General.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, int(*configCopy.VRFv2Plus.General.NumberOfWords), len(status.RandomWords)) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -219,7 +220,7 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, *testConfig.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, int(*testConfig.NumberOfWords), len(status.RandomWords)) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -327,7 +328,7 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfcommon.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, int(*testConfig.NumberOfWords), len(consumerStatus.RandomWords)) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -376,7 +377,7 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfcommon.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + require.Equal(t, int(*testConfig.NumberOfWords), len(consumerStatus.RandomWords)) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -958,7 +959,7 @@ func TestVRFv2PlusMigration(t *testing.T) { newCoordinator, err := contracts.DeployVRFCoordinatorV2PlusUpgradedVersion(sethClient, vrfContracts.BHS.Address()) require.NoError(t, err, "error deploying VRF CoordinatorV2PlusUpgradedVersion") - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).ToInt().Uint64()) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -1127,7 +1128,7 @@ func TestVRFv2PlusMigration(t *testing.T) { newCoordinator, err := contracts.DeployVRFCoordinatorV2PlusUpgradedVersion(sethClient, vrfContracts.BHS.Address()) require.NoError(t, err, "error deploying VRF CoordinatorV2PlusUpgradedVersion") - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).ToInt().Uint64()) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -1345,13 +1346,13 @@ func TestVRFV2PlusWithBHS(t *testing.T) { var wg sync.WaitGroup wg.Add(1) - waitForNumberOfBlocks := 257 + const waitForNumberOfBlocks = 257 desiredBlockNumberReached := make(chan bool) go func() { //Wait at least 256 blocks _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+uint64(waitForNumberOfBlocks), + randRequestBlockNumber+waitForNumberOfBlocks, sethClient, &wg, desiredBlockNumberReached, @@ -1396,7 +1397,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) require.NoError(t, err, "error getting blockhash for a blocknumber which was stored in BHS contract") l.Info(). @@ -1443,14 +1444,17 @@ func TestVRFV2PlusWithBHS(t *testing.T) { ) require.NoError(t, err, "error requesting randomness") randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") + if *configCopy.VRFv2Plus.General.BHSJobWaitBlocks < 0 { + t.Fatalf("negative job wait blocks: %d", *configCopy.VRFv2Plus.General.BHSJobWaitBlocks) + } var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+uint64(*configCopy.VRFv2Plus.General.BHSJobWaitBlocks+10), + randRequestBlockNumber+uint64(*configCopy.VRFv2Plus.General.BHSJobWaitBlocks)+10, //nolint:gosec // G115 false positive sethClient, &wg, nil, @@ -1497,7 +1501,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { - randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting blockhash for a blocknumber which was stored in BHS contract") }, "2m", "1s").Should(gomega.Succeed()) l.Info(). @@ -1642,7 +1646,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { } require.True(t, batchBHSTxFound) - randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) + randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) require.NoError(t, err, "error getting blockhash for a blocknumber which was stored in BHS contract") l.Info(). @@ -2148,6 +2152,9 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + if randRequestCount > math.MaxUint16 { + t.Fatalf("rand request count overflows uint16: %d", randRequestCount) + } configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert @@ -2262,6 +2269,9 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + if randRequestCount > math.MaxUint16 { + t.Fatalf("rand request count overflows uint16: %d", randRequestCount) + } configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert diff --git a/integration-tests/testconfig/ccip/config.go b/integration-tests/testconfig/ccip/config.go index 3ef746e29e3..6c1bfcbe560 100644 --- a/integration-tests/testconfig/ccip/config.go +++ b/integration-tests/testconfig/ccip/config.go @@ -2,6 +2,7 @@ package ccip import ( "fmt" + "math" "strconv" "github.com/AlekSi/pointer" @@ -184,8 +185,12 @@ func IsSelectorValid(selector uint64, evmNetworks []blockchain.EVMNetwork) (bool if err != nil { return false, err } + if chainId >= math.MaxInt64 { + return false, fmt.Errorf("chain id overflows int64: %d", chainId) + } + id := int64(chainId) for _, net := range evmNetworks { - if net.ChainID == int64(chainId) { + if net.ChainID == id { return true, nil } } diff --git a/integration-tests/testconfig/testconfig_utils.go b/integration-tests/testconfig/testconfig_utils.go index e7b38ea3e4e..8d41ed55be9 100644 --- a/integration-tests/testconfig/testconfig_utils.go +++ b/integration-tests/testconfig/testconfig_utils.go @@ -1,6 +1,7 @@ package testconfig import ( + "errors" "fmt" "os" "strings" @@ -18,12 +19,12 @@ Chainlink version must be set in toml config. ` if os.Getenv("E2E_TEST_CHAINLINK_IMAGE") == "" || os.Getenv("E2E_TEST_CHAINLINK_UPGRADE_IMAGE") == "" { - return fmt.Errorf(fmt.Sprintf("%s\n%s", errStr, missingImage)) + return fmt.Errorf("%s\n%s", errStr, missingImage) } if os.Getenv("CHAINLINK_VERSION") == "" || os.Getenv("CHAINLINK_UPGRADE_VERSION") == "" { - return fmt.Errorf(fmt.Sprintf("%s\n%s", errStr, missingVersion)) + return fmt.Errorf("%s\n%s", errStr, missingVersion) } - return fmt.Errorf(errStr) + return errors.New(errStr) } // NoSelectedNetworkInfoAsError return a helfpul error message when the no selected network info is found in TOML config. @@ -34,8 +35,6 @@ You might have used old configuration approach. If so, use TOML instead of env v Please refer to integration-tests/testconfig/README.md for more information. ` - finalErrStr := fmt.Sprintf("%s\n%s", errStr, intro) - if net := os.Getenv("SELECTED_NETWORKS"); net != "" { parts := strings.Split(net, ",") selectedNetworkStr := "[" @@ -52,10 +51,10 @@ Please refer to integration-tests/testconfig/README.md for more information. Or if you want to run your tests right now add following content to integration-tests/testconfig/overrides.toml: [Network] selected_networks=` - finalErrStr = fmt.Sprintf("%s\n%s%s%s", errStr, intro, extraInfo, selectedNetworkStr) + return fmt.Errorf("%s\n%s%s%s", errStr, intro, extraInfo, selectedNetworkStr) } - return fmt.Errorf(finalErrStr) + return fmt.Errorf("%s\n%s", errStr, intro) } func GetChainAndTestTypeSpecificConfig(testType string, product Product) (TestConfig, error) { diff --git a/integration-tests/testreporters/keeper.go b/integration-tests/testreporters/keeper.go index dfafda06e86..bfa9585b8bc 100644 --- a/integration-tests/testreporters/keeper.go +++ b/integration-tests/testreporters/keeper.go @@ -4,7 +4,6 @@ import ( "encoding/csv" "encoding/json" "fmt" - "math" "os" "path/filepath" "sync" @@ -65,7 +64,7 @@ func (k *KeeperBlockTimeTestReporter) WriteReport(folderLocation string) error { } var totalExpected, totalSuccessful, totalMissed, worstMiss int64 for contractIndex, report := range k.Reports { - avg, max := int64AvgMax(report.AllMissedUpkeeps) + avg, maxVal := int64AvgMax(report.AllMissedUpkeeps) err = keeperReportWriter.Write([]string{ fmt.Sprint(contractIndex), report.ContractAddress, @@ -73,13 +72,13 @@ func (k *KeeperBlockTimeTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(report.TotalSuccessfulUpkeeps), fmt.Sprint(len(report.AllMissedUpkeeps)), fmt.Sprint(avg), - fmt.Sprint(max), + fmt.Sprint(maxVal), fmt.Sprintf("%.2f%%", (float64(report.TotalSuccessfulUpkeeps)/float64(report.TotalExpectedUpkeeps))*100), }) totalExpected += report.TotalExpectedUpkeeps totalSuccessful += report.TotalSuccessfulUpkeeps totalMissed += int64(len(report.AllMissedUpkeeps)) - worstMiss = int64(math.Max(float64(max), float64(worstMiss))) + worstMiss = max(maxVal, worstMiss) if err != nil { return err } @@ -160,13 +159,13 @@ func (k *KeeperBlockTimeTestReporter) SendSlackNotification(t *testing.T, slackC // int64AvgMax helper calculates the avg and the max values in a list func int64AvgMax(in []int64) (float64, int64) { var sum int64 - var max int64 + var val int64 // max if len(in) == 0 { return 0, 0 } for _, num := range in { sum += num - max = int64(math.Max(float64(max), float64(num))) + val = max(val, num) } - return float64(sum) / float64(len(in)), max + return float64(sum) / float64(len(in)), val } diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go index 00a31a12411..81a792002d9 100644 --- a/integration-tests/testreporters/keeper_benchmark.go +++ b/integration-tests/testreporters/keeper_benchmark.go @@ -129,7 +129,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { if err != nil { return err } - avg, median, ninetyPct, ninetyNinePct, max := IntListStats(allDelays) + avg, median, ninetyPct, ninetyNinePct, maxVal := IntListStats(allDelays) err = keeperReportWriter.Write([]string{ fmt.Sprint(totalEligibleCount), fmt.Sprint(totalPerformed), @@ -139,7 +139,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(median), fmt.Sprint(ninetyPct), fmt.Sprint(ninetyNinePct), - fmt.Sprint(max), + fmt.Sprint(maxVal), fmt.Sprintf("%.2f%%", pctWithinSLA), fmt.Sprintf("%.2f%%", pctReverted), fmt.Sprintf("%.2f%%", pctStale), @@ -156,7 +156,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { Int64("Median Perform Delay", median). Int64("90th pct Perform Delay", ninetyPct). Int64("99th pct Perform Delay", ninetyNinePct). - Int64("Max Perform Delay", max). + Int64("Max Perform Delay", maxVal). Float64("Percent Within SLA", pctWithinSLA). Float64("Percent Reverted", pctReverted). Msg("Calculated Aggregate Results") @@ -179,7 +179,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { } for contractIndex, report := range k.Reports { - avg, median, ninetyPct, ninetyNinePct, max = IntListStats(report.AllCheckDelays) + avg, median, ninetyPct, ninetyNinePct, maxVal = IntListStats(report.AllCheckDelays) err = keeperReportWriter.Write([]string{ fmt.Sprint(contractIndex), report.RegistryAddress, @@ -190,7 +190,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(median), fmt.Sprint(ninetyPct), fmt.Sprint(ninetyNinePct), - fmt.Sprint(max), + fmt.Sprint(maxVal), fmt.Sprintf("%.2f%%", (1.0-float64(report.TotalSLAMissedUpkeeps)/float64(report.TotalEligibleCount))*100), }) if err != nil { @@ -215,7 +215,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { "median": median, "90p": ninetyPct, "99p": ninetyNinePct, - "max": max, + "max": maxVal, } k.Summary.Metrics.PercentWithinSLA = pctWithinSLA k.Summary.Metrics.PercentRevert = pctReverted diff --git a/integration-tests/testsetups/automation_benchmark.go b/integration-tests/testsetups/automation_benchmark.go index 18e13816f5a..d6f5615965c 100644 --- a/integration-tests/testsetups/automation_benchmark.go +++ b/integration-tests/testsetups/automation_benchmark.go @@ -303,11 +303,15 @@ func (k *KeeperBenchmarkTest) Run() { startedObservations.Add(1) k.log.Info().Int("Channel index", chIndex).Str("UpkeepID", upkeepIDCopy.String()).Msg("Starting upkeep observation") + upKeepSLA := inputs.Upkeeps.BlockRange + inputs.UpkeepSLA + if upKeepSLA < 0 { + k.t.Fatalf("negative upkeep SLA: %d", upKeepSLA) + } confirmer := contracts.NewAutomationConsumerBenchmarkUpkeepObserver( k.keeperConsumerContracts[registryIndex], k.keeperRegistries[registryIndex], upkeepIDCopy, - inputs.Upkeeps.BlockRange+inputs.UpkeepSLA, + uint64(upKeepSLA), inputs.UpkeepSLA, &k.TestReporter, upkeepIndex, @@ -723,6 +727,9 @@ func (k *KeeperBenchmarkTest) SetupBenchmarkKeeperContracts(index int, a *automa err = actions.SetupMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds, a.TestConfig) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") + if upkeep.UpkeepGasLimit < 0 || upkeep.UpkeepGasLimit > math.MaxUint32 { + k.t.Fatalf("upkeep gas limit overflows uint32: %d", upkeep.UpkeepGasLimit) + } upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), a.Registry, a.Registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false, false, nil) k.automationTests[index] = *a diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 52a5594564b..0c127d576c0 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "math" "math/big" "math/rand" "sort" @@ -441,7 +442,15 @@ func (m *MissingLogs) IsEmpty() bool { } // GetMissingLogs returns a map of CL node name to missing logs in that node compared to EVM node to which the provided evm client is connected -func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, client *seth.Client, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *lp_config.Config) (MissingLogs, error) { +func GetMissingLogs( + startBlock, endBlock int64, + logEmitters []*contracts.LogEmitter, + client *seth.Client, + clnodeCluster *test_env.ClCluster, + l zerolog.Logger, + coreLogger core_logger.SugaredLogger, + cfg *lp_config.Config, +) (MissingLogs, error) { wg := &sync.WaitGroup{} type dbQueryResult struct { @@ -564,6 +573,12 @@ func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmit missingLogs := make([]geth_types.Log, 0) for i, evmLog := range allLogsInEVMNode { logFound := false + if evmLog.BlockNumber > math.MaxInt64 { + panic(fmt.Errorf("block number overflows int64: %d", evmLog.BlockNumber)) + } + if evmLog.Index > math.MaxInt64 { + panic(fmt.Errorf("index overflows int64: %d", evmLog.Index)) + } for _, logPollerLog := range allLogPollerLogs[nodeName] { if logPollerLog.BlockNumber == int64(evmLog.BlockNumber) && logPollerLog.TxHash == evmLog.TxHash && bytes.Equal(logPollerLog.Data, evmLog.Data) && logPollerLog.LogIndex == int64(evmLog.Index) && logPollerLog.Address == evmLog.Address && logPollerLog.BlockHash == evmLog.BlockHash && bytes.Equal(logPollerLog.Topics[0][:], evmLog.Topics[0].Bytes()) { @@ -982,6 +997,9 @@ func GetEndBlockToWaitFor(endBlock int64, network blockchain.EVMNetwork, cfg *lp return endBlock + 1, nil } + if network.FinalityDepth > math.MaxInt64 { + return -1, fmt.Errorf("finality depth overflows int64: %d", network.FinalityDepth) + } return endBlock + int64(network.FinalityDepth), nil } diff --git a/plugins/chainlink.Dockerfile b/plugins/chainlink.Dockerfile index 6d42567c745..a17f5df3898 100644 --- a/plugins/chainlink.Dockerfile +++ b/plugins/chainlink.Dockerfile @@ -1,5 +1,5 @@ # Build image: Chainlink binary -FROM golang:1.22-bullseye as buildgo +FROM golang:1.23-bullseye as buildgo RUN go version WORKDIR /chainlink @@ -33,7 +33,7 @@ RUN mkdir /chainlink-starknet RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer | xargs -I % ln -s % /chainlink-starknet/relayer # Build image: Plugins -FROM golang:1.22-bullseye as buildplugins +FROM golang:1.23-bullseye as buildplugins RUN go version WORKDIR /chainlink-feeds