Skip to content

Commit

Permalink
capabilities: Move evm specific code inside the relayer
Browse files Browse the repository at this point in the history
  • Loading branch information
archseer committed May 29, 2024
1 parent 86ed2b2 commit e922329
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 113 deletions.
70 changes: 5 additions & 65 deletions core/capabilities/targets/write_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,33 @@ 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

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_race_tests)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / lint

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_fuzz)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Flakey Test Detection

undefined: commontypes.ChainWriter

Check failure on line 25 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Analyze go

undefined: commontypes.ChainWriter
forwarderAddress string
capabilities.CapabilityInfo
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 {

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_race_tests)

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / lint

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_fuzz)

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Core Tests (go_core_tests)

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Flakey Test Detection

undefined: commontypes.ChainWriter

Check failure on line 31 in core/capabilities/targets/write_target.go

View workflow job for this annotation

GitHub Actions / Analyze go

undefined: commontypes.ChainWriter
info := capabilities.MustNewCapabilityInfo(
name,
capabilities.CapabilityTypeTarget,
Expand All @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion core/services/chainlink/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions core/services/chainlink/relayer_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
72 changes: 72 additions & 0 deletions core/services/relay/evm/write_target.go
Original file line number Diff line number Diff line change
@@ -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
}
53 changes: 6 additions & 47 deletions core/services/workflows/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit e922329

Please sign in to comment.