diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 0363f4ba23a..d71ee5dd4b2 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -2,32 +2,25 @@ package targets import ( "context" - "encoding/json" "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/loop" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) var ( _ capabilities.ActionCapability = &WriteTarget{} ) +// NOTE: this code will be moved into chainlink-common once fully abstracted + type WriteTarget struct { - relayer loop.Relayer cr commontypes.ContractReader cw commontypes.ChainWriter forwarderAddress string @@ -35,14 +28,7 @@ type WriteTarget struct { lggr logger.Logger } -func NewEvmWriteTarget(ctx context.Context, relayer loop.Relayer, chain legacyevm.Chain, lggr logger.Logger) (*WriteTarget, error) { - // generate ID based on chain selector - name := fmt.Sprintf("write_%v", chain.ID()) - chainName, err := chainselectors.NameFromChainId(chain.ID().Uint64()) - if err == nil { - name = fmt.Sprintf("write_%v", chainName) - } - +func NewWriteTarget(lggr logger.Logger, name string, cr commontypes.ContractReader, cw commontypes.ChainWriter, forwarderAddress string) *WriteTarget { info := capabilities.MustNewCapabilityInfo( name, capabilities.CapabilityTypeTarget, @@ -51,61 +37,15 @@ func NewEvmWriteTarget(ctx context.Context, relayer loop.Relayer, chain legacyev nil, ) - // EVM-specific init - config := chain.Config().EVM().ChainWriter() - - // Initialize a reader to check whether a value was already transmitted on chain - contractReaderConfigEncoded, err := json.Marshal(relayevmtypes.ChainReaderConfig{ - Contracts: map[string]relayevmtypes.ChainContractReader{ - "forwarder": { - ContractABI: forwarder.KeystoneForwarderABI, - Configs: map[string]*relayevmtypes.ChainReaderDefinition{ - "getTransmitter": { - ChainSpecificName: "getTransmitter", - }, - }, - }, - }, - }) - if err != nil { - return nil, fmt.Errorf("failed to marshal contract reader config %v", err) - } - cr, err := relayer.NewContractReader(ctx, contractReaderConfigEncoded) - if err != nil { - return nil, err - } - cr.Bind(ctx, []commontypes.BoundContract{{ - Address: config.ForwarderAddress().String(), - Name: "forwarder", - }}) - logger := lggr.Named("WriteTarget") - chainWriterConfig := relayevmtypes.ChainWriterConfig{ - Contracts: map[string]relayevmtypes.ChainWriter{ - "forwarder": { - ContractABI: forwarder.KeystoneForwarderABI, - Configs: map[string]*relayevmtypes.ChainWriterDefinition{ - "report": { - ChainSpecificName: "report", - Checker: "simulate", - FromAddress: config.FromAddress().Address(), - GasLimit: 200_000, - }, - }, - }, - }, - } - cw := evm.NewChainWriterService(logger, chain.Client(), chain.TxManager(), chainWriterConfig) - return &WriteTarget{ - relayer, cr, cw, - config.ForwarderAddress().String(), + forwarderAddress, info, logger, - }, nil + } } type EvmConfig struct { diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index c0ed37a7b5d..3eeaaa880ed 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -395,7 +395,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { delegates[job.Workflow] = workflows.NewDelegate( globalLogger, opts.CapabilitiesRegistry, - opts.RelayerChainInteroperators, workflowORM, func() *p2ptypes.PeerID { if externalPeerWrapper == nil { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index bcdb08b8026..7eeec781b03 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -84,6 +84,15 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } relayers[relayID] = evmrelay.NewLoopRelayServerAdapter(relayer, ext) + + // Initialize write target capability + capability, err := evmrelay.NewWriteTarget(ctx, relayer, chain, lggr) + if err != nil { + return nil, fmt.Errorf("failed to initialize write target: %w", err) + } + if err := r.CapabilitiesRegistry.Add(ctx, capability); err != nil { + return nil, err + } } // always return err because it is accumulating individual errors diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go new file mode 100644 index 00000000000..def575390be --- /dev/null +++ b/core/services/relay/evm/write_target.go @@ -0,0 +1,72 @@ +package evm + +import ( + "context" + "encoding/json" + "fmt" + + chainselectors "github.com/smartcontractkit/chain-selectors" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/logger" + relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, lggr logger.Logger) (*targets.WriteTarget, error) { + // generate ID based on chain selector + name := fmt.Sprintf("write_%v", chain.ID()) + chainName, err := chainselectors.NameFromChainId(chain.ID().Uint64()) + if err == nil { + name = fmt.Sprintf("write_%v", chainName) + } + + // EVM-specific init + config := chain.Config().EVM().ChainWriter() + + // Initialize a reader to check whether a value was already transmitted on chain + contractReaderConfigEncoded, err := json.Marshal(relayevmtypes.ChainReaderConfig{ + Contracts: map[string]relayevmtypes.ChainContractReader{ + "forwarder": { + ContractABI: forwarder.KeystoneForwarderABI, + Configs: map[string]*relayevmtypes.ChainReaderDefinition{ + "getTransmitter": { + ChainSpecificName: "getTransmitter", + }, + }, + }, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to marshal contract reader config %v", err) + } + cr, err := relayer.NewContractReader(contractReaderConfigEncoded) + if err != nil { + return nil, err + } + cr.Bind(ctx, []commontypes.BoundContract{{ + Address: config.ForwarderAddress().String(), + Name: "forwarder", + }}) + + chainWriterConfig := relayevmtypes.ChainWriterConfig{ + Contracts: map[string]relayevmtypes.ChainWriter{ + "forwarder": { + ContractABI: forwarder.KeystoneForwarderABI, + Configs: map[string]*relayevmtypes.ChainWriterDefinition{ + "report": { + ChainSpecificName: "report", + Checker: "simulate", + FromAddress: config.FromAddress().Address(), + GasLimit: 200_000, + }, + }, + }, + }, + } + cw := NewChainWriterService(lggr.Named("ChainWriter"), chain.Client(), chain.TxManager(), chainWriterConfig) + + return targets.NewWriteTarget(lggr, name, cr, cw, config.ForwarderAddress().String()), nil +} diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index ae555746303..ad51ee41cb2 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -9,28 +9,18 @@ import ( "github.com/pelletier/go-toml" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/core" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) -type RelayGetter interface { - GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) - LegacyEVMChains() legacyevm.LegacyChainContainer -} - type Delegate struct { - registry core.CapabilitiesRegistry - logger logger.Logger - relayGetter RelayGetter - peerID func() *p2ptypes.PeerID - store store.Store + registry core.CapabilitiesRegistry + logger logger.Logger + peerID func() *p2ptypes.PeerID + store store.Store } var _ job.Delegate = (*Delegate)(nil) @@ -47,39 +37,8 @@ func (d *Delegate) BeforeJobDeleted(spec job.Job) {} func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } -func InitializeWriteTargets(ctx context.Context, registry core.CapabilitiesRegistry, relayGetter RelayGetter, lggr logger.Logger) error { - legacyChains := relayGetter.LegacyEVMChains() - relayers, err := relayGetter.GetIDToRelayerMap() - if err != nil { - return fmt.Errorf("failed to get relayers: %w", err) - } - - for id, relayer := range relayers { - if id.Network != types.NetworkEVM { - continue // only EVM supported for now - } - chain, err := legacyChains.Get(id.ChainID) - if err != nil { - return fmt.Errorf("failed to get chain: %w", err) - } - capability, err := targets.NewWriteTarget(ctx, relayer, chain, lggr) - if err != nil { - return fmt.Errorf("failed to initialize write target: %w", err) - } - if err := registry.Add(ctx, capability); err != nil { - return err - } - } - return nil -} - // ServicesForSpec satisfies the job.Delegate interface. func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.ServiceCtx, error) { - // NOTE: we temporarily do registration inside ServicesForSpec, this will be moved out of job specs in the future - if err := InitializeWriteTargets(ctx, d.registry, d.relayGetter, d.logger); err != nil { - d.logger.Errorw("could not initialize writes", err) - } - dinfo, err := initializeDONInfo(d.logger) if err != nil { d.logger.Errorw("could not add initialize don info", err) @@ -139,8 +98,8 @@ func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { } -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, relayGetter RelayGetter, store store.Store, peerID func() *p2ptypes.PeerID) *Delegate { - return &Delegate{logger: logger, registry: registry, relayGetter: relayGetter, store: store, peerID: peerID} +func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, store store.Store, peerID func() *p2ptypes.PeerID) *Delegate { + return &Delegate{logger: logger, registry: registry, store: store, peerID: peerID} } func ValidatedWorkflowSpec(tomlString string) (job.Job, error) {