Skip to content

Commit

Permalink
Merge branch 'update-secondary-transmission-method-signature' into tx…
Browse files Browse the repository at this point in the history
…mv2-with-dual-transmission
  • Loading branch information
george-dorin committed Nov 29, 2024
2 parents 4001522 + e8058f8 commit 895ff1d
Show file tree
Hide file tree
Showing 9 changed files with 575 additions and 86 deletions.
6 changes: 6 additions & 0 deletions core/services/ocr2/plugins/ccip/transmitter/transmitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type txManager interface {
type Transmitter interface {
CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error
FromAddress(context.Context) common.Address

CreateSecondaryEthTransaction(context.Context, []byte, *txmgr.TxMeta) error
}

type transmitter struct {
Expand Down Expand Up @@ -141,3 +143,7 @@ func (t *transmitter) forwarderAddress() common.Address {
}
return t.effectiveTransmitterAddress
}

func (t *transmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error {
return errors.New("trying to send a secondary transmission on a non dual transmitter")
}
134 changes: 134 additions & 0 deletions core/services/ocrcommon/dual_transmittrer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package ocrcommon

import (
"context"
"math/big"
"net/url"
"slices"

"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"

"github.com/smartcontractkit/chainlink/v2/common/txmgr/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
)

type ocr2FeedsDualTransmission struct {
txm txManager
primaryFromAddresses []common.Address
gasLimit uint64
primaryEffectiveTransmitterAddress common.Address
strategy types.TxStrategy
checker txmgr.TransmitCheckerSpec
chainID *big.Int
keystore roundRobinKeystore

ocr2Aggregator common.Address
txManagerOCR2

secondaryContractAddress common.Address
secondaryFromAddress common.Address
secondaryMeta map[string][]string
}

func (t *ocr2FeedsDualTransmission) forwarderAddress(ctx context.Context, eoa, ocr2Aggregator common.Address) (common.Address, error) {
// If effectiveTransmitterAddress is in fromAddresses, then forwarders aren't set.
if slices.Contains(t.primaryFromAddresses, t.primaryEffectiveTransmitterAddress) {
return common.Address{}, nil
}

forwarderAddress, err := t.GetForwarderForEOAOCR2Feeds(ctx, eoa, ocr2Aggregator)
if err != nil {
return common.Address{}, err
}

// if forwarder address is in fromAddresses, then none of the forwarders are valid
if slices.Contains(t.primaryFromAddresses, forwarderAddress) {
forwarderAddress = common.Address{}
}

return forwarderAddress, nil
}

func (t *ocr2FeedsDualTransmission) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error {
roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.primaryFromAddresses...)
if err != nil {
return errors.Wrap(err, "skipped OCR transmission, error getting round-robin address")
}

forwarderAddress, err := t.forwarderAddress(ctx, roundRobinFromAddress, toAddress)
if err != nil {
return err
}

_, err = t.txm.CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: roundRobinFromAddress,
ToAddress: toAddress,
EncodedPayload: payload,
FeeLimit: t.gasLimit,
ForwarderAddress: forwarderAddress,
Strategy: t.strategy,
Checker: t.checker,
Meta: txMeta,
})

return errors.Wrap(err, "skipped OCR transmission: skipped primary transmission")
}

func (t *ocr2FeedsDualTransmission) CreateSecondaryEthTransaction(ctx context.Context, payload []byte, txMeta *txmgr.TxMeta) error {
forwarderAddress, err := t.forwarderAddress(ctx, t.secondaryFromAddress, t.secondaryContractAddress)
if err != nil {
return err
}

if txMeta == nil {
txMeta = &txmgr.TxMeta{}
}

dualBroadcast := true
dualBroadcastParams := t.urlParams()

txMeta.DualBroadcast = &dualBroadcast
txMeta.DualBroadcastParams = &dualBroadcastParams

_, err = t.txm.CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: t.secondaryFromAddress,
ToAddress: t.secondaryContractAddress,
EncodedPayload: payload,
ForwarderAddress: forwarderAddress,
FeeLimit: t.gasLimit,
Strategy: t.strategy,
Checker: t.checker,
Meta: txMeta,
})

return errors.Wrap(err, "skipped secondary transmission")
}

func (t *ocr2FeedsDualTransmission) FromAddress(ctx context.Context) common.Address {
roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.primaryFromAddresses...)
if err != nil {
return t.primaryEffectiveTransmitterAddress
}

forwarderAddress, err := t.GetForwarderForEOAOCR2Feeds(ctx, roundRobinFromAddress, t.ocr2Aggregator)
if errors.Is(err, forwarders.ErrForwarderForEOANotFound) {
// if there are no valid forwarders try to fallback to eoa
return roundRobinFromAddress
} else if err != nil {
return t.primaryEffectiveTransmitterAddress
}

return forwarderAddress
}

func (t *ocr2FeedsDualTransmission) urlParams() string {
values := url.Values{}
for k, v := range t.secondaryMeta {
for _, p := range v {
values.Add(k, p)
}
}
return values.Encode()
}
94 changes: 27 additions & 67 deletions core/services/ocrcommon/transmitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package ocrcommon

