Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiNode Integration: TOML Configurations #844

Open
wants to merge 39 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
60673aa
MultiNode integration setup
DylanTinianov Aug 20, 2024
dc85772
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Aug 27, 2024
e6683e6
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Sep 3, 2024
1c68485
Update MultiNode files
DylanTinianov Sep 3, 2024
c44a6ce
Add MultiNode flag
DylanTinianov Sep 3, 2024
64db86a
Remove internal dependency
DylanTinianov Sep 3, 2024
f7c1bc9
Fix build
DylanTinianov Sep 3, 2024
9e91b47
Fix import cycle
DylanTinianov Sep 4, 2024
354dc50
tidy
DylanTinianov Sep 4, 2024
60c3352
Update client_test.go
DylanTinianov Sep 4, 2024
dcec343
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Sep 4, 2024
8e2306b
lint
DylanTinianov Sep 4, 2024
b8d6755
Fix duplicate metrics
DylanTinianov Sep 4, 2024
2cb4d77
Add chain multinode flag
DylanTinianov Sep 5, 2024
0b33b1f
Extend client
DylanTinianov Sep 6, 2024
95e1c9a
Add defaults
DylanTinianov Sep 6, 2024
6641bc9
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Sep 6, 2024
d8d312c
Address comments
DylanTinianov Sep 10, 2024
aa3c068
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Sep 10, 2024
3c3756e
lint
DylanTinianov Sep 12, 2024
7c8b55d
Merge branch 'develop' into BCI-2835-integrate-multinode
DylanTinianov Sep 12, 2024
2521670
Fix lint overflow issues
DylanTinianov Sep 12, 2024
5b5cfd6
Update transaction_sender.go
DylanTinianov Sep 12, 2024
690f812
Fix lint
DylanTinianov Sep 12, 2024
fd3823b
Validate node config
DylanTinianov Sep 12, 2024
4bf96b7
Update toml.go
DylanTinianov Sep 12, 2024
c1b83a5
Add SendOnly nodes
DylanTinianov Sep 18, 2024
c58dbc8
Merge branch 'BCI-2835-integrate-multinode' into BCFR-302-multinode-toml
DylanTinianov Sep 18, 2024
e0231b0
Use pointers on config
DylanTinianov Sep 18, 2024
0122a5f
Fix conflicts
DylanTinianov Sep 18, 2024
8aa39f6
Use test context
DylanTinianov Sep 19, 2024
0e5a35e
Merge branch 'BCI-2835-integrate-multinode' into BCFR-302-multinode-toml
DylanTinianov Sep 19, 2024
b5ff16d
Use configured selection mode
DylanTinianov Sep 19, 2024
1b3a101
Set defaults
DylanTinianov Sep 24, 2024
b7cc350
Merge branch 'develop' into BCFR-302-multinode-toml
DylanTinianov Sep 24, 2024
0afd8da
lint
DylanTinianov Sep 24, 2024
b99b90c
Add nil check
DylanTinianov Sep 24, 2024
d7203f8
Merge branch 'develop' into BCFR-302-multinode-toml
DylanTinianov Sep 27, 2024
98b0e9d
Update multinode.go
DylanTinianov Sep 27, 2024
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
12 changes: 6 additions & 6 deletions pkg/solana/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ func newChain(id string, cfg *config.TOMLConfig, ks loop.Keystore, lggr logger.L
clientCache: map[string]*verifiedCachedClient{},
}

