Skip to content

Commit

Permalink
(feat): Copy common Transmitter into FunctionsContractTransmitter to …
Browse files Browse the repository at this point in the history
…enable product specific modifications
  • Loading branch information
justinkaseman committed Mar 25, 2024
1 parent 7dc21d9 commit 1a26544
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 62 deletions.
5 changes: 5 additions & 0 deletions .changeset/wet-turtles-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

Copy common transmitter methods into FunctionsContractTransmitter to enable product specific modification
23 changes: 7 additions & 16 deletions core/services/relay/evm/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions"
evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)
Expand Down Expand Up @@ -197,7 +196,13 @@ func newFunctionsContractTransmitter(ctx context.Context, contractVersion uint32
gasLimit = uint64(*ocr2Limit)
}

transmitter, err := ocrcommon.NewTransmitter(
functionsTransmitter, err := functionsRelay.NewFunctionsContractTransmitter(
configWatcher.chain.Client(),
OCR2AggregatorTransmissionContractABI,
configWatcher.chain.LogPoller(),
lggr,
nil,
contractVersion,
configWatcher.chain.TxManager(),
fromAddresses,
gasLimit,
Expand All @@ -207,20 +212,6 @@ func newFunctionsContractTransmitter(ctx context.Context, contractVersion uint32
configWatcher.chain.ID(),
ethKeystore,
)

if err != nil {
return nil, errors.Wrap(err, "failed to create transmitter")
}

functionsTransmitter, err := functionsRelay.NewFunctionsContractTransmitter(
configWatcher.chain.Client(),
OCR2AggregatorTransmissionContractABI,
transmitter,
configWatcher.chain.LogPoller(),
lggr,
nil,
contractVersion,
)
if err != nil {
return nil, err
}
Expand Down
113 changes: 86 additions & 27 deletions core/services/relay/evm/functions/contract_transmitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"

"github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils"
Expand All @@ -25,33 +26,43 @@ import (
evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)

type roundRobinKeystore interface {
GetRoundRobinAddress(ctx context.Context, chainID *big.Int, addresses ...common.Address) (address common.Address, err error)
}

type txManager interface {
CreateTransaction(ctx context.Context, txRequest txmgr.TxRequest) (tx txmgr.Tx, err error)
}

type FunctionsContractTransmitter interface {
services.ServiceCtx
ocrtypes.ContractTransmitter
}

type Transmitter interface {
CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error
FromAddress() common.Address
}

type ReportToEthMetadata func([]byte) (*txmgr.TxMeta, error)

func reportToEvmTxMetaNoop([]byte) (*txmgr.TxMeta, error) {
return nil, nil
}

type contractTransmitter struct {
contractAddress atomic.Pointer[common.Address]
contractABI abi.ABI
transmitter Transmitter
transmittedEventSig common.Hash
contractReader contractReader
lp logpoller.LogPoller
lggr logger.Logger
reportToEvmTxMeta ReportToEthMetadata
contractVersion uint32
reportCodec encoding.ReportCodec
contractAddress atomic.Pointer[common.Address]
contractABI abi.ABI
transmittedEventSig common.Hash
contractReader contractReader
lp logpoller.LogPoller
lggr logger.Logger
reportToEvmTxMeta ReportToEthMetadata
contractVersion uint32
reportCodec encoding.ReportCodec
txm txManager
fromAddresses []common.Address
gasLimit uint64
effectiveTransmitterAddress common.Address
strategy types.TxStrategy
checker txmgr.TransmitCheckerSpec
chainID *big.Int
keystore roundRobinKeystore
}

var _ FunctionsContractTransmitter = &contractTransmitter{}
Expand All @@ -64,12 +75,24 @@ func transmitterFilterName(addr common.Address) string {
func NewFunctionsContractTransmitter(
caller contractReader,
contractABI abi.ABI,
transmitter Transmitter,
lp logpoller.LogPoller,
lggr logger.Logger,
reportToEvmTxMeta ReportToEthMetadata,
contractVersion uint32,
txm txManager,
fromAddresses []common.Address,
gasLimit uint64,
effectiveTransmitterAddress common.Address,
strategy types.TxStrategy,
checker txmgr.TransmitCheckerSpec,
chainID *big.Int,
keystore roundRobinKeystore,
) (*contractTransmitter, error) {
// Ensure that a keystore is provided.
if keystore == nil {
return nil, errors.New("nil keystore provided to transmitter")
}

transmitted, ok := contractABI.Events["Transmitted"]
if !ok {
return nil, errors.New("invalid ABI, missing transmitted")
Expand All @@ -87,18 +110,54 @@ func NewFunctionsContractTransmitter(
return nil, err
}
return &contractTransmitter{
contractABI: contractABI,
transmitter: transmitter,
transmittedEventSig: transmitted.ID,
lp: lp,
contractReader: caller,
lggr: lggr.Named("OCRContractTransmitter"),
reportToEvmTxMeta: reportToEvmTxMeta,
contractVersion: contractVersion,
reportCodec: codec,
contractABI: contractABI,
transmittedEventSig: transmitted.ID,
lp: lp,
contractReader: caller,
lggr: lggr.Named("OCRContractTransmitter"),
reportToEvmTxMeta: reportToEvmTxMeta,
contractVersion: contractVersion,
reportCodec: codec,
txm: txm,
fromAddresses: fromAddresses,
gasLimit: gasLimit,
effectiveTransmitterAddress: effectiveTransmitterAddress,
strategy: strategy,
checker: checker,
chainID: chainID,
keystore: keystore,
}, nil
}

func (oc *contractTransmitter) createEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error {

roundRobinFromAddress, err := oc.keystore.GetRoundRobinAddress(ctx, oc.chainID, oc.fromAddresses...)
if err != nil {
return errors.Wrap(err, "skipped OCR transmission, error getting round-robin address")
}

_, err = oc.txm.CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: roundRobinFromAddress,
ToAddress: toAddress,
EncodedPayload: payload,
FeeLimit: oc.gasLimit,
ForwarderAddress: oc.forwarderAddress(),
Strategy: oc.strategy,
Checker: oc.checker,
Meta: txMeta,
})
return errors.Wrap(err, "skipped OCR transmission")
}

func (oc *contractTransmitter) forwarderAddress() common.Address {
for _, a := range oc.fromAddresses {
if a == oc.effectiveTransmitterAddress {
return common.Address{}
}
}
return oc.effectiveTransmitterAddress
}

// Transmit sends the report to the on-chain smart contract's Transmit method.
func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signatures []ocrtypes.AttributedOnchainSignature) error {
var rs [][32]byte
Expand Down Expand Up @@ -161,7 +220,7 @@ func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.
}

oc.lggr.Debugw("FunctionsContractTransmitter: transmitting report", "contractAddress", destinationContract, "txMeta", txMeta, "payloadSize", len(payload))
return errors.Wrap(oc.transmitter.CreateEthTransaction(ctx, destinationContract, payload, txMeta), "failed to send Eth transaction")
return errors.Wrap(oc.createEthTransaction(ctx, destinationContract, payload, txMeta), "failed to send Eth transaction")
}

type contractReader interface {
Expand Down Expand Up @@ -240,7 +299,7 @@ func (oc *contractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) (

// FromAccount returns the account from which the transmitter invokes the contract
func (oc *contractTransmitter) FromAccount() (ocrtypes.Account, error) {
return ocrtypes.Account(oc.transmitter.FromAddress().String()), nil
return ocrtypes.Account(oc.effectiveTransmitterAddress.String()), nil
}

func (oc *contractTransmitter) Start(ctx context.Context) error { return nil }
Expand Down
Loading

0 comments on commit 1a26544

Please sign in to comment.