Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
9c4741b
cre-1601: shard orchestrator plugin for delegate
mchain0 Dec 22, 2025
de0d9f0
cre-1601: consistent hashing and plugin test
mchain0 Dec 22, 2025
045f5ec
cre-1601: tidy
mchain0 Dec 22, 2025
6ae609e
cre-1601: pb generate
mchain0 Dec 22, 2025
adaf093
cre-1601: review improvement
mchain0 Dec 23, 2025
93a8734
cre-1601: review improvement
mchain0 Dec 23, 2025
38db9f4
cre-1601: review improvement
mchain0 Dec 23, 2025
e3e2e02
cre-1601: remove previous outcome, use outctx.SeqNr instead
mchain0 Dec 23, 2025
4b0684f
cre-1601: transition state machine
mchain0 Dec 23, 2025
36252b0
cre-1601: removed TransmissionScheduleOverride
mchain0 Dec 23, 2025
0553e74
cre-1601: comments
mchain0 Dec 23, 2025
cec9228
cre-1601: rename plugin to ring
mchain0 Dec 23, 2025
6d1b057
cre-1601: renames and cleanup
mchain0 Dec 23, 2025
d848886
cre-1601: delegate integrations adjustments
mchain0 Dec 23, 2025
65f2e1d
cre-1601: proto comments; import fix
mchain0 Dec 29, 2025
a0601eb
cre-1601: snake_case consistent for proto fields
mchain0 Dec 29, 2025
b9e70a7
cre-1601: remove unused field
mchain0 Dec 29, 2025
790bc5d
cre-1601: more proto comments
mchain0 Dec 29, 2025
7be5eb2
cre-1601: proto cleanup, orphans removed
mchain0 Dec 29, 2025
ffe484b
cre-1601: log overrides, log plugin config
mchain0 Dec 29, 2025
26f8c8c
cre-1601: better comment
mchain0 Dec 29, 2025
cf0bb98
cre-1601: deterministic time; f check for round; improved time median…
mchain0 Dec 29, 2025
2f2e45d
cre-1601: log improvement
mchain0 Dec 29, 2025
d7db767
cre-1601: shard count health refactor
mchain0 Dec 29, 2025
effb57a
cre-1601: hash ring pure function refactor for both storage and obser…
mchain0 Dec 29, 2025
18161c1
cre-1601: Transmitter notifies Arbiter
mchain0 Dec 29, 2025
f455bc0
cre-1601: store in two states, steady and transition; enque for alloc…
mchain0 Dec 29, 2025
9198b9c
cre-1601: comments improved
mchain0 Dec 29, 2025
457af17
cre-1601: more comments improvements
mchain0 Dec 29, 2025
9599327
cre-1601: test extension to validate workflows to shards eassignments
mchain0 Dec 29, 2025
1c53fef
cre-1601: test improvement - distribution check by percents
mchain0 Dec 29, 2025
15465d1
cre-1601: using maps improvement
mchain0 Dec 29, 2025
5022467
cre-1601: remove number of shards limits (ref. review)
mchain0 Dec 29, 2025
287bf71
cre-1601: initial state fix; intial transition state until OCR round;…
mchain0 Dec 30, 2025
c8cd5fe
Merge branch 'main' into cre-1601-shard-orchestrator-plugin
mchain0 Dec 30, 2025
df7e4e4
cre-1601: more tests; boosting test coverage
mchain0 Dec 30, 2025
600d035
cre-1601: better comments
mchain0 Dec 30, 2025
0bd0aaf
cre-1601: better comments
mchain0 Dec 30, 2025
a1e8307
cre-1601: improved test for plugin outcome
mchain0 Dec 30, 2025
1e3f43b
cre-1601: comments improved
mchain0 Dec 30, 2025
57f0423
cre-1601: comment improvement
mchain0 Dec 30, 2025
e042bb2
cre-1601: more tests; more coverage
mchain0 Dec 30, 2025
26cbc3b
cre-1601: refactor of state; state verification tests; related changes;
mchain0 Dec 30, 2025
29b4072
cre-1601: bool wrapper ShardStatus to extend with weights later
mchain0 Dec 30, 2025
693eb34
cre-1601: ArbiterScaler.Status() wantShards being part of the observa…
mchain0 Dec 30, 2025
3198932
cre-1601: improved comments; improved naming; simplified logic; obser…
mchain0 Dec 31, 2025
16f7555
cre-1601: on 1st round make prior outcome wantShards equal to the cur…
mchain0 Dec 31, 2025
dbc586d
cre-1601: removed unnecessary check (code review suggestions)
mchain0 Dec 31, 2025
5b1c2a1
Merge branch 'main' into cre-1601-shard-orchestrator-plugin
mchain0 Dec 31, 2025
eaec50d
Fail Observation() on Arbiter error
bolekk Jan 2, 2026
c6c46c9
Merge branch 'main' into cre-1601-shard-orchestrator-plugin
mchain0 Jan 5, 2026
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
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ require (
github.com/XSAM/otelsql v0.37.0
github.com/andybalholm/brotli v1.1.1
github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c
github.com/buraksezer/consistent v0.10.0
github.com/bytecodealliance/wasmtime-go/v28 v28.0.0
github.com/cespare/xxhash/v2 v2.3.0
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/dominikbraun/graph v0.23.0
github.com/fxamacker/cbor/v2 v2.7.0
Expand Down Expand Up @@ -88,7 +90,6 @@ require (
github.com/buger/goterm v1.0.4 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 // indirect
github.com/cloudevents/sdk-go/v2 v2.16.1 // indirect
github.com/fatih/color v1.18.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/buraksezer/consistent v0.10.0 h1:hqBgz1PvNLC5rkWcEBVAL9dFMBWz6I0VgUCW25rrZlU=
github.com/buraksezer/consistent v0.10.0/go.mod h1:6BrVajWq7wbKZlTOUPs/XVfR8c0maujuPowduSpZqmw=
github.com/bytecodealliance/wasmtime-go/v28 v28.0.0 h1:aBU8cexP2rPZ0Qz488kvn2NXvWZHL2aG1/+n7Iv+xGc=
github.com/bytecodealliance/wasmtime-go/v28 v28.0.0/go.mod h1:4OCU0xAW9ycwtX4nMF4zxwgJBJ5/0eMfJiHB0wAmkV4=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
Expand Down
1 change: 1 addition & 0 deletions pkg/types/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
OCR3Capability OCR2PluginType = "ocr3-capability"
VaultPlugin OCR2PluginType = "vault-plugin"
DonTimePlugin OCR2PluginType = "dontime"
RingPlugin OCR2PluginType = "ring"
SecureMint OCR2PluginType = "securemint"

CCIPCommit OCR2PluginType = "ccip-commit"
Expand Down
79 changes: 79 additions & 0 deletions pkg/workflows/ring/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ring

import (
"context"
"errors"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/services"
"github.com/smartcontractkit/chainlink-common/pkg/types/core"
"github.com/smartcontractkit/chainlink-common/pkg/workflows/ring/pb"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
)

const (
defaultMaxPhaseOutputBytes = 1000000 // 1 MB
defaultMaxReportCount = 1
defaultBatchSize = 100
)

var _ core.OCR3ReportingPluginFactory = &Factory{}

type Factory struct {
store *Store
arbiterScaler pb.ArbiterScalerClient
config *ConsensusConfig
lggr logger.Logger

services.StateMachine
}

func NewFactory(s *Store, arbiterScaler pb.ArbiterScalerClient, lggr logger.Logger, cfg *ConsensusConfig) (*Factory, error) {
if arbiterScaler == nil {
return nil, errors.New("arbiterScaler is required")
}
if cfg == nil {
cfg = &ConsensusConfig{
BatchSize: defaultBatchSize,
}
}
return &Factory{
store: s,
arbiterScaler: arbiterScaler,
config: cfg,
lggr: logger.Named(lggr, "RingPluginFactory"),
}, nil
}

func (o *Factory) NewReportingPlugin(_ context.Context, config ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[[]byte], ocr3types.ReportingPluginInfo, error) {
plugin, err := NewPlugin(o.store, o.arbiterScaler, config, o.lggr, o.config)
pluginInfo := ocr3types.ReportingPluginInfo{
Name: "RingPlugin",
Limits: ocr3types.ReportingPluginLimits{
MaxQueryLength: defaultMaxPhaseOutputBytes,
MaxObservationLength: defaultMaxPhaseOutputBytes,
MaxOutcomeLength: defaultMaxPhaseOutputBytes,
MaxReportLength: defaultMaxPhaseOutputBytes,
MaxReportCount: defaultMaxReportCount,
},
}
return plugin, pluginInfo, err
}

func (o *Factory) Start(ctx context.Context) error {
return o.StartOnce("RingPlugin", func() error {
return nil
})
}

func (o *Factory) Close() error {
return o.StopOnce("RingPlugin", func() error {
return nil
})
}

func (o *Factory) Name() string { return o.lggr.Name() }

func (o *Factory) HealthReport() map[string]error {
return map[string]error{o.Name(): o.Healthy()}
}
70 changes: 70 additions & 0 deletions pkg/workflows/ring/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ring

import (
"context"
"testing"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
"github.com/stretchr/testify/require"
)

func TestFactory_NewFactory(t *testing.T) {
lggr := logger.Test(t)
store := NewStore()
arbiter := &mockArbiter{}

t.Run("with_nil_config", func(t *testing.T) {
f, err := NewFactory(store, arbiter, lggr, nil)
require.NoError(t, err)
require.NotNil(t, f)
})

t.Run("with_custom_config", func(t *testing.T) {
cfg := &ConsensusConfig{BatchSize: 50}
f, err := NewFactory(store, arbiter, lggr, cfg)
require.NoError(t, err)
require.NotNil(t, f)
})

t.Run("nil_arbiter_returns_error", func(t *testing.T) {
_, err := NewFactory(store, nil, lggr, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "arbiterScaler is required")
})
}
Comment thread
mchain0 marked this conversation as resolved.

func TestFactory_NewReportingPlugin(t *testing.T) {
lggr := logger.Test(t)
store := NewStore()
f, err := NewFactory(store, &mockArbiter{}, lggr, nil)
require.NoError(t, err)

config := ocr3types.ReportingPluginConfig{N: 4, F: 1}
plugin, info, err := f.NewReportingPlugin(context.Background(), config)
require.NoError(t, err)
require.NotNil(t, plugin)
require.NotEmpty(t, info.Name)
require.Equal(t, "RingPlugin", info.Name)
require.Equal(t, defaultMaxReportCount, info.Limits.MaxReportCount)
}

func TestFactory_Lifecycle(t *testing.T) {
lggr := logger.Test(t)
store := NewStore()
f, err := NewFactory(store, &mockArbiter{}, lggr, nil)
require.NoError(t, err)

err = f.Start(context.Background())
require.NoError(t, err)

name := f.Name()
require.NotEmpty(t, name)

report := f.HealthReport()
require.NotNil(t, report)
require.Contains(t, report, name)

err = f.Close()
require.NoError(t, err)
}
Loading
Loading