Skip to content

Commit

Permalink
fix(nodes): use loadByRelayIDs for nodes and node query
Browse files Browse the repository at this point in the history
Nodes and node query only ever supported EVM, migrating to use `loadByRelayIDs` and make sure to set the network to EVM.

IF we do not migrate, if there is a duplicate in id between EVM and other network, it will return incorrect results worst case or an error best case.

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1151
  • Loading branch information
graham-chainlink committed Oct 17, 2024
1 parent 4d44d8b commit d93a55f
Show file tree
Hide file tree
Showing 6 changed files with 10 additions and 78 deletions.
5 changes: 5 additions & 0 deletions .changeset/honest-bugs-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#updated handle duplicate chain id in different network better
56 changes: 0 additions & 56 deletions core/web/loader/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package loader

import (
"context"
"slices"

"github.com/graph-gophers/dataloader"
commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types"
Expand All @@ -15,61 +14,6 @@ type chainBatcher struct {
app chainlink.Application
}

// DEPRECATED: loadByChainIDs is deprecated and we should be using loadByRelayIDs.
func (b *chainBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
// Create a map for remembering the order of keys passed in
keyOrder := make(map[string]int, len(keys))
// Collect the keys to search for
var chainIDs []string
for ix, key := range keys {
chainIDs = append(chainIDs, key.String())
keyOrder[key.String()] = ix
}

var cs []types.ChainStatusWithID
relayersMap, err := b.app.GetRelayers().GetIDToRelayerMap()
if err != nil {
return []*dataloader.Result{{Data: nil, Error: err}}
}

for k, v := range relayersMap {
s, err := v.GetChainStatus(ctx)
if err != nil {
return []*dataloader.Result{{Data: nil, Error: err}}
}

if slices.Contains(chainIDs, s.ID) {
cs = append(cs, types.ChainStatusWithID{
ChainStatus: s,
RelayID: k,
})
}
}

// todo: future improvements to handle multiple chains with same id
if len(cs) > len(keys) {
b.app.GetLogger().Warn("Found multiple chain with same id")
return []*dataloader.Result{{Data: nil, Error: chains.ErrMultipleChainFound}}
}

results := make([]*dataloader.Result, len(keys))
for _, c := range cs {
ix, ok := keyOrder[c.ID]
// if found, remove from index lookup map, so we know elements were found
if ok {
results[ix] = &dataloader.Result{Data: c, Error: nil}
delete(keyOrder, c.ID)
}
}

// fill array positions without any nodes
for _, ix := range keyOrder {
results[ix] = &dataloader.Result{Data: nil, Error: chains.ErrNotFound}
}

return results
}

func (b *chainBatcher) loadByRelayIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
results := make([]*dataloader.Result, 0, len(keys))
for _, key := range keys {
Expand Down
19 changes: 0 additions & 19 deletions core/web/loader/getters.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@ import (
// ErrInvalidType indicates that results loaded is not the type expected
var ErrInvalidType = errors.New("invalid type")

// GetChainByID fetches the chain by it's id.
// DEPRECATED: use GetChainByRelayID.
func GetChainByID(ctx context.Context, id string) (*commonTypes.ChainStatusWithID, error) {
ldr := For(ctx)

thunk := ldr.ChainsByIDLoader.Load(ctx, dataloader.StringKey(id))
result, err := thunk()
if err != nil {
return nil, err
}

chain, ok := result.(commonTypes.ChainStatusWithID)
if !ok {
return nil, ErrInvalidType
}

return &chain, nil
}

// GetChainByRelayID fetches the chain by it's relayId.
func GetChainByRelayID(ctx context.Context, id string) (*commonTypes.ChainStatusWithID, error) {
ldr := For(ctx)
Expand Down
2 changes: 0 additions & 2 deletions core/web/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type loadersKey struct{}
type Dataloader struct {
app chainlink.Application

ChainsByIDLoader *dataloader.Loader
ChainsByRelayIDLoader *dataloader.Loader
EthTxAttemptsByEthTxIDLoader *dataloader.Loader
FeedsManagersByIDLoader *dataloader.Loader
Expand Down Expand Up @@ -45,7 +44,6 @@ func New(app chainlink.Application) *Dataloader {
return &Dataloader{
app: app,

ChainsByIDLoader: dataloader.NewBatchedLoader(chains.loadByIDs),
ChainsByRelayIDLoader: dataloader.NewBatchedLoader(chains.loadByRelayIDs),
EthTxAttemptsByEthTxIDLoader: dataloader.NewBatchedLoader(attmpts.loadByEthTransactionIDs),
FeedsManagersByIDLoader: dataloader.NewBatchedLoader(mgrs.loadByIDs),
Expand Down
4 changes: 3 additions & 1 deletion core/web/resolver/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/graph-gophers/graphql-go"
"github.com/pelletier/go-toml/v2"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"

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

Expand Down Expand Up @@ -88,7 +89,8 @@ func (r *NodeResolver) Order() *int32 {

// Chain resolves the node's chain object field.
func (r *NodeResolver) Chain(ctx context.Context) (*ChainResolver, error) {
chain, err := loader.GetChainByID(ctx, r.status.ChainID)
relayID := types.NewRelayID(relay.NetworkEVM, r.status.ChainID)
chain, err := loader.GetChainByRelayID(ctx, relayID.Name())
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions core/web/resolver/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ func (r *Resolver) Features(ctx context.Context) (*FeaturesPayloadResolver, erro
}

// Node retrieves a node by ID (Name)
// only supports EVM chains
func (r *Resolver) Node(ctx context.Context, args struct{ ID graphql.ID }) (*NodePayloadResolver, error) {
if err := authenticateUser(ctx); err != nil {
return nil, err
Expand Down Expand Up @@ -378,6 +379,7 @@ func (r *Resolver) JobProposal(ctx context.Context, args struct {
}

// Nodes retrieves a paginated list of nodes.
// only supports EVM chains
func (r *Resolver) Nodes(ctx context.Context, args struct {
Offset *int32
Limit *int32
Expand Down

0 comments on commit d93a55f

Please sign in to comment.