import (
"context"
errors2 "errors"
"fmt"
"math/big"
"net/url"
"slices"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -28,6 +25,8 @@ type txManager interface {
type Transmitter interface {
CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error
FromAddress(context.Context) common.Address

CreateSecondaryEthTransaction(context.Context, []byte, *txmgr.TxMeta) error
}

type transmitter struct {
Expand Down Expand Up @@ -99,7 +98,24 @@ func NewOCR2FeedsTransmitter(
return nil, errors.New("nil keystore provided to transmitter")
}

baseTransmitter := &ocr2FeedsTransmitter{
if dualTransmissionConfig != nil {
return &ocr2FeedsDualTransmission{
ocr2Aggregator: ocr2Aggregator,
txm: txm,
txManagerOCR2: txm,
primaryFromAddresses: fromAddresses,
gasLimit: gasLimit,
primaryEffectiveTransmitterAddress: effectiveTransmitterAddress,
strategy: strategy,
checker: checker,
chainID: chainID,
keystore: keystore,
secondaryContractAddress: dualTransmissionConfig.ContractAddress,
secondaryFromAddress: dualTransmissionConfig.TransmitterAddress,
secondaryMeta: dualTransmissionConfig.Meta,
}, nil
}
return &ocr2FeedsTransmitter{
ocr2Aggregator: ocr2Aggregator,
txManagerOCR2: txm,
transmitter: transmitter{
Expand All @@ -112,17 +128,7 @@ func NewOCR2FeedsTransmitter(
chainID: chainID,
keystore: keystore,
},
}

if dualTransmissionConfig != nil {
return &ocr2FeedsDualTransmission{
transmitter: *baseTransmitter,
secondaryContractAddress: dualTransmissionConfig.ContractAddress,
secondaryFromAddress: dualTransmissionConfig.TransmitterAddress,
secondaryMeta: dualTransmissionConfig.Meta,
}, nil
}
return baseTransmitter, nil
}, nil
}

func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error {
Expand All @@ -144,6 +150,10 @@ func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common
return errors.Wrap(err, "skipped OCR transmission")
}

func (t *transmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error {
return errors.New("trying to send a secondary transmission on a non dual transmitter")
}

func (t *transmitter) FromAddress(context.Context) common.Address {
return t.effectiveTransmitterAddress
}
Expand Down Expand Up @@ -219,56 +229,6 @@ func (t *ocr2FeedsTransmitter) forwarderAddress(ctx context.Context, eoa, ocr2Ag
return forwarderAddress, nil
}

type ocr2FeedsDualTransmission struct {
transmitter ocr2FeedsTransmitter

secondaryContractAddress common.Address
secondaryFromAddress common.Address
secondaryMeta map[string][]string
}

func (t *ocr2FeedsDualTransmission) CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error {
// Primary transmission
errPrimary := t.transmitter.CreateEthTransaction(ctx, toAddress, payload, txMeta)
if errPrimary != nil {
errPrimary = fmt.Errorf("skipped primary transmission: %w", errPrimary)
}

if txMeta == nil {
txMeta = &txmgr.TxMeta{}
}

dualBroadcast := true
dualBroadcastParams := t.urlParams()

txMeta.DualBroadcast = &dualBroadcast
txMeta.DualBroadcastParams = &dualBroadcastParams

// Secondary transmission
_, errSecondary := t.transmitter.txm.CreateTransaction(ctx, txmgr.TxRequest{
FromAddress: t.secondaryFromAddress,
ToAddress: t.secondaryContractAddress,
EncodedPayload: payload,
FeeLimit: t.transmitter.gasLimit,
Strategy: t.transmitter.strategy,
Checker: t.transmitter.checker,
Meta: txMeta,
})

errSecondary = errors.Wrap(errSecondary, "skipped secondary transmission")
return errors2.Join(errPrimary, errSecondary)
}

func (t *ocr2FeedsDualTransmission) FromAddress(ctx context.Context) common.Address {
return t.transmitter.FromAddress(ctx)
}

func (t *ocr2FeedsDualTransmission) urlParams() string {
values := url.Values{}
for k, v := range t.secondaryMeta {
for _, p := range v {
values.Add(k, p)
}
}
return values.Encode()
func (t *ocr2FeedsTransmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error {
return errors.New("trying to send a secondary transmission on a non dual transmitter")
}
1 change: 1 addition & 0 deletions core/services/ocrcommon/transmitter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ func Test_DualTransmitter(t *testing.T) {
})).Twice().Return(txmgr.Tx{}, nil)

require.NoError(t, transmitter.CreateEthTransaction(testutils.Context(t), toAddress, payload, nil))
require.NoError(t, transmitter.CreateSecondaryEthTransaction(testutils.Context(t), payload, nil))

require.True(t, primaryTxConfirmed)
require.True(t, secondaryTxConfirmed)
Expand Down
Loading

0 comments on commit 895ff1d

Please sign in to comment.