From eacd0fec3a9a0c6f0ab85566456d7c216ddfc334 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 13:28:19 -0600 Subject: [PATCH 01/15] remove db config --- pkg/solana/cache_test.go | 7 +- pkg/solana/chain.go | 33 ++-- pkg/solana/chain_test.go | 28 ++-- pkg/solana/client/client_test.go | 9 +- pkg/solana/client/test_helpers_test.go | 3 +- pkg/solana/cmd/chainlink-solana/main.go | 3 +- pkg/solana/config.go | 197 +---------------------- pkg/solana/config/config.go | 170 -------------------- pkg/solana/config/toml.go | 205 ++++++++++++++++++++++++ pkg/solana/db/db.go | 54 ------- pkg/solana/txm/txm_internal_test.go | 5 +- pkg/solana/txm/txm_test.go | 8 +- 12 files changed, 258 insertions(+), 464 deletions(-) create mode 100644 pkg/solana/config/toml.go delete mode 100644 pkg/solana/db/db.go diff --git a/pkg/solana/cache_test.go b/pkg/solana/cache_test.go index 59e6c7bb6..5529be342 100644 --- a/pkg/solana/cache_test.go +++ b/pkg/solana/cache_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" ) var mockTransmission = []byte{ @@ -94,7 +93,7 @@ func testTransmissionsResponse(t *testing.T, body []byte, sub uint64) []byte { func testSetupReader(t *testing.T, endpoint string) client.Reader { lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() client, err := client.NewClient(endpoint, cfg, 1*time.Second, lggr) require.NoError(t, err) return client @@ -170,7 +169,7 @@ func TestCache(t *testing.T) { lggr := logger.Test(t) stateCache := StateCache{ StateID: solana.MustPublicKeyFromBase58("11111111111111111111111111111111"), - cfg: config.NewConfig(db.ChainCfg{}, lggr), + cfg: config.NewDefault(), reader: testSetupReader(t, mockServer.URL), lggr: lggr, } @@ -182,7 +181,7 @@ func TestCache(t *testing.T) { transmissionsCache := TransmissionsCache{ TransmissionsID: solana.MustPublicKeyFromBase58("11111111111111111111111111111112"), - cfg: config.NewConfig(db.ChainCfg{}, lggr), + cfg: config.NewDefault(), reader: testSetupReader(t, mockServer.URL), lggr: lggr, } diff --git a/pkg/solana/chain.go b/pkg/solana/chain.go index bc69a453e..6c2927d76 100644 --- a/pkg/solana/chain.go +++ b/pkg/solana/chain.go @@ -24,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" "github.com/smartcontractkit/chainlink-solana/pkg/solana/monitor" "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm" ) @@ -65,7 +64,7 @@ func (o *ChainOpts) GetLogger() logger.Logger { return o.Logger } -func NewChain(cfg *TOMLConfig, opts ChainOpts) (Chain, error) { +func NewChain(cfg *config.TOMLConfig, opts ChainOpts) (Chain, error) { if !cfg.IsEnabled() { return nil, fmt.Errorf("cannot create new chain with ID %s: chain is disabled", *cfg.ChainID) } @@ -81,7 +80,7 @@ var _ Chain = (*chain)(nil) type chain struct { services.StateMachine id string - cfg *TOMLConfig + cfg *config.TOMLConfig txm *txm.Txm balanceMonitor services.Service lggr logger.Logger @@ -214,7 +213,7 @@ func (v *verifiedCachedClient) GetAccountInfoWithOpts(ctx context.Context, addr return v.ReaderWriter.GetAccountInfoWithOpts(ctx, addr, opts) } -func newChain(id string, cfg *TOMLConfig, ks loop.Keystore, lggr logger.Logger) (*chain, error) { +func newChain(id string, cfg *config.TOMLConfig, ks loop.Keystore, lggr logger.Logger) (*chain, error) { lggr = logger.With(lggr, "chainID", id, "chain", "solana") var ch = chain{ id: id, @@ -297,12 +296,9 @@ func (c *chain) ChainID() string { // getClient returns a client, randomly selecting one from available and valid nodes func (c *chain) getClient() (client.ReaderWriter, error) { - var node db.Node + var node *config.Node var client client.ReaderWriter - nodes, err := c.cfg.ListNodes() - if err != nil { - return nil, fmt.Errorf("failed to get nodes: %w", err) - } + nodes := c.cfg.ListNodes() if len(nodes) == 0 { return nil, errors.New("no nodes available") } @@ -311,10 +307,11 @@ func (c *chain) getClient() (client.ReaderWriter, error) { for _, i := range index { node = nodes[i] // create client and check + var err error client, err = c.verifiedClient(node) // if error, try another node if err != nil { - c.lggr.Warnw("failed to create node", "name", node.Name, "solana-url", node.SolanaURL, "err", err.Error()) + c.lggr.Warnw("failed to create node", "name", node.Name, "solana-url", node.URL, "err", err.Error()) continue } // if all checks passed, mark found and break loop @@ -324,15 +321,23 @@ func (c *chain) getClient() (client.ReaderWriter, error) { if client == nil { return nil, errors.New("no node valid nodes available") } - c.lggr.Debugw("Created client", "name", node.Name, "solana-url", node.SolanaURL) + c.lggr.Debugw("Created client", "name", node.Name, "solana-url", node.URL) return client, nil } // verifiedClient returns a client for node or an error if fails to create the client. // The client will still be returned if the nodes are not valid, or the chain id doesn't match. // Further client calls will try and verify the client, and fail if the client is still not valid. -func (c *chain) verifiedClient(node db.Node) (client.ReaderWriter, error) { - url := node.SolanaURL +func (c *chain) verifiedClient(node *config.Node) (client.ReaderWriter, error) { + if node == nil { + return nil, fmt.Errorf("nil node") + } + + if node.Name == nil || node.URL == nil { + return nil, fmt.Errorf("node config contains nil: %+v", node) + } + + url := node.URL.String() var err error // check if cached client exists @@ -346,7 +351,7 @@ func (c *chain) verifiedClient(node db.Node) (client.ReaderWriter, error) { expectedChainID: c.id, } // create client - cl.ReaderWriter, err = client.NewClient(url, c.cfg, DefaultRequestTimeout, logger.Named(c.lggr, "Client."+node.Name)) + cl.ReaderWriter, err = client.NewClient(url, c.cfg, DefaultRequestTimeout, logger.Named(c.lggr, "Client."+*node.Name)) if err != nil { return nil, fmt.Errorf("failed to create client: %w", err) } diff --git a/pkg/solana/chain_test.go b/pkg/solana/chain_test.go index f01406e81..aa52b8b4d 100644 --- a/pkg/solana/chain_test.go +++ b/pkg/solana/chain_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -18,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" ) const TestSolanaGenesisHashTemplate = `{"jsonrpc":"2.0","result":"%s","id":1}` @@ -46,7 +46,7 @@ func TestSolanaChain_GetClient(t *testing.T) { ch := solcfg.Chain{} ch.SetDefaults() - cfg := &TOMLConfig{ + cfg := &solcfg.TOMLConfig{ ChainID: ptr("devnet"), Chain: ch, } @@ -143,7 +143,7 @@ func TestSolanaChain_VerifiedClient(t *testing.T) { ch := solcfg.Chain{} ch.SetDefaults() - cfg := &TOMLConfig{ + cfg := &solcfg.TOMLConfig{ ChainID: ptr("devnet"), Chain: ch, } @@ -152,28 +152,32 @@ func TestSolanaChain_VerifiedClient(t *testing.T) { lggr: logger.Test(t), clientCache: map[string]*verifiedCachedClient{}, } - node := db.Node{SolanaURL: mockServer.URL} + nName := t.Name() + "-" + uuid.NewString() + node := &solcfg.Node{ + Name: &nName, + URL: config.MustParseURL(mockServer.URL), + } // happy path testChain.id = "devnet" _, err := testChain.verifiedClient(node) - assert.NoError(t, err) + require.NoError(t, err) // retrieve cached client and retrieve slot height c, err := testChain.verifiedClient(node) - assert.NoError(t, err) + require.NoError(t, err) slot, err := c.SlotHeight() assert.NoError(t, err) assert.Equal(t, uint64(1234), slot) - node.SolanaURL = mockServer.URL + "/mismatch" + node.URL = config.MustParseURL(mockServer.URL + "/mismatch") testChain.id = "incorrect" c, err = testChain.verifiedClient(node) assert.NoError(t, err) _, err = c.ChainID() // expect error from id mismatch (even if using a cached client) when performing RPC calls assert.Error(t, err) - assert.Equal(t, fmt.Sprintf("client returned mismatched chain id (expected: %s, got: %s): %s", "incorrect", "devnet", node.SolanaURL), err.Error()) + assert.Equal(t, fmt.Sprintf("client returned mismatched chain id (expected: %s, got: %s): %s", "incorrect", "devnet", node.URL), err.Error()) } func TestSolanaChain_VerifiedClient_ParallelClients(t *testing.T) { @@ -186,7 +190,7 @@ func TestSolanaChain_VerifiedClient_ParallelClients(t *testing.T) { ch := solcfg.Chain{} ch.SetDefaults() - cfg := &TOMLConfig{ + cfg := &solcfg.TOMLConfig{ ChainID: ptr("devnet"), Enabled: ptr(true), Chain: ch, @@ -197,7 +201,11 @@ func TestSolanaChain_VerifiedClient_ParallelClients(t *testing.T) { lggr: logger.Test(t), clientCache: map[string]*verifiedCachedClient{}, } - node := db.Node{SolanaURL: mockServer.URL} + nName := t.Name() + "-" + uuid.NewString() + node := &solcfg.Node{ + Name: &nName, + URL: config.MustParseURL(mockServer.URL), + } var wg sync.WaitGroup wg.Add(2) diff --git a/pkg/solana/client/client_test.go b/pkg/solana/client/client_test.go index 0ac0ebcdb..94871e53a 100644 --- a/pkg/solana/client/client_test.go +++ b/pkg/solana/client/client_test.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" ) func TestClient_Reader_Integration(t *testing.T) { @@ -31,7 +30,7 @@ func TestClient_Reader_Integration(t *testing.T) { requestTimeout := 5 * time.Second lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() c, err := NewClient(url, cfg, requestTimeout, lggr) require.NoError(t, err) @@ -105,7 +104,7 @@ func TestClient_Reader_ChainID(t *testing.T) { requestTimeout := 5 * time.Second lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() c, err := NewClient(mockServer.URL, cfg, requestTimeout, lggr) require.NoError(t, err) @@ -126,7 +125,7 @@ func TestClient_Writer_Integration(t *testing.T) { requestTimeout := 5 * time.Second lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() ctx := context.Background() c, err := NewClient(url, cfg, requestTimeout, lggr) @@ -212,7 +211,7 @@ func TestClient_SendTxDuplicates_Integration(t *testing.T) { // create client requestTimeout := 5 * time.Second lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() c, err := NewClient(url, cfg, requestTimeout, lggr) require.NoError(t, err) diff --git a/pkg/solana/client/test_helpers_test.go b/pkg/solana/client/test_helpers_test.go index dd9e682a8..1f530da2b 100644 --- a/pkg/solana/client/test_helpers_test.go +++ b/pkg/solana/client/test_helpers_test.go @@ -11,7 +11,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" ) func TestSetupLocalSolNode_SimultaneousNetworks(t *testing.T) { @@ -25,7 +24,7 @@ func TestSetupLocalSolNode_SimultaneousNetworks(t *testing.T) { // client configs requestTimeout := 5 * time.Second lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() // check & fund address checkFunded := func(t *testing.T, url string) { diff --git a/pkg/solana/cmd/chainlink-solana/main.go b/pkg/solana/cmd/chainlink-solana/main.go index 22f614a18..e8a211af2 100644 --- a/pkg/solana/cmd/chainlink-solana/main.go +++ b/pkg/solana/cmd/chainlink-solana/main.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-solana/pkg/solana" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" ) const ( @@ -53,7 +54,7 @@ func (c *pluginRelayer) NewRelayer(ctx context.Context, config string, keystore d := toml.NewDecoder(strings.NewReader(config)) d.DisallowUnknownFields() var cfg struct { - Solana solana.TOMLConfig + Solana solcfg.TOMLConfig } if err := d.Decode(&cfg); err != nil { diff --git a/pkg/solana/config.go b/pkg/solana/config.go index 82c463b64..83ce47883 100644 --- a/pkg/solana/config.go +++ b/pkg/solana/config.go @@ -4,9 +4,7 @@ import ( "errors" "fmt" "net/url" - "time" - "github.com/gagliardetto/solana-go/rpc" "github.com/pelletier/go-toml/v2" "golang.org/x/exp/slices" @@ -14,13 +12,9 @@ import ( relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - soldb "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" ) -// Deprecated: use TOMLConfigs -type SolanaConfigs = TOMLConfigs - -type TOMLConfigs []*TOMLConfig +type TOMLConfigs []*solcfg.TOMLConfig func (cs TOMLConfigs) ValidateConfig() (err error) { return cs.validateKeys() @@ -65,7 +59,7 @@ func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) (err error) { for _, f := range *fs { if f.ChainID == nil { *cs = append(*cs, f) - } else if i := slices.IndexFunc(*cs, func(c *TOMLConfig) bool { + } else if i := slices.IndexFunc(*cs, func(c *solcfg.TOMLConfig) bool { return c.ChainID != nil && *c.ChainID == *f.ChainID }); i == -1 { *cs = append(*cs, f) @@ -87,190 +81,3 @@ func nodeStatus(n *solcfg.Node, id string) (relaytypes.NodeStatus, error) { s.Config = string(b) return s, nil } - -type SolanaNodes []*solcfg.Node - -func (ns *SolanaNodes) SetFrom(fs *SolanaNodes) { - for _, f := range *fs { - if f.Name == nil { - *ns = append(*ns, f) - } else if i := slices.IndexFunc(*ns, func(n *solcfg.Node) bool { - return n.Name != nil && *n.Name == *f.Name - }); i == -1 { - *ns = append(*ns, f) - } else { - setFromNode((*ns)[i], f) - } - } -} - -func setFromNode(n, f *solcfg.Node) { - if f.Name != nil { - n.Name = f.Name - } - if f.URL != nil { - n.URL = f.URL - } -} - -func legacySolNode(n *solcfg.Node, id string) soldb.Node { - return soldb.Node{ - Name: *n.Name, - SolanaChainID: id, - SolanaURL: (*url.URL)(n.URL).String(), - } -} - -// Deprecated: use TOMLConfig -type SolanaConfig = TOMLConfig - -type TOMLConfig struct { - ChainID *string - // Do not access directly, use [IsEnabled] - Enabled *bool - solcfg.Chain - Nodes SolanaNodes -} - -func (c *TOMLConfig) IsEnabled() bool { - return c.Enabled == nil || *c.Enabled -} - -func (c *TOMLConfig) SetFrom(f *TOMLConfig) { - if f.ChainID != nil { - c.ChainID = f.ChainID - } - if f.Enabled != nil { - c.Enabled = f.Enabled - } - setFromChain(&c.Chain, &f.Chain) - c.Nodes.SetFrom(&f.Nodes) -} - -func setFromChain(c, f *solcfg.Chain) { - if f.BalancePollPeriod != nil { - c.BalancePollPeriod = f.BalancePollPeriod - } - if f.ConfirmPollPeriod != nil { - c.ConfirmPollPeriod = f.ConfirmPollPeriod - } - if f.OCR2CachePollPeriod != nil { - c.OCR2CachePollPeriod = f.OCR2CachePollPeriod - } - if f.OCR2CacheTTL != nil { - c.OCR2CacheTTL = f.OCR2CacheTTL - } - if f.TxTimeout != nil { - c.TxTimeout = f.TxTimeout - } - if f.TxRetryTimeout != nil { - c.TxRetryTimeout = f.TxRetryTimeout - } - if f.TxConfirmTimeout != nil { - c.TxConfirmTimeout = f.TxConfirmTimeout - } - if f.SkipPreflight != nil { - c.SkipPreflight = f.SkipPreflight - } - if f.Commitment != nil { - c.Commitment = f.Commitment - } - if f.MaxRetries != nil { - c.MaxRetries = f.MaxRetries - } -} - -func (c *TOMLConfig) ValidateConfig() (err error) { - if c.ChainID == nil { - err = errors.Join(err, config.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) - } else if *c.ChainID == "" { - err = errors.Join(err, config.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) - } - - if len(c.Nodes) == 0 { - err = errors.Join(err, config.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) - } - return -} - -func (c *TOMLConfig) TOMLString() (string, error) { - b, err := toml.Marshal(c) - if err != nil { - return "", err - } - return string(b), nil -} - -var _ solcfg.Config = &TOMLConfig{} - -func (c *TOMLConfig) BalancePollPeriod() time.Duration { - return c.Chain.BalancePollPeriod.Duration() -} - -func (c *TOMLConfig) ConfirmPollPeriod() time.Duration { - return c.Chain.ConfirmPollPeriod.Duration() -} - -func (c *TOMLConfig) OCR2CachePollPeriod() time.Duration { - return c.Chain.OCR2CachePollPeriod.Duration() -} - -func (c *TOMLConfig) OCR2CacheTTL() time.Duration { - return c.Chain.OCR2CacheTTL.Duration() -} - -func (c *TOMLConfig) TxTimeout() time.Duration { - return c.Chain.TxTimeout.Duration() -} - -func (c *TOMLConfig) TxRetryTimeout() time.Duration { - return c.Chain.TxRetryTimeout.Duration() -} - -func (c *TOMLConfig) TxConfirmTimeout() time.Duration { - return c.Chain.TxConfirmTimeout.Duration() -} - -func (c *TOMLConfig) SkipPreflight() bool { - return *c.Chain.SkipPreflight -} - -func (c *TOMLConfig) Commitment() rpc.CommitmentType { - return rpc.CommitmentType(*c.Chain.Commitment) -} - -func (c *TOMLConfig) MaxRetries() *uint { - if c.Chain.MaxRetries == nil { - return nil - } - mr := uint(*c.Chain.MaxRetries) - return &mr -} - -func (c *TOMLConfig) FeeEstimatorMode() string { - return *c.Chain.FeeEstimatorMode -} - -func (c *TOMLConfig) ComputeUnitPriceMax() uint64 { - return *c.Chain.ComputeUnitPriceMax -} - -func (c *TOMLConfig) ComputeUnitPriceMin() uint64 { - return *c.Chain.ComputeUnitPriceMin -} - -func (c *TOMLConfig) ComputeUnitPriceDefault() uint64 { - return *c.Chain.ComputeUnitPriceDefault -} - -func (c *TOMLConfig) FeeBumpPeriod() time.Duration { - return c.Chain.FeeBumpPeriod.Duration() -} - -func (c *TOMLConfig) ListNodes() ([]soldb.Node, error) { - var allNodes []soldb.Node - for _, n := range c.Nodes { - allNodes = append(allNodes, legacySolNode(n, *c.ChainID)) - } - return allNodes, nil -} diff --git a/pkg/solana/config/config.go b/pkg/solana/config/config.go index 15a96c62d..83753e5cd 100644 --- a/pkg/solana/config/config.go +++ b/pkg/solana/config/config.go @@ -2,15 +2,11 @@ package config import ( "errors" - "strings" "time" "github.com/gagliardetto/solana-go/rpc" "github.com/smartcontractkit/chainlink-common/pkg/config" - - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/logger" ) // Global solana defaults. @@ -75,172 +71,6 @@ type configSet struct { FeeBumpPeriod time.Duration } -var _ Config = (*cfg)(nil) - -// Deprecated -type cfg struct { - defaults configSet - chain db.ChainCfg - lggr logger.Logger -} - -// NewConfig returns a Config with defaults overridden by dbcfg. -// Deprecated -func NewConfig(dbcfg db.ChainCfg, lggr logger.Logger) *cfg { - return &cfg{ - defaults: defaultConfigSet, - chain: dbcfg, - lggr: lggr, - } -} - -func (c *cfg) BalancePollPeriod() time.Duration { - ch := c.chain.BalancePollPeriod - if ch != nil { - return ch.Duration() - } - return c.defaults.BalancePollPeriod -} - -func (c *cfg) ConfirmPollPeriod() time.Duration { - ch := c.chain.ConfirmPollPeriod - if ch != nil { - return ch.Duration() - } - return c.defaults.ConfirmPollPeriod -} - -func (c *cfg) OCR2CachePollPeriod() time.Duration { - ch := c.chain.OCR2CachePollPeriod - if ch != nil { - return ch.Duration() - } - return c.defaults.OCR2CachePollPeriod -} - -func (c *cfg) OCR2CacheTTL() time.Duration { - ch := c.chain.OCR2CacheTTL - if ch != nil { - return ch.Duration() - } - return c.defaults.OCR2CacheTTL -} - -func (c *cfg) TxTimeout() time.Duration { - ch := c.chain.TxTimeout - if ch != nil { - return ch.Duration() - } - return c.defaults.TxTimeout -} - -func (c *cfg) TxRetryTimeout() time.Duration { - ch := c.chain.TxRetryTimeout - if ch != nil { - return ch.Duration() - } - return c.defaults.TxRetryTimeout -} - -func (c *cfg) TxConfirmTimeout() time.Duration { - ch := c.chain.TxConfirmTimeout - if ch != nil { - return ch.Duration() - } - return c.defaults.TxConfirmTimeout -} - -func (c *cfg) SkipPreflight() bool { - ch := c.chain.SkipPreflight - if ch.Valid { - return ch.Bool - } - return c.defaults.SkipPreflight -} - -func (c *cfg) Commitment() rpc.CommitmentType { - ch := c.chain.Commitment - if ch.Valid { - str := ch.String - var commitment rpc.CommitmentType - switch str { - case "processed": - commitment = rpc.CommitmentProcessed - case "confirmed": - commitment = rpc.CommitmentConfirmed - case "finalized": - commitment = rpc.CommitmentFinalized - default: - c.lggr.Warnf(`Invalid value provided for %s, "%s" - falling back to default "%s"`, "CommitmentType", str, c.defaults.Commitment) - commitment = rpc.CommitmentConfirmed - } - return commitment - } - return c.defaults.Commitment -} - -func (c *cfg) FeeEstimatorMode() string { - ch := c.chain.FeeEstimatorMode - if ch.Valid { - return strings.ToLower(ch.String) - } - return c.defaults.FeeEstimatorMode -} - -func (c *cfg) ComputeUnitPriceMax() uint64 { - ch := c.chain.ComputeUnitPriceMax - if ch.Valid { - if ch.Int64 >= 0 { - return uint64(ch.Int64) - } - c.lggr.Warnf("Negative value provided for ComputeUnitPriceMax, falling back to default: %d", c.defaults.ComputeUnitPriceMax) - } - return c.defaults.ComputeUnitPriceMax -} - -func (c *cfg) ComputeUnitPriceMin() uint64 { - ch := c.chain.ComputeUnitPriceMin - if ch.Valid { - if ch.Int64 >= 0 { - return uint64(ch.Int64) - } - c.lggr.Warnf("Negative value provided for ComputeUnitPriceMin, falling back to default: %d", c.defaults.ComputeUnitPriceMin) - } - return c.defaults.ComputeUnitPriceMin -} - -func (c *cfg) ComputeUnitPriceDefault() uint64 { - ch := c.chain.ComputeUnitPriceDefault - if ch.Valid { - if ch.Int64 >= 0 { - return uint64(ch.Int64) - } - c.lggr.Warnf("Negative value provided for ComputeUnitPriceDefault, falling back to default: %d", c.defaults.ComputeUnitPriceDefault) - } - return c.defaults.ComputeUnitPriceDefault -} - -func (c *cfg) MaxRetries() *uint { - ch := c.chain.MaxRetries - if ch.Valid { - if ch.Int64 < 0 { - c.lggr.Warnf(`Negative value provided for %s: %d, falling back to - let RPC node do a reasonable amount of tries`, "MaxRetries", ch.Int64) - return nil - } - val := uint(ch.Int64) - return &val - } - return c.defaults.MaxRetries -} - -func (c *cfg) FeeBumpPeriod() time.Duration { - ch := c.chain.FeeBumpPeriod - if ch != nil { - return ch.Duration() - } - return c.defaults.FeeBumpPeriod -} - type Chain struct { BalancePollPeriod *config.Duration ConfirmPollPeriod *config.Duration diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go new file mode 100644 index 000000000..dd337e22d --- /dev/null +++ b/pkg/solana/config/toml.go @@ -0,0 +1,205 @@ +package config + +import ( + "errors" + "time" + + "github.com/gagliardetto/solana-go/rpc" + "github.com/pelletier/go-toml/v2" + "golang.org/x/exp/slices" + + "github.com/smartcontractkit/chainlink-common/pkg/config" +) + +type SolanaNodes []*Node + +func (ns *SolanaNodes) SetFrom(fs *SolanaNodes) { + for _, f := range *fs { + if f.Name == nil { + *ns = append(*ns, f) + } else if i := slices.IndexFunc(*ns, func(n *Node) bool { + return n.Name != nil && *n.Name == *f.Name + }); i == -1 { + *ns = append(*ns, f) + } else { + setFromNode((*ns)[i], f) + } + } +} + +func setFromNode(n, f *Node) { + if f.Name != nil { + n.Name = f.Name + } + if f.URL != nil { + n.URL = f.URL + } +} + +type TOMLConfig struct { + ChainID *string + // Do not access directly, use [IsEnabled] + Enabled *bool + Chain + Nodes SolanaNodes +} + +func (c *TOMLConfig) IsEnabled() bool { + return c.Enabled == nil || *c.Enabled +} + +func (c *TOMLConfig) SetFrom(f *TOMLConfig) { + if f.ChainID != nil { + c.ChainID = f.ChainID + } + if f.Enabled != nil { + c.Enabled = f.Enabled + } + setFromChain(&c.Chain, &f.Chain) + c.Nodes.SetFrom(&f.Nodes) +} + +func setFromChain(c, f *Chain) { + if f.BalancePollPeriod != nil { + c.BalancePollPeriod = f.BalancePollPeriod + } + if f.ConfirmPollPeriod != nil { + c.ConfirmPollPeriod = f.ConfirmPollPeriod + } + if f.OCR2CachePollPeriod != nil { + c.OCR2CachePollPeriod = f.OCR2CachePollPeriod + } + if f.OCR2CacheTTL != nil { + c.OCR2CacheTTL = f.OCR2CacheTTL + } + if f.TxTimeout != nil { + c.TxTimeout = f.TxTimeout + } + if f.TxRetryTimeout != nil { + c.TxRetryTimeout = f.TxRetryTimeout + } + if f.TxConfirmTimeout != nil { + c.TxConfirmTimeout = f.TxConfirmTimeout + } + if f.SkipPreflight != nil { + c.SkipPreflight = f.SkipPreflight + } + if f.Commitment != nil { + c.Commitment = f.Commitment + } + if f.MaxRetries != nil { + c.MaxRetries = f.MaxRetries + } + if f.FeeEstimatorMode != nil { + c.FeeEstimatorMode = f.FeeEstimatorMode + } + if f.ComputeUnitPriceMax != nil { + c.ComputeUnitPriceMax = f.ComputeUnitPriceMax + } + if f.ComputeUnitPriceMin != nil { + c.ComputeUnitPriceMin = f.ComputeUnitPriceMin + } + if f.ComputeUnitPriceDefault != nil { + c.ComputeUnitPriceDefault = f.ComputeUnitPriceDefault + } + if f.FeeBumpPeriod != nil { + c.FeeBumpPeriod = f.FeeBumpPeriod + } +} + +func (c *TOMLConfig) ValidateConfig() (err error) { + if c.ChainID == nil { + err = errors.Join(err, config.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) + } else if *c.ChainID == "" { + err = errors.Join(err, config.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) + } + + if len(c.Nodes) == 0 { + err = errors.Join(err, config.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) + } + return +} + +func (c *TOMLConfig) TOMLString() (string, error) { + b, err := toml.Marshal(c) + if err != nil { + return "", err + } + return string(b), nil +} + +var _ Config = &TOMLConfig{} + +func (c *TOMLConfig) BalancePollPeriod() time.Duration { + return c.Chain.BalancePollPeriod.Duration() +} + +func (c *TOMLConfig) ConfirmPollPeriod() time.Duration { + return c.Chain.ConfirmPollPeriod.Duration() +} + +func (c *TOMLConfig) OCR2CachePollPeriod() time.Duration { + return c.Chain.OCR2CachePollPeriod.Duration() +} + +func (c *TOMLConfig) OCR2CacheTTL() time.Duration { + return c.Chain.OCR2CacheTTL.Duration() +} + +func (c *TOMLConfig) TxTimeout() time.Duration { + return c.Chain.TxTimeout.Duration() +} + +func (c *TOMLConfig) TxRetryTimeout() time.Duration { + return c.Chain.TxRetryTimeout.Duration() +} + +func (c *TOMLConfig) TxConfirmTimeout() time.Duration { + return c.Chain.TxConfirmTimeout.Duration() +} + +func (c *TOMLConfig) SkipPreflight() bool { + return *c.Chain.SkipPreflight +} + +func (c *TOMLConfig) Commitment() rpc.CommitmentType { + return rpc.CommitmentType(*c.Chain.Commitment) +} + +func (c *TOMLConfig) MaxRetries() *uint { + if c.Chain.MaxRetries == nil { + return nil + } + mr := uint(*c.Chain.MaxRetries) + return &mr +} + +func (c *TOMLConfig) FeeEstimatorMode() string { + return *c.Chain.FeeEstimatorMode +} + +func (c *TOMLConfig) ComputeUnitPriceMax() uint64 { + return *c.Chain.ComputeUnitPriceMax +} + +func (c *TOMLConfig) ComputeUnitPriceMin() uint64 { + return *c.Chain.ComputeUnitPriceMin +} + +func (c *TOMLConfig) ComputeUnitPriceDefault() uint64 { + return *c.Chain.ComputeUnitPriceDefault +} + +func (c *TOMLConfig) FeeBumpPeriod() time.Duration { + return c.Chain.FeeBumpPeriod.Duration() +} + +func (c *TOMLConfig) ListNodes() SolanaNodes { + return c.Nodes +} + +func NewDefault() *TOMLConfig { + cfg := &TOMLConfig{} + cfg.SetDefaults() + return cfg +} diff --git a/pkg/solana/db/db.go b/pkg/solana/db/db.go deleted file mode 100644 index 30c3e6a1a..000000000 --- a/pkg/solana/db/db.go +++ /dev/null @@ -1,54 +0,0 @@ -package db - -import ( - "database/sql/driver" - "encoding/json" - "errors" - "time" - - "gopkg.in/guregu/null.v4" - - "github.com/smartcontractkit/chainlink-common/pkg/config" -) - -type Node struct { - ID int32 - Name string - SolanaChainID string `json:"solanaChainId" db:"solana_chain_id"` - SolanaURL string `json:"solanaURL" db:"solana_url"` - CreatedAt time.Time - UpdatedAt time.Time -} - -// Deprecated -type ChainCfg struct { - BalancePollPeriod *config.Duration - ConfirmPollPeriod *config.Duration - OCR2CachePollPeriod *config.Duration - OCR2CacheTTL *config.Duration - TxTimeout *config.Duration - TxRetryTimeout *config.Duration - TxConfirmTimeout *config.Duration - SkipPreflight null.Bool // to enable or disable preflight checks - Commitment null.String - MaxRetries null.Int - - FeeEstimatorMode null.String - ComputeUnitPriceMax null.Int - ComputeUnitPriceMin null.Int - ComputeUnitPriceDefault null.Int - FeeBumpPeriod *config.Duration -} - -func (c *ChainCfg) Scan(value interface{}) error { - b, ok := value.([]byte) - if !ok { - return errors.New("type assertion to []byte failed") - } - - return json.Unmarshal(b, c) -} - -func (c *ChainCfg) Value() (driver.Value, error) { - return json.Marshal(c) -} diff --git a/pkg/solana/txm/txm_internal_test.go b/pkg/solana/txm/txm_internal_test.go index 8e303a712..3299e7da6 100644 --- a/pkg/solana/txm/txm_internal_test.go +++ b/pkg/solana/txm/txm_internal_test.go @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/mocks" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" "github.com/smartcontractkit/chainlink-solana/pkg/solana/fees" keyMocks "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm/mocks" @@ -94,7 +93,7 @@ func TestTxm(t *testing.T) { ctx := tests.Context(t) lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() mc := mocks.NewReaderWriter(t) // mock solana keystore @@ -577,7 +576,7 @@ func TestTxm(t *testing.T) { func TestTxm_Enqueue(t *testing.T) { // set up configs needed in txm lggr := logger.Test(t) - cfg := config.NewConfig(db.ChainCfg{}, lggr) + cfg := config.NewDefault() mc := mocks.NewReaderWriter(t) // mock solana keystore diff --git a/pkg/solana/txm/txm_test.go b/pkg/solana/txm/txm_test.go index 597f32043..85e84ba90 100644 --- a/pkg/solana/txm/txm_test.go +++ b/pkg/solana/txm/txm_test.go @@ -16,7 +16,6 @@ import ( solanaClient "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/db" "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm" keyMocks "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm/mocks" @@ -59,11 +58,8 @@ func TestTxm_Integration(t *testing.T) { // set up txm lggr := logger.Test(t) - confirmDuration, err := relayconfig.NewDuration(500 * time.Millisecond) - require.NoError(t, err) - cfg := config.NewConfig(db.ChainCfg{ - ConfirmPollPeriod: &confirmDuration, - }, lggr) + cfg := config.NewDefault() + cfg.Chain.ConfirmPollPeriod = relayconfig.MustNewDuration(500 * time.Millisecond) client, err := solanaClient.NewClient(url, cfg, 2*time.Second, lggr) require.NoError(t, err) getClient := func() (solanaClient.ReaderWriter, error) { From 38db8e1a35a08e339a5981666e987315503596b0 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 13:30:24 -0600 Subject: [PATCH 02/15] gomodtidy --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index a2d9d9405..d51a4b7e0 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 golang.org/x/text v0.14.0 - gopkg.in/guregu/null.v4 v4.0.0 ) require ( diff --git a/go.sum b/go.sum index a977cafcf..406196eb3 100644 --- a/go.sum +++ b/go.sum @@ -923,8 +923,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= -gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= From 3258424be5695690ae8e1fa7813595f9c343c6ff Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 14:02:28 -0600 Subject: [PATCH 03/15] prevent overflow on MaxRetries --- pkg/solana/config/config.go | 2 +- pkg/solana/config/toml.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/solana/config/config.go b/pkg/solana/config/config.go index 83753e5cd..df5be635f 100644 --- a/pkg/solana/config/config.go +++ b/pkg/solana/config/config.go @@ -20,7 +20,7 @@ var defaultConfigSet = configSet{ TxConfirmTimeout: 30 * time.Second, // duration before discarding tx as unconfirmed SkipPreflight: true, // to enable or disable preflight checks Commitment: rpc.CommitmentConfirmed, - MaxRetries: new(uint), // max number of retries, when nil - rpc node will do a reasonable number of retries + MaxRetries: new(uint), // max number of retries (default = *new(uint) = 0). when config.MaxRetries < 0, interpreted as MaxRetries = nil and rpc node will do a reasonable number of retries // fee estimator FeeEstimatorMode: "fixed", diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index dd337e22d..4b3635473 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -170,6 +170,9 @@ func (c *TOMLConfig) MaxRetries() *uint { if c.Chain.MaxRetries == nil { return nil } + if *c.Chain.MaxRetries < 0 { + return nil // interpret negative numbers as nil (prevents unlikely case of overflow) + } mr := uint(*c.Chain.MaxRetries) return &mr } From ecb23e9075c95ce0d292741f490ec57b86f85c0f Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 14:25:03 -0600 Subject: [PATCH 04/15] move config.go -> config/toml.go --- pkg/solana/chain.go | 2 +- pkg/solana/config.go | 83 --------------------------------------- pkg/solana/config/toml.go | 71 +++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 84 deletions(-) delete mode 100644 pkg/solana/config.go diff --git a/pkg/solana/chain.go b/pkg/solana/chain.go index 6c2927d76..e62aa4531 100644 --- a/pkg/solana/chain.go +++ b/pkg/solana/chain.go @@ -261,7 +261,7 @@ func (c *chain) listNodeStatuses(start, end int) ([]relaytypes.NodeStatus, int, } nodes := c.cfg.Nodes[start:end] for _, node := range nodes { - stat, err := nodeStatus(node, c.ChainID()) + stat, err := config.NodeStatus(node, c.ChainID()) if err != nil { return stats, total, err } diff --git a/pkg/solana/config.go b/pkg/solana/config.go deleted file mode 100644 index 83ce47883..000000000 --- a/pkg/solana/config.go +++ /dev/null @@ -1,83 +0,0 @@ -package solana - -import ( - "errors" - "fmt" - "net/url" - - "github.com/pelletier/go-toml/v2" - "golang.org/x/exp/slices" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" - - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" -) - -type TOMLConfigs []*solcfg.TOMLConfig - -func (cs TOMLConfigs) ValidateConfig() (err error) { - return cs.validateKeys() -} - -func (cs TOMLConfigs) validateKeys() (err error) { - // Unique chain IDs - chainIDs := config.UniqueStrings{} - for i, c := range cs { - if chainIDs.IsDupe(c.ChainID) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) - } - } - - // Unique node names - names := config.UniqueStrings{} - for i, c := range cs { - for j, n := range c.Nodes { - if names.IsDupe(n.Name) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) - } - } - } - - // Unique URLs - urls := config.UniqueStrings{} - for i, c := range cs { - for j, n := range c.Nodes { - u := (*url.URL)(n.URL) - if urls.IsDupeFmt(u) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) - } - } - } - return -} - -func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) (err error) { - if err1 := fs.validateKeys(); err1 != nil { - return err1 - } - for _, f := range *fs { - if f.ChainID == nil { - *cs = append(*cs, f) - } else if i := slices.IndexFunc(*cs, func(c *solcfg.TOMLConfig) bool { - return c.ChainID != nil && *c.ChainID == *f.ChainID - }); i == -1 { - *cs = append(*cs, f) - } else { - (*cs)[i].SetFrom(f) - } - } - return -} - -func nodeStatus(n *solcfg.Node, id string) (relaytypes.NodeStatus, error) { - var s relaytypes.NodeStatus - s.ChainID = id - s.Name = *n.Name - b, err := toml.Marshal(n) - if err != nil { - return relaytypes.NodeStatus{}, err - } - s.Config = string(b) - return s, nil -} diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index 4b3635473..b6106dc23 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -2,6 +2,8 @@ package config import ( "errors" + "fmt" + "net/url" "time" "github.com/gagliardetto/solana-go/rpc" @@ -9,8 +11,77 @@ import ( "golang.org/x/exp/slices" "github.com/smartcontractkit/chainlink-common/pkg/config" + relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" ) +type TOMLConfigs []*TOMLConfig + +func (cs TOMLConfigs) ValidateConfig() (err error) { + return cs.validateKeys() +} + +func (cs TOMLConfigs) validateKeys() (err error) { + // Unique chain IDs + chainIDs := config.UniqueStrings{} + for i, c := range cs { + if chainIDs.IsDupe(c.ChainID) { + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) + } + } + + // Unique node names + names := config.UniqueStrings{} + for i, c := range cs { + for j, n := range c.Nodes { + if names.IsDupe(n.Name) { + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) + } + } + } + + // Unique URLs + urls := config.UniqueStrings{} + for i, c := range cs { + for j, n := range c.Nodes { + u := (*url.URL)(n.URL) + if urls.IsDupeFmt(u) { + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) + } + } + } + return +} + +func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) (err error) { + if err1 := fs.validateKeys(); err1 != nil { + return err1 + } + for _, f := range *fs { + if f.ChainID == nil { + *cs = append(*cs, f) + } else if i := slices.IndexFunc(*cs, func(c *TOMLConfig) bool { + return c.ChainID != nil && *c.ChainID == *f.ChainID + }); i == -1 { + *cs = append(*cs, f) + } else { + (*cs)[i].SetFrom(f) + } + } + return +} + +func NodeStatus(n *Node, id string) (relaytypes.NodeStatus, error) { + var s relaytypes.NodeStatus + s.ChainID = id + s.Name = *n.Name + b, err := toml.Marshal(n) + if err != nil { + return relaytypes.NodeStatus{}, err + } + s.Config = string(b) + return s, nil +} + type SolanaNodes []*Node func (ns *SolanaNodes) SetFrom(fs *SolanaNodes) { From d88b16df135014a3232ff9c3ae2391473a0b8cad Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 14:50:00 -0600 Subject: [PATCH 05/15] bump + fix e2e tests --- integration-tests/common/common.go | 5 ++--- integration-tests/go.mod | 6 +++--- integration-tests/go.sum | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index 9053d188e..8e04a6b5c 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -42,7 +42,6 @@ import ( test_env_sol "github.com/smartcontractkit/chainlink-solana/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink-solana/integration-tests/solclient" - "github.com/smartcontractkit/chainlink-solana/pkg/solana" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" ) @@ -497,7 +496,7 @@ func BuildNodeContractPairID(node *client.ChainlinkClient, ocr2Addr string) (str } func (c *Common) DefaultNodeConfig() *cl.Config { - solConfig := solana.TOMLConfig{ + solConfig := solcfg.TOMLConfig{ Enabled: ptr.Ptr(true), ChainID: ptr.Ptr(c.ChainId), Nodes: []*solcfg.Node{ @@ -508,7 +507,7 @@ func (c *Common) DefaultNodeConfig() *cl.Config { }, } baseConfig := node.NewBaseConfig() - baseConfig.Solana = solana.TOMLConfigs{ + baseConfig.Solana = solcfg.TOMLConfigs{ &solConfig, } baseConfig.OCR2.Enabled = ptr.Ptr(true) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 49e42190d..a36d7e232 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -12,11 +12,11 @@ require ( github.com/lib/pq v1.10.9 github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240516150131-e1be553a9d10 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240510181707-46b1311a5a83 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240517134904-f4446b816a28 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240517202503-ecb23e9075c9 github.com/smartcontractkit/chainlink-testing-framework v1.28.12 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 - github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240515225456-aeb9f4d50d65 + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d50d05972..e97d478a5 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1406,8 +1406,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240516150131-e1be553a9d10 h1:IwJKWZHPBJbbh4oI3BGX8VNT3c/ChNiPZ/XI4iq6c0E= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240516150131-e1be553a9d10/go.mod h1:sj0pjL+METqeYL9ibp0T8SXquymlaQsofa6bdfLgXX8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240517134904-f4446b816a28 h1:Pr8/CdiTNnzRwpYc2z7NpHYbw3Dpl1eqiqt9/J/Bcqc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240517134904-f4446b816a28/go.mod h1:s+68EchlrXqHKRW3JJgZLEARvzMSKRI5+cE5Zx7pVJA= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240508101745-af1ed7bc8a69 h1:Sec/GpBpUVaTEax1kSHlTvkzF/+d3w5roAQXaj5+SLA= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240508101745-af1ed7bc8a69/go.mod h1:ZQKf+0OLzCLYIisH/OdOIQuFRI6bDuw+jPBTATyHfFM= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= @@ -1424,8 +1424,8 @@ github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1: github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 h1:8AoBDPHOLgZA1JodqysYK/JxcVbjwNhyGfmwzQuep4s= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65/go.mod h1:DOeyxJuvSV8No26UHAtmvZTycuGe0S4w/XMMj1EGMV8= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240515225456-aeb9f4d50d65 h1:ba2ZooA598i9P2qakTggT81f5TIFI9efPVsGy7MjY9Y= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240515225456-aeb9f4d50d65/go.mod h1:ICLCfUotU6Zk+S2kry3XE6i3lyhk30sr2rz89Y5QkGI= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb h1:Lvvryi+wf5XukbEd5CIitQ8mvD7qntA8PEUT2I3/LAA= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb/go.mod h1:9gXqIjXjAJTP3nEIJLk7yskSw+Snc+oNFsx8+9admM4= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= From 4a5f6d2cfecbfa70ca82403f676ecd89a8a4bba9 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 16:18:28 -0600 Subject: [PATCH 06/15] use multierr.append for proper delineation --- go.mod | 2 +- pkg/solana/config/toml.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index d51a4b7e0..bff22e670 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/smartcontractkit/chainlink-common v0.1.7-0.20240516150131-e1be553a9d10 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/stretchr/testify v1.9.0 + go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 @@ -102,7 +103,6 @@ require ( go.opentelemetry.io/otel/sdk v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/mod v0.14.0 // indirect diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index b6106dc23..ee72e6317 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -8,6 +8,7 @@ import ( "github.com/gagliardetto/solana-go/rpc" "github.com/pelletier/go-toml/v2" + "go.uber.org/multierr" "golang.org/x/exp/slices" "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -25,7 +26,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { chainIDs := config.UniqueStrings{} for i, c := range cs { if chainIDs.IsDupe(c.ChainID) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) + err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) } } @@ -34,7 +35,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { for i, c := range cs { for j, n := range c.Nodes { if names.IsDupe(n.Name) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) + err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) } } } @@ -45,7 +46,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { for j, n := range c.Nodes { u := (*url.URL)(n.URL) if urls.IsDupeFmt(u) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) + err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) } } } From 8fb84c1ed9687b4cf58cf6477722c8140be3215c Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Fri, 17 May 2024 17:18:23 -0600 Subject: [PATCH 07/15] bump core commit --- integration-tests/go.mod | 4 ++-- integration-tests/go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index a36d7e232..1363bb746 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -13,10 +13,10 @@ require ( github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240517134904-f4446b816a28 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240517202503-ecb23e9075c9 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240517221828-4a5f6d2cfecb github.com/smartcontractkit/chainlink-testing-framework v1.28.12 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 - github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e97d478a5..c848f04f6 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1424,8 +1424,8 @@ github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1: github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 h1:8AoBDPHOLgZA1JodqysYK/JxcVbjwNhyGfmwzQuep4s= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65/go.mod h1:DOeyxJuvSV8No26UHAtmvZTycuGe0S4w/XMMj1EGMV8= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb h1:Lvvryi+wf5XukbEd5CIitQ8mvD7qntA8PEUT2I3/LAA= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517204058-5e3d59f6c4bb/go.mod h1:9gXqIjXjAJTP3nEIJLk7yskSw+Snc+oNFsx8+9admM4= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e h1:NKoYXknuEprU7pk7jDQ/YRIuXwg1Rj7TpdGxX28fs+Y= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e/go.mod h1:ZyqcVJrDQx5/kvNwbpbGZsGW5KzUS0U/btG78BUEnMo= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= From 270e303c0412cedc32fe65ce21fa935fe4d46268 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Tue, 21 May 2024 08:35:20 -0600 Subject: [PATCH 08/15] SolanaNodes -> Nodes --- pkg/solana/config/toml.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index bb1165ec9..62ab98dfd 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -83,10 +83,9 @@ func NodeStatus(n *Node, id string) (relaytypes.NodeStatus, error) { return s, nil } -// revive:disable-next-line will be handled in https://github.com/smartcontractkit/chainlink-solana/pull/709 -type SolanaNodes []*Node +type Nodes []*Node -func (ns *SolanaNodes) SetFrom(fs *SolanaNodes) { +func (ns *Nodes) SetFrom(fs *Nodes) { for _, f := range *fs { if f.Name == nil { *ns = append(*ns, f) @@ -114,7 +113,7 @@ type TOMLConfig struct { // Do not access directly, use [IsEnabled] Enabled *bool Chain - Nodes SolanaNodes + Nodes Nodes } func (c *TOMLConfig) IsEnabled() bool { @@ -270,7 +269,7 @@ func (c *TOMLConfig) FeeBumpPeriod() time.Duration { return c.Chain.FeeBumpPeriod.Duration() } -func (c *TOMLConfig) ListNodes() SolanaNodes { +func (c *TOMLConfig) ListNodes() Nodes { return c.Nodes } From 6c605f618787be82cbd6dd00ae893ea75c318392 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Tue, 21 May 2024 14:08:03 -0600 Subject: [PATCH 09/15] use errors.Join --- pkg/solana/config/toml.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index 62ab98dfd..04cf0a08f 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -8,7 +8,6 @@ import ( "github.com/gagliardetto/solana-go/rpc" "github.com/pelletier/go-toml/v2" - "go.uber.org/multierr" "golang.org/x/exp/slices" "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -26,7 +25,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { chainIDs := config.UniqueStrings{} for i, c := range cs { if chainIDs.IsDupe(c.ChainID) { - err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) } } @@ -35,7 +34,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { for i, c := range cs { for j, n := range c.Nodes { if names.IsDupe(n.Name) { - err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) } } } @@ -46,7 +45,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { for j, n := range c.Nodes { u := (*url.URL)(n.URL) if urls.IsDupeFmt(u) { - err = multierr.Append(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) + err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) } } } From 5a2e75269a984d4cdfde2484d4e8e558b6e7022d Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Tue, 21 May 2024 14:15:29 -0600 Subject: [PATCH 10/15] pin core integration tests --- go.mod | 2 +- integration-tests/go.mod | 4 ++-- integration-tests/go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 266c759d2..c9bbf8583 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/smartcontractkit/chainlink-common v0.1.7-0.20240516150131-e1be553a9d10 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/stretchr/testify v1.9.0 - go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 @@ -103,6 +102,7 @@ require ( go.opentelemetry.io/otel/sdk v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/mod v0.14.0 // indirect diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 8da6f064f..260adbe78 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -12,10 +12,10 @@ require ( github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240517134904-f4446b816a28 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240517221828-4a5f6d2cfecb + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240521200803-6c605f618787 github.com/smartcontractkit/chainlink-testing-framework v1.28.12 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 - github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240521201249-c00f33248fe4 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c848f04f6..a589bc7f1 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1424,8 +1424,8 @@ github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1: github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65 h1:8AoBDPHOLgZA1JodqysYK/JxcVbjwNhyGfmwzQuep4s= github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240515225456-aeb9f4d50d65/go.mod h1:DOeyxJuvSV8No26UHAtmvZTycuGe0S4w/XMMj1EGMV8= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e h1:NKoYXknuEprU7pk7jDQ/YRIuXwg1Rj7TpdGxX28fs+Y= -github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240517223924-60eb51b3b61e/go.mod h1:ZyqcVJrDQx5/kvNwbpbGZsGW5KzUS0U/btG78BUEnMo= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240521201249-c00f33248fe4 h1:KrQxqehwHCpbJJtltv2iWlVR+cxNzEoBN8EFtbwWtPg= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240521201249-c00f33248fe4/go.mod h1:10XUZ0WuFDdW+RYD0PdTpHlnaxkh/sqeAtjrAV6vUvQ= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= From 6d763ca9f7b48693f5ae2abd8e0a7a51ce85fff1 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Wed, 22 May 2024 11:47:26 -0600 Subject: [PATCH 11/15] flatten validation errors --- pkg/solana/config/toml.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index 04cf0a08f..4b865c8ae 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -21,11 +21,13 @@ func (cs TOMLConfigs) ValidateConfig() (err error) { } func (cs TOMLConfigs) validateKeys() (err error) { + errA := []error{} + // Unique chain IDs chainIDs := config.UniqueStrings{} for i, c := range cs { if chainIDs.IsDupe(c.ChainID) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) + errA = append(errA, config.NewErrDuplicate(fmt.Sprintf("%d.ChainID", i), *c.ChainID)) } } @@ -34,7 +36,7 @@ func (cs TOMLConfigs) validateKeys() (err error) { for i, c := range cs { for j, n := range c.Nodes { if names.IsDupe(n.Name) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) + errA = append(errA, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.Name", i, j), *n.Name)) } } } @@ -45,11 +47,11 @@ func (cs TOMLConfigs) validateKeys() (err error) { for j, n := range c.Nodes { u := (*url.URL)(n.URL) if urls.IsDupeFmt(u) { - err = errors.Join(err, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) + errA = append(errA, config.NewErrDuplicate(fmt.Sprintf("%d.Nodes.%d.URL", i, j), u.String())) } } } - return + return errors.Join(errA...) } func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) (err error) { @@ -179,16 +181,18 @@ func setFromChain(c, f *Chain) { } func (c *TOMLConfig) ValidateConfig() (err error) { + errA := []error{} + if c.ChainID == nil { - err = errors.Join(err, config.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) + errA = append(errA, config.ErrMissing{Name: "ChainID", Msg: "required for all chains"}) } else if *c.ChainID == "" { - err = errors.Join(err, config.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) + errA = append(errA, config.ErrEmpty{Name: "ChainID", Msg: "required for all chains"}) } if len(c.Nodes) == 0 { - err = errors.Join(err, config.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) + errA = append(errA, config.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) } - return + return errors.Join(errA...) } func (c *TOMLConfig) TOMLString() (string, error) { From 431889be85feacff53e2cbd315b9486c027c2c9a Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Wed, 22 May 2024 17:12:30 -0600 Subject: [PATCH 12/15] nobuild optimization for running gauntlet within e2e tests --- gauntlet/package.json | 1 + integration-tests/gauntlet/gauntlet_solana.go | 56 ++++++++++++------- integration-tests/smoke/ocr2_test.go | 2 + 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/gauntlet/package.json b/gauntlet/package.json index c71817d41..84485cf22 100644 --- a/gauntlet/package.json +++ b/gauntlet/package.json @@ -14,6 +14,7 @@ "bin": "packages/gauntlet-solana-contracts/dist/cli.js", "scripts": { "gauntlet": "yarn build && node ./packages/gauntlet-solana-contracts/dist/cli.js", + "gauntlet-nobuild": "node ./packages/gauntlet-solana-contracts/dist/cli.js", "gauntlet-serum-multisig": "yarn build && node ./packages/gauntlet-serum-multisig/dist/index.js", "lint": "tsc -b ./tsconfig.json", "eslint": "eslint -f json -o eslint-report.json ./packages || true", diff --git a/integration-tests/gauntlet/gauntlet_solana.go b/integration-tests/gauntlet/gauntlet_solana.go index c4f8bcb59..f7e088f10 100644 --- a/integration-tests/gauntlet/gauntlet_solana.go +++ b/integration-tests/gauntlet/gauntlet_solana.go @@ -121,12 +121,31 @@ func (sg *SolanaGauntlet) InstallDependencies() error { if err != nil { return err } - sg.G.Command = "gauntlet" + _, err = sg.G.ExecCommand([]string{"build"}, *sg.options) // initial build + if err != nil { + return err + } + sg.G.Command = "gauntlet-nobuild" // optimization to not rebuild packages each time return nil } +// exect is a custom wrapper to use custom set gauntlet command + error wrapping +func (sg *SolanaGauntlet) exec(args []string, options gauntlet.ExecCommandOptions) (string, error) { + updatedArgs := []string{sg.G.Command, args[0], sg.G.Flag("network", sg.G.Network)} + if len(args) > 1 { + updatedArgs = append(updatedArgs, args[1:]...) + } + + out, err := sg.G.ExecCommand(updatedArgs, options) + // wrapping output into err if err present + if err != nil { + err = fmt.Errorf("%w\ngauntlet command: %s\nstdout: %s", err, updatedArgs, out) + } + return out, err +} + func (sg *SolanaGauntlet) InitializeAccessController() (string, error) { - _, err := sg.G.ExecCommand([]string{"access_controller:initialize"}, *sg.options) + _, err := sg.exec([]string{"access_controller:initialize"}, *sg.options) if err != nil { return "", err } @@ -138,7 +157,7 @@ func (sg *SolanaGauntlet) InitializeAccessController() (string, error) { } func (sg *SolanaGauntlet) DeployLinkToken() error { - _, err := sg.G.ExecCommand([]string{"token:deploy"}, *sg.options) + _, err := sg.exec([]string{"token:deploy"}, *sg.options) if err != nil { return err } @@ -153,7 +172,7 @@ func (sg *SolanaGauntlet) DeployLinkToken() error { } func (sg *SolanaGauntlet) InitializeStore(billingController string) (string, error) { - _, err := sg.G.ExecCommand([]string{"store:initialize", fmt.Sprintf("--accessController=%s", billingController)}, *sg.options) + _, err := sg.exec([]string{"store:initialize", fmt.Sprintf("--accessController=%s", billingController)}, *sg.options) if err != nil { return "", err } @@ -169,7 +188,7 @@ func (sg *SolanaGauntlet) StoreCreateFeed(length int, feedConfig *ocr2_config.St if err != nil { return "", err } - _, err = sg.G.ExecCommand([]string{"store:create_feed", fmt.Sprintf("--length=%d", length), fmt.Sprintf("--input=%v", string(config))}, *sg.options) + _, err = sg.exec([]string{"store:create_feed", fmt.Sprintf("--length=%d", length), fmt.Sprintf("--input=%v", string(config))}, *sg.options) if err != nil { return "", err } @@ -182,7 +201,7 @@ func (sg *SolanaGauntlet) StoreCreateFeed(length int, feedConfig *ocr2_config.St } func (sg *SolanaGauntlet) StoreSetValidatorConfig(feedAddress string, threshold int) (string, error) { - _, err := sg.G.ExecCommand([]string{"store:set_validator_config", fmt.Sprintf("--feed=%s", feedAddress), fmt.Sprintf("--threshold=%d", threshold)}, *sg.options) + _, err := sg.exec([]string{"store:set_validator_config", fmt.Sprintf("--feed=%s", feedAddress), fmt.Sprintf("--threshold=%d", threshold)}, *sg.options) if err != nil { return "", err } @@ -198,7 +217,7 @@ func (sg *SolanaGauntlet) InitializeOCR2(requesterAccessController string, billi if err != nil { return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:initialize", fmt.Sprintf("--requesterAccessController=%s", requesterAccessController), fmt.Sprintf("--billingAccessController=%s", billingAccessController), @@ -219,7 +238,7 @@ func (sg *SolanaGauntlet) StoreSetWriter(storeConfig *ocr2_config.StoreWriterCon if err != nil { return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "store:set_writer", fmt.Sprintf("--input=%v", string(config)), ocrAddress, @@ -243,7 +262,7 @@ func (sg *SolanaGauntlet) OCR2SetBilling(ocr2BillingConfig *ocr2_config.OCR2Bill if err != nil { return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:set_billing", fmt.Sprintf("--input=%v", string(config)), ocrAddress, @@ -263,7 +282,7 @@ func (sg *SolanaGauntlet) OCR2SetBilling(ocr2BillingConfig *ocr2_config.OCR2Bill } func (sg *SolanaGauntlet) OCR2CreateProposal(version int) (string, error) { - _, err := sg.G.ExecCommand([]string{ + _, err := sg.exec([]string{ "ocr2:create_proposal", fmt.Sprintf("--version=%d", version), }, @@ -286,7 +305,7 @@ func (sg *SolanaGauntlet) ProposeOnChainConfig(proposalID string, onChainConfig if err != nil { return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:propose_config", fmt.Sprintf("--proposalId=%s", proposalID), fmt.Sprintf("--input=%v", string(config)), @@ -312,7 +331,7 @@ func (sg *SolanaGauntlet) ProposeOffChainConfig(proposalID string, offChainConfi return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:propose_offchain_config", fmt.Sprintf("--proposalId=%s", proposalID), fmt.Sprintf("--input=%v", string(config)), @@ -338,7 +357,7 @@ func (sg *SolanaGauntlet) ProposePayees(proposalID string, payeesConfig ocr2_con return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:propose_payees", fmt.Sprintf("--proposalId=%s", proposalID), fmt.Sprintf("--input=%v", string(config)), @@ -359,7 +378,7 @@ func (sg *SolanaGauntlet) ProposePayees(proposalID string, payeesConfig ocr2_con } func (sg *SolanaGauntlet) FinalizeProposal(proposalID string) (string, error) { - _, err := sg.G.ExecCommand([]string{ + _, err := sg.exec([]string{ "ocr2:finalize_proposal", fmt.Sprintf("--proposalId=%s", proposalID), }, @@ -383,7 +402,7 @@ func (sg *SolanaGauntlet) AcceptProposal(proposalID string, secret string, propo return "", err } - _, err = sg.G.ExecCommand([]string{ + _, err = sg.exec([]string{ "ocr2:accept_proposal", fmt.Sprintf("--proposalId=%s", proposalID), fmt.Sprintf("--secret=%s", secret), @@ -406,7 +425,7 @@ func (sg *SolanaGauntlet) AcceptProposal(proposalID string, secret string, propo // FetchTransmissions returns the last 10 transmissions func (sg *SolanaGauntlet) FetchTransmissions(ocrState string) ([]Transmission, error) { - _, err := sg.G.ExecCommand([]string{ + _, err := sg.exec([]string{ "ocr2:inspect:responses", ocrState, }, @@ -426,11 +445,6 @@ func (sg *SolanaGauntlet) FetchTransmissions(ocrState string) ([]Transmission, e func (sg *SolanaGauntlet) DeployOCR2() (string, error) { var err error - err = sg.InstallDependencies() - if err != nil { - return "", err - } - sg.AccessControllerAddress, err = sg.InitializeAccessController() if err != nil { return "", err diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index f9c4f09d6..645efb4b2 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -73,6 +73,8 @@ func TestSolanaOCRV2Smoke(t *testing.T) { err = sg.SetupNetwork(gauntletConfig) require.NoError(t, err, "Error setting gauntlet network") + err = sg.InstallDependencies() + require.NoError(t, err, "Error installing gauntlet dependencies") if *config.Common.Network == "devnet" { state.Common.ChainDetails.ProgramAddresses.OCR2 = *config.SolanaConfig.OCR2ProgramID From 76ce2a8ffccf1ef21f9b5dc09fb2481408960c18 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Wed, 22 May 2024 18:40:20 -0600 Subject: [PATCH 13/15] parallelize e2e tests --- integration-tests/gauntlet/gauntlet_solana.go | 7 +++---- integration-tests/smoke/ocr2_test.go | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/integration-tests/gauntlet/gauntlet_solana.go b/integration-tests/gauntlet/gauntlet_solana.go index f7e088f10..ef3884fe2 100644 --- a/integration-tests/gauntlet/gauntlet_solana.go +++ b/integration-tests/gauntlet/gauntlet_solana.go @@ -65,7 +65,6 @@ type Transmission struct { // NewSolanaGauntlet Creates a default gauntlet config func NewSolanaGauntlet(workingDir string) (*SolanaGauntlet, error) { g, err := gauntlet.NewGauntlet() - g.SetWorkingDir(workingDir) if err != nil { return nil, err } @@ -117,11 +116,11 @@ func (sg *SolanaGauntlet) SetupNetwork(args map[string]string) error { func (sg *SolanaGauntlet) InstallDependencies() error { sg.G.Command = "yarn" - _, err := sg.G.ExecCommand([]string{"install"}, *sg.options) + _, err := sg.G.ExecCommand([]string{"--cwd", sg.Dir, "install"}, *sg.options) if err != nil { return err } - _, err = sg.G.ExecCommand([]string{"build"}, *sg.options) // initial build + _, err = sg.G.ExecCommand([]string{"--cwd", sg.Dir, "build"}, *sg.options) // initial build if err != nil { return err } @@ -131,7 +130,7 @@ func (sg *SolanaGauntlet) InstallDependencies() error { // exect is a custom wrapper to use custom set gauntlet command + error wrapping func (sg *SolanaGauntlet) exec(args []string, options gauntlet.ExecCommandOptions) (string, error) { - updatedArgs := []string{sg.G.Command, args[0], sg.G.Flag("network", sg.G.Network)} + updatedArgs := []string{"--cwd", sg.Dir, sg.G.Command, args[0], sg.G.Flag("network", sg.G.Network)} if len(args) > 1 { updatedArgs = append(updatedArgs, args[1:]...) } diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 645efb4b2..77ca5d0fa 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -3,6 +3,7 @@ package smoke import ( "fmt" "maps" + "os/exec" "testing" "time" @@ -37,7 +38,10 @@ func TestSolanaOCRV2Smoke(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { - state, err := common.NewOCRv2State(t, 1, "gauntlet-"+test.name, &config) + t.Parallel() + + name := "gauntlet-" + test.name + state, err := common.NewOCRv2State(t, 1, name, &config) require.NoError(t, err, "Could not setup the ocrv2 state") if len(test.env) > 0 { state.Common.TestEnvDetails.NodeOpts = append(state.Common.TestEnvDetails.NodeOpts, func(n *test_env.ClNode) { @@ -50,7 +54,13 @@ func TestSolanaOCRV2Smoke(t *testing.T) { state.DeployCluster(utils.ContractsDir) - sg, err := gauntlet.NewSolanaGauntlet(fmt.Sprintf("%s/gauntlet", utils.ProjectRoot)) + // copy gauntlet folder to run in parallel (gauntlet generates an output file that is read by the e2e tests - causes conflict if shared) + gauntletCopyPath := utils.ProjectRoot + "/" + name + if out, cpErr := exec.Command("cp", "-r", utils.ProjectRoot+"/gauntlet", gauntletCopyPath).Output(); cpErr != nil { // nolint:gosec + require.NoError(t, err, "output: "+string(out)) + } + + sg, err := gauntlet.NewSolanaGauntlet(gauntletCopyPath) require.NoError(t, err) state.Gauntlet = sg From b7fa244e2720b901f150cbb7fcc8ca6713f01ca4 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Thu, 23 May 2024 11:07:35 -0600 Subject: [PATCH 14/15] reduce round count --- integration-tests/testconfig/default.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 525ef3de9..c6744a9c2 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -44,5 +44,5 @@ node_count = 6 test_duration = "50m" [OCR2.Smoke] -number_of_rounds = 5 +number_of_rounds = 2 From 6d111418062a72ebe82f86956a6aabbcd12128d6 Mon Sep 17 00:00:00 2001 From: aalu1418 <50029043+aalu1418@users.noreply.github.com> Date: Thu, 23 May 2024 11:32:03 -0600 Subject: [PATCH 15/15] add ticket to revisit errors.Join issue --- pkg/solana/config/toml.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index 4b865c8ae..96302a45d 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -21,7 +21,7 @@ func (cs TOMLConfigs) ValidateConfig() (err error) { } func (cs TOMLConfigs) validateKeys() (err error) { - errA := []error{} + errA := []error{} // goal: remove and go back to only errors.Join (https://smartcontract-it.atlassian.net/browse/BCI-3330) // Unique chain IDs chainIDs := config.UniqueStrings{}