Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/scripts/cre/environment/configs/workflow-don.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
docker_file = "core/chainlink.Dockerfile"
docker_build_args = { "CL_IS_PROD_BUILD" = "false" }
#image = "chainlink-tmp:latest"
custom_ports = ["45000:45000"]
user_config_overrides = """
[Log]
Level = 'debug'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.24.5
toolchain go1.25.3

require (
github.com/google/uuid v1.6.0
github.com/smartcontractkit/cre-sdk-go v0.5.1-0.20250818141131-0b979c98bab0
github.com/smartcontractkit/cre-sdk-go/capabilities/scheduler/cron v0.5.1-0.20250818141131-0b979c98bab0
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
Expand Down
160 changes: 145 additions & 15 deletions core/scripts/cre/environment/examples/workflows/v2/node-mode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ package main

import (
"errors"
"fmt"
"log/slog"
"math/rand"
"strings"

"github.com/google/uuid"

"github.com/smartcontractkit/cre-sdk-go/capabilities/scheduler/cron"
"github.com/smartcontractkit/cre-sdk-go/cre"
Expand Down Expand Up @@ -33,34 +37,160 @@ func RunSimpleCronWorkflow(_ None, _ *slog.Logger, _ cre.SecretsProvider) (cre.W
func onTrigger(cfg None, runtime cre.Runtime, _ *cron.Payload) (string, error) {
runtime.Logger().Info("Triggered fetch of value")

defaultStringPromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) ([]byte, error) {
return nil, nil
}, cre.ConsensusIdenticalAggregation[[]byte]().WithDefault([]byte("stuff")))
resultBytes, err := defaultStringPromise.Await()
err := testIdenticalConsensus(cfg, runtime)
if err != nil {
runtime.Logger().Warn("Consensus error on default string", "error", err)
return "", err
return "testIdenticalConsensus failed", err
}

runtime.Logger().Info("Result bytes are here", "result", resultBytes)
err = testIdenticalConsensusFailure(cfg, runtime)
if err != nil {
return "testIdenticalConsensusFailure failed", err
}

if string(resultBytes) == "stuff" {
runtime.Logger().Info("Successfully reached identical consensus on default value", "result", resultBytes)
} else {
return "failed", errors.New("Failed to reach consensus on default value")
err = testIdenticalConsensusFailureWithDefault(cfg, runtime)
if err != nil {
return "testIdenticalConsensusFailureWithDefault failed", err
}

err = testMedianConsensus(cfg, runtime)
if err != nil {
return "testMedianConsensus failed", err
}

err = testMedianConsensusWithErrors(cfg, runtime)
if err != nil {
return "testMedianConsensusWithErrors failed", err
}

err = testMedianConsensusWithErrorsAndDefault(cfg, runtime)
if err != nil {
return "testMedianConsensusWithErrors failed", err
}

err = testConsensusCommonPrefixAggregation(cfg, runtime)
if err != nil {
return "testConsensusCommonPrefixAggregation failed", err
}

runtime.Logger().Info("Successfully passed all consensus tests")

return "success", nil
}

func testMedianConsensus(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testMedianConsensus")
mathPromise := cre.RunInNodeMode(cfg, runtime, fetchData, cre.ConsensusMedianAggregation[int]())
offchainValue, err := mathPromise.Await()
if err != nil {
runtime.Logger().Warn("Consensus error", "error", err)
return "", err
runtime.Logger().Warn("Median consensus error", "error", err)
return err
}
runtime.Logger().Info("Successfully fetched offchain value and reached consensus", "result", offchainValue)
return nil
}

runtime.Logger().Info("Successfully passed all consensus tests")
func testMedianConsensusWithErrors(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testMedianConsensusWithErrors")
mathPromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) (int, error) {
return 0, errors.New("simulated error")
}, cre.ConsensusMedianAggregation[int]())
offchainValue, err := mathPromise.Await()
if err == nil {
runtime.Logger().Warn("expected median consensus error", "error", err)
return err
} else {
expectedInMessage := "simulated error"
if !strings.Contains(err.Error(), expectedInMessage) {
runtime.Logger().Warn("expected median consensus error", "error", err)
return fmt.Errorf("expected error to contain '%s', got '%s'", expectedInMessage, err.Error())
}
}

return "success", nil
runtime.Logger().Info("Successfully tested consensus errors", "result", offchainValue)
return nil
}

func testMedianConsensusWithErrorsAndDefault(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testMedianConsensusWithErrorsAndDefault")
mathPromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) (int, error) {
return 0, errors.New("simulated error")
}, cre.ConsensusMedianAggregation[int]().WithDefault(42))
offchainValue, err := mathPromise.Await()
if err != nil {
runtime.Logger().Warn("Median consensus with errors and default error error", "error", err)
return err
}
runtime.Logger().Info("Successfully used default when errors", "result", offchainValue)
return nil
}

func testIdenticalConsensus(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testIdenticalConsensus")
sameValueStr := "samevalue"
byteSlicePromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) ([]byte, error) {
return []byte(sameValueStr), nil
}, cre.ConsensusIdenticalAggregation[[]byte]())
resultBytes, err := byteSlicePromise.Await()
if err != nil {
runtime.Logger().Warn("Consensus error on identical consensus test", "error", err)
return err
}

if string(resultBytes) == sameValueStr {
runtime.Logger().Info("Identical consensus on a []byte succeeded", "result", resultBytes)
} else {
msg := fmt.Sprintf("Identical consensus on a []byte failed, expected '%s', got '%s'", sameValueStr, resultBytes)
runtime.Logger().Error(msg)
return errors.New(msg)
}

return nil
}

// testIdenticalConsensus tests identical consensus on a []byte value that is different on each node.
func testIdenticalConsensusFailure(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testIdenticalConsensusFailure")
sameValueStr := uuid.New().String()
byteSlicePromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) ([]byte, error) {
return []byte(sameValueStr), nil
}, cre.ConsensusIdenticalAggregation[[]byte]())
resultBytes, err := byteSlicePromise.Await()
if err == nil {
runtime.Logger().Warn("Expected consensus to fail but it succeeded", "result", resultBytes)
return errors.New("Expected consensus to fail but it succeeded")
}

errString := err.Error()
if !strings.Contains(errString, "no values met f+1 threshold") {
runtime.Logger().Warn("Unexpected error message", "error", errString)
return fmt.Errorf("unexpected error message: %s", errString)
}

return nil
}

func testIdenticalConsensusFailureWithDefault(cfg None, runtime cre.Runtime) error {
runtime.Logger().Info("Starting testIdenticalConsensusFailureWithDefault")
sameValueStr := uuid.New().String()
defaultStr := "adefault"
byteSlicePromise := cre.RunInNodeMode(cfg, runtime, func(config None, nodeRuntime cre.NodeRuntime) ([]byte, error) {
return []byte(sameValueStr), nil
}, cre.ConsensusIdenticalAggregation[[]byte]().WithDefault([]byte(defaultStr)))
resultBytes, err := byteSlicePromise.Await()
if err != nil {
runtime.Logger().Warn("Consensus error on identical consensus failoure with default test", "error", err)
return err
}

if string(resultBytes) == defaultStr {
runtime.Logger().Info("Identical consensus on a []byte with default succeeded", "result", resultBytes)
} else {
msg := fmt.Sprintf("Identical consensus on a []byte with default failed, expected '%s', got '%s'", defaultStr, resultBytes)
runtime.Logger().Error(msg)
return errors.New(msg)
}

return nil
}

func fetchData(cfg None, nodeRuntime cre.NodeRuntime) (int, error) {
Expand Down
56 changes: 27 additions & 29 deletions system-tests/tests/smoke/cre/cre_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (

"github.com/stretchr/testify/require"

"github.com/smartcontractkit/quarantine"

"github.com/smartcontractkit/chainlink/system-tests/lib/cre/environment/blockchains"
t_helpers "github.com/smartcontractkit/chainlink/system-tests/tests/test-helpers"
)
Expand Down Expand Up @@ -96,43 +94,43 @@ To execute tests with v2 contracts start the local CRE first:
2. Execute the tests in `system-tests/tests/smoke/cre`: `go test -timeout 15m -run "^Test_CRE_V2"`.
*/
func Test_CRE_V2_Suite(t *testing.T) {
quarantine.Flaky(t, "DX-2122")
// quarantine.Flaky(t, "DX-2122")
topology := os.Getenv("TOPOLOGY_NAME")
t.Run("[v2] Proof Of Reserve - "+topology, func(t *testing.T) {
// TODO: Review why this test cannot run with two chains? (CRE-983)
// How to configure evm for both chains and capabilities DON (DON<>DON topology)?
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)
/* t.Run("[v2] Proof Of Reserve - "+topology, func(t *testing.T) {
// TODO: Review why this test cannot run with two chains? (CRE-983)
// How to configure evm for both chains and capabilities DON (DON<>DON topology)?
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

// TODO: remove this when OCR works properly with multiple chains in Local CRE
testEnv.CreEnvironment.Blockchains = []blockchains.Blockchain{testEnv.CreEnvironment.Blockchains[0]}
priceProvider, wfConfig := beforePoRTest(t, testEnv, "por-workflow-v2", PoRWFV2Location)
wfConfig.FeedIDs = []string{wfConfig.FeedIDs[0]}
ExecutePoRTest(t, testEnv, priceProvider, wfConfig, false)
})
// TODO: remove this when OCR works properly with multiple chains in Local CRE
testEnv.CreEnvironment.Blockchains = []blockchains.Blockchain{testEnv.CreEnvironment.Blockchains[0]}
priceProvider, wfConfig := beforePoRTest(t, testEnv, "por-workflow-v2", PoRWFV2Location)
wfConfig.FeedIDs = []string{wfConfig.FeedIDs[0]}
ExecutePoRTest(t, testEnv, priceProvider, wfConfig, false)
})

t.Run("[v2] Vault DON - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)
t.Run("[v2] Vault DON - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

ExecuteVaultTest(t, testEnv)
})
ExecuteVaultTest(t, testEnv)
})

t.Run("[v2] Cron Beholder - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)
t.Run("[v2] Cron Beholder - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

ExecuteCronBeholderTest(t, testEnv)
})
ExecuteCronBeholderTest(t, testEnv)
})

t.Run("[v2] HTTP Trigger Action - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)
t.Run("[v2] HTTP Trigger Action - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

ExecuteHTTPTriggerActionTest(t, testEnv)
})
ExecuteHTTPTriggerActionTest(t, testEnv)
})

t.Run("[v2] DON Time - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)
t.Run("[v2] DON Time - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

ExecuteDonTimeTest(t, testEnv)
})
ExecuteDonTimeTest(t, testEnv)
}) */
t.Run("[v2] Consensus - "+topology, func(t *testing.T) {
testEnv := t_helpers.SetupTestEnvironmentWithConfig(t, t_helpers.GetDefaultTestConfig(t), v2RegistriesFlags...)

Expand Down