-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: multichain ocr3 contract transmitter #11672
Closed
Closed
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
fc7a508
feat: multichain ocr3 contract transmitter
makramkd 42d4b21
make FromAccount() return a hex-ified address
makramkd 323b36b
address PR comments
makramkd 8a2d9bc
Revert "make FromAccount() return a hex-ified address"
makramkd 8dfb0e9
add ocr3 base
makramkd 7f482a9
add multichain config tracker
makramkd 3f664f0
don't fetch follower configs in LatestConfigDetails
makramkd dd5f024
fix comments
makramkd 5c97655
call RPC for latest config details
makramkd 0044ec5
add contract transmitter test
makramkd c18cf25
add multichain transmitter test
makramkd ee936ea
add some config tracker tests
makramkd f0549a9
fix linting errors
makramkd aed6d45
fix solhint
makramkd 6a275c7
add multichain config tracker test
makramkd b097ae8
goimports
makramkd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package evm | ||
|
||
import ( | ||
"context" | ||
"encoding/binary" | ||
"encoding/hex" | ||
"fmt" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
gethcommon "github.com/ethereum/go-ethereum/common" | ||
"github.com/pkg/errors" | ||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" | ||
"github.com/smartcontractkit/chainlink/v2/core/logger" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/types" | ||
) | ||
|
||
var _ ocr3types.ContractTransmitter[any] = &contractTransmitterOCR3[any]{} | ||
|
||
type contractTransmitterOCR3[RI any] struct { | ||
contractAddress gethcommon.Address | ||
contractABI abi.ABI | ||
transmitter Transmitter | ||
transmittedEventSig gethcommon.Hash | ||
lp logpoller.LogPoller | ||
lggr logger.Logger | ||
reportToEvmTxMeta ReportToEthMetadata | ||
} | ||
|
||
func NewOCR3ContractTransmitter[RI any]( | ||
address gethcommon.Address, | ||
contractABI abi.ABI, | ||
transmitter Transmitter, | ||
lp logpoller.LogPoller, | ||
lggr logger.Logger, | ||
reportToEvmTxMeta ReportToEthMetadata, | ||
) (*contractTransmitterOCR3[RI], error) { | ||
transmitted, ok := contractABI.Events["Transmitted"] | ||
if !ok { | ||
return nil, fmt.Errorf("abi missing Transmitted event") | ||
} | ||
|
||
err := lp.RegisterFilter(logpoller.Filter{ | ||
Name: transmitterFilterName(address), | ||
EventSigs: []gethcommon.Hash{transmitted.ID}, | ||
Addresses: []gethcommon.Address{address}, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
makramkd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if reportToEvmTxMeta == nil { | ||
reportToEvmTxMeta = reportToEvmTxMetaNoop | ||
} | ||
return &contractTransmitterOCR3[RI]{ | ||
contractAddress: address, | ||
contractABI: contractABI, | ||
transmitter: transmitter, | ||
transmittedEventSig: transmitted.ID, | ||
lp: lp, | ||
lggr: lggr, | ||
reportToEvmTxMeta: reportToEvmTxMeta, | ||
}, nil | ||
} | ||
|
||
// FromAccount implements ocr3types.ContractTransmitter. | ||
func (c *contractTransmitterOCR3[RI]) FromAccount() (types.Account, error) { | ||
return types.Account(c.transmitter.FromAddress().Hex()), nil | ||
} | ||
|
||
// Transmit implements ocr3types.ContractTransmitter. | ||
func (c *contractTransmitterOCR3[RI]) Transmit(ctx context.Context, configDigest types.ConfigDigest, seqNum uint64, rwi ocr3types.ReportWithInfo[RI], sigs []types.AttributedOnchainSignature) error { | ||
var rs [][32]byte | ||
var ss [][32]byte | ||
var vs [32]byte | ||
if len(sigs) > 32 { | ||
return errors.New("too many signatures, maximum is 32") | ||
} | ||
for i, as := range sigs { | ||
r, s, v, err := evmutil.SplitSignature(as.Signature) | ||
if err != nil { | ||
panic("eventTransmit(ev): error in SplitSignature") | ||
dimkouv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
rs = append(rs, r) | ||
ss = append(ss, s) | ||
vs[i] = v | ||
} | ||
|
||
// report ctx for OCR3 consists of the following | ||
// reportContext[0]: ConfigDigest | ||
// reportContext[1]: 24 byte padding, 8 byte sequence number | ||
// reportContext[2]: unused | ||
var rawReportCtx [3][32]byte | ||
copy(rawReportCtx[0][:], configDigest[:]) | ||
binary.BigEndian.PutUint64(rawReportCtx[1][24:], seqNum) | ||
makramkd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
txMeta, err := c.reportToEvmTxMeta(rwi.Report) | ||
if err != nil { | ||
c.lggr.Warnw("failed to generate tx metadata for report", "err", err) | ||
} | ||
|
||
c.lggr.Debugw("Transmitting report", "report", hex.EncodeToString(rwi.Report), "rawReportCtx", rawReportCtx, "contractAddress", c.contractAddress, "txMeta", txMeta) | ||
|
||
payload, err := c.contractABI.Pack("transmit", rawReportCtx, []byte(rwi.Report), rs, ss, vs) | ||
if err != nil { | ||
return errors.Wrapf(err, "abi.Pack failed with args: (%v, %s, %v, %v, %v)", rawReportCtx, hex.EncodeToString(rwi.Report), rs, ss, vs) | ||
makramkd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return errors.Wrap(c.transmitter.CreateEthTransaction(ctx, c.contractAddress, payload, txMeta), "failed to send Eth transaction") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package evm | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" | ||
"github.com/smartcontractkit/chainlink/v2/core/logger" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/types" | ||
) | ||
|
||
type MultichainMeta interface { | ||
GetDestinationChainID() string | ||
} | ||
|
||
type multichainTransmitterOCR3[RI MultichainMeta] struct { | ||
transmitters map[string]ocr3types.ContractTransmitter[RI] | ||
lp logpoller.LogPoller | ||
lggr logger.Logger | ||
} | ||
|
||
func NewMultichainTransmitterOCR3[RI MultichainMeta]( | ||
transmitters map[string]ocr3types.ContractTransmitter[RI], | ||
lp logpoller.LogPoller, | ||
lggr logger.Logger, | ||
) (*multichainTransmitterOCR3[RI], error) { | ||
return &multichainTransmitterOCR3[RI]{ | ||
transmitters: transmitters, | ||
lp: lp, | ||
lggr: lggr, | ||
}, nil | ||
} | ||
|
||
// FromAccount implements ocr3types.ContractTransmitter. | ||
func (m *multichainTransmitterOCR3[RI]) FromAccount() (types.Account, error) { | ||
makramkd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var accounts []string | ||
for _, t := range m.transmitters { | ||
account, err := t.FromAccount() | ||
if err != nil { | ||
return "", err | ||
} | ||
accounts = append(accounts, string(account)) | ||
} | ||
return types.Account(strings.Join(accounts, ",")), nil | ||
} | ||
|
||
// Transmit implements ocr3types.ContractTransmitter. | ||
func (m *multichainTransmitterOCR3[RI]) Transmit(ctx context.Context, configDigest types.ConfigDigest, seqNr uint64, rwi ocr3types.ReportWithInfo[RI], sigs []types.AttributedOnchainSignature) error { | ||
transmitter, ok := m.transmitters[rwi.Info.GetDestinationChainID()] | ||
if !ok { | ||
return fmt.Errorf("no transmitter for chain %s", rwi.Info.GetDestinationChainID()) | ||
} | ||
return transmitter.Transmit(ctx, configDigest, seqNr, rwi, sigs) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will never be Unregistered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do unregisters need to happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @reductionista