if cfg.MultiNodeEnabled() {
if cfg.MultiNode.MultiNodeEnabled() {
chainFamily := "solana"

mnCfg := cfg.MultiNodeConfig()
Expand Down Expand Up @@ -258,8 +258,8 @@ func newChain(id string, cfg *config.TOMLConfig, ks loop.Keystore, lggr logger.L

multiNode := mn.NewMultiNode[mn.StringID, *client.Client](
lggr,
mn.NodeSelectionModeRoundRobin,
0,
mnCfg.SelectionMode(),
mnCfg.LeaseDuration(),
nodes,
sendOnlyNodes,
mn.StringID(id),
Expand Down Expand Up @@ -398,7 +398,7 @@ func (c *chain) ChainID() string {

// getClient returns a client, randomly selecting one from available and valid nodes
func (c *chain) getClient() (client.ReaderWriter, error) {
if c.cfg.MultiNodeEnabled() {
if c.cfg.MultiNode.MultiNodeEnabled() {
return c.multiNode.SelectRPC()
}

Expand Down Expand Up @@ -482,7 +482,7 @@ func (c *chain) Start(ctx context.Context) error {
c.lggr.Debug("Starting balance monitor")
var ms services.MultiStart
startAll := []services.StartClose{c.txm, c.balanceMonitor}
if c.cfg.MultiNodeEnabled() {
if c.cfg.MultiNode.MultiNodeEnabled() {
c.lggr.Debug("Starting multinode")
startAll = append(startAll, c.multiNode, c.txSender)
}
Expand All @@ -496,7 +496,7 @@ func (c *chain) Close() error {
c.lggr.Debug("Stopping txm")
c.lggr.Debug("Stopping balance monitor")
closeAll := []io.Closer{c.txm, c.balanceMonitor}
if c.cfg.MultiNodeEnabled() {
if c.cfg.MultiNode.MultiNodeEnabled() {
c.lggr.Debug("Stopping multinode")
closeAll = append(closeAll, c.multiNode, c.txSender)
}
Expand Down
158 changes: 116 additions & 42 deletions pkg/solana/config/multinode.go
Original file line number Diff line number Diff line change
@@ -1,87 +1,161 @@
package config

import "time"
import (
"time"

"github.com/smartcontractkit/chainlink-common/pkg/config"

client "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode"
)

type MultiNode struct {
// TODO: Determine current config overlap https://smartcontract-it.atlassian.net/browse/BCI-4065
// Feature flag
multiNodeEnabled bool
multiNodeEnabled *bool

// Node Configs
pollFailureThreshold uint32
pollInterval time.Duration
selectionMode string
syncThreshold uint32
nodeIsSyncingEnabled bool
finalizedBlockPollInterval time.Duration
enforceRepeatableRead bool
deathDeclarationDelay time.Duration
pollFailureThreshold *uint32
pollInterval *config.Duration
selectionMode *string
syncThreshold *uint32
nodeIsSyncingEnabled *bool
leaseDuration *config.Duration
finalizedBlockPollInterval *config.Duration
enforceRepeatableRead *bool
deathDeclarationDelay *config.Duration

// Chain Configs
nodeNoNewHeadsThreshold time.Duration
noNewFinalizedHeadsThreshold time.Duration
finalityDepth uint32
finalityTagEnabled bool
finalizedBlockOffset uint32
nodeNoNewHeadsThreshold *config.Duration
noNewFinalizedHeadsThreshold *config.Duration
finalityDepth *uint32
finalityTagEnabled *bool
finalizedBlockOffset *uint32
}

func (c *MultiNode) MultiNodeEnabled() bool {
return c.multiNodeEnabled
return c.multiNodeEnabled != nil && *c.multiNodeEnabled
}

func (c *MultiNode) PollFailureThreshold() uint32 {
return c.pollFailureThreshold
return *c.pollFailureThreshold
}

func (c *MultiNode) PollInterval() time.Duration {
return c.pollInterval
return c.pollInterval.Duration()
}

func (c *MultiNode) SelectionMode() string {
return c.selectionMode
return *c.selectionMode
}

func (c *MultiNode) SyncThreshold() uint32 {
return c.syncThreshold
return *c.syncThreshold
}

func (c *MultiNode) NodeIsSyncingEnabled() bool {
return c.nodeIsSyncingEnabled
return *c.nodeIsSyncingEnabled
}

func (c *MultiNode) LeaseDuration() time.Duration { return c.leaseDuration.Duration() }

func (c *MultiNode) FinalizedBlockPollInterval() time.Duration {
return c.finalizedBlockPollInterval
return c.finalizedBlockPollInterval.Duration()
}

func (c *MultiNode) EnforceRepeatableRead() bool {
return c.enforceRepeatableRead
}
func (c *MultiNode) EnforceRepeatableRead() bool { return *c.enforceRepeatableRead }

func (c *MultiNode) DeathDeclarationDelay() time.Duration {
return c.deathDeclarationDelay
}
func (c *MultiNode) DeathDeclarationDelay() time.Duration { return c.deathDeclarationDelay.Duration() }

func (c *MultiNode) NodeNoNewHeadsThreshold() time.Duration {
return c.nodeNoNewHeadsThreshold
return c.nodeNoNewHeadsThreshold.Duration()
}

func (c *MultiNode) NoNewFinalizedHeadsThreshold() time.Duration {
return c.noNewFinalizedHeadsThreshold
return c.noNewFinalizedHeadsThreshold.Duration()
}

func (c *MultiNode) FinalityDepth() uint32 {
return c.finalityDepth
}
func (c *MultiNode) FinalityDepth() uint32 { return *c.finalityDepth }

func (c *MultiNode) FinalityTagEnabled() bool {
return c.finalityTagEnabled
}
func (c *MultiNode) FinalityTagEnabled() bool { return *c.finalityTagEnabled }

func (c *MultiNode) FinalizedBlockOffset() uint32 {
return c.finalizedBlockOffset
}
func (c *MultiNode) FinalizedBlockOffset() uint32 { return *c.finalizedBlockOffset }

func (c *MultiNode) SetDefaults() {
// TODO: Set defaults for MultiNode config https://smartcontract-it.atlassian.net/browse/BCI-4065
c.multiNodeEnabled = false
// Default disabled
c.multiNodeEnabled = ptr(false)

// Node Configs
c.pollFailureThreshold = ptr(uint32(5))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default values here - where are they coming from? For example, the 5 for syncThreshold or the 10 for pollInterval. Could these come from another source or if they are to be hardcoded, could we provide some documentation as to why these are the best default values for these fields?

Copy link
Contributor Author

@DylanTinianov DylanTinianov Sep 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a meeting with Dmytro and Aaron where we discussed what default values make sense for each config. I can for sure add some comments though!

c.pollInterval = config.MustNewDuration(10 * time.Second)

c.selectionMode = ptr(client.NodeSelectionModePriorityLevel)

c.syncThreshold = ptr(uint32(5))

c.leaseDuration = config.MustNewDuration(time.Minute)

c.nodeIsSyncingEnabled = ptr(false)
c.finalizedBlockPollInterval = config.MustNewDuration(5 * time.Second)
c.enforceRepeatableRead = ptr(true)
c.deathDeclarationDelay = config.MustNewDuration(10 * time.Second)

// Chain Configs
c.nodeNoNewHeadsThreshold = config.MustNewDuration(10 * time.Second)
c.noNewFinalizedHeadsThreshold = config.MustNewDuration(10 * time.Second)
c.finalityDepth = ptr(uint32(0))
DylanTinianov marked this conversation as resolved.
Show resolved Hide resolved
c.finalityTagEnabled = ptr(true)
c.finalizedBlockOffset = ptr(uint32(0))
}

func (c *MultiNode) SetFrom(f *MultiNode) {
if f.multiNodeEnabled != nil {
c.multiNodeEnabled = f.multiNodeEnabled
}

// TODO: Try using reflection here to loop through each one

// Node Configs
if f.pollFailureThreshold != nil {
c.pollFailureThreshold = f.pollFailureThreshold
}
if f.pollInterval != nil {
c.pollInterval = f.pollInterval
}
if f.selectionMode != nil {
c.selectionMode = f.selectionMode
}
if f.syncThreshold != nil {
c.syncThreshold = f.syncThreshold
}
if f.nodeIsSyncingEnabled != nil {
c.nodeIsSyncingEnabled = f.nodeIsSyncingEnabled
}
if f.leaseDuration != nil {
c.leaseDuration = f.leaseDuration
}
if f.finalizedBlockPollInterval != nil {
c.finalizedBlockPollInterval = f.finalizedBlockPollInterval
}
if f.enforceRepeatableRead != nil {
c.enforceRepeatableRead = f.enforceRepeatableRead
}
if f.deathDeclarationDelay != nil {
c.deathDeclarationDelay = f.deathDeclarationDelay
}

// Chain Configs
if f.nodeNoNewHeadsThreshold != nil {
c.nodeNoNewHeadsThreshold = f.nodeNoNewHeadsThreshold
}
if f.noNewFinalizedHeadsThreshold != nil {
c.noNewFinalizedHeadsThreshold = f.noNewFinalizedHeadsThreshold
}
if f.finalityDepth != nil {
c.finalityDepth = f.finalityDepth
}
if f.finalityTagEnabled != nil {
c.finalityTagEnabled = f.finalityTagEnabled
}
if f.finalizedBlockOffset != nil {
c.finalizedBlockOffset = f.finalizedBlockOffset
}
}
5 changes: 3 additions & 2 deletions pkg/solana/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ type TOMLConfig struct {
// Do not access directly, use [IsEnabled]
Enabled *bool
Chain
MultiNode
Nodes Nodes
MultiNode MultiNode
Nodes Nodes
}

func (c *TOMLConfig) IsEnabled() bool {
Expand All @@ -130,6 +130,7 @@ func (c *TOMLConfig) SetFrom(f *TOMLConfig) {
}
setFromChain(&c.Chain, &f.Chain)
c.Nodes.SetFrom(&f.Nodes)
c.MultiNode.SetFrom(&f.MultiNode)
}

func setFromChain(c, f *Chain) {
Expand Down
Loading