Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import (

chainselectors "github.com/smartcontractkit/chain-selectors"
ocrcommon "github.com/smartcontractkit/libocr/commontypes"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2/types"
ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"

"github.com/smartcontractkit/chainlink-common/pkg/capabilities"
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/types/chains/solana"
"github.com/smartcontractkit/chainlink-common/pkg/types/core/securemint"
"github.com/smartcontractkit/chainlink-protos/cre/go/values"
)

Expand Down Expand Up @@ -60,28 +60,17 @@ const (
SolDataIDOutputFieldName = SolanaEncoderKey("dataId")
)

// secureMintReport represents the inner report structure, mimics the Report type in the SM plugin repo
type secureMintReport struct {
ConfigDigest ocr2types.ConfigDigest `json:"configDigest"`
SeqNr uint64 `json:"seqNr"`
Block uint64 `json:"block"`
Mintable *big.Int `json:"mintable"`
}

type wrappedMintReport struct {
Report secureMintReport `json:"report"`
Report securemint.Report `json:"report"`
SolanaAccountContext solana.AccountMetaSlice `json:"solanaAccountContext,omitempty"`
}

// chainSelector represents the chain selector type, mimics the ChainSelector type in the SM plugin repo
type chainSelector uint64

// SecureMintAggregatorConfig is the config for the SecureMint aggregator.
// This aggregator is designed to pick out reports for a specific chain selector.
type SecureMintAggregatorConfig struct {
// TargetChainSelector is the chain selector to look for
TargetChainSelector chainSelector `mapstructure:"targetChainSelector"`
DataID [16]byte `mapstructure:"dataID"`
TargetChainSelector securemint.ChainSelector `mapstructure:"targetChainSelector"`
DataID [16]byte `mapstructure:"dataID"`
}

// ToMap converts the SecureMintAggregatorConfig to a values.Map, which is suitable for the
Expand All @@ -107,13 +96,13 @@ type chainReportFormatter interface {
}

type evmReportFormatter struct {
targetChainSelector chainSelector
targetChainSelector securemint.ChainSelector
dataID [16]byte
}

func (f *evmReportFormatter) packReport(lggr logger.Logger, wreport *wrappedMintReport) (*values.Map, error) {
report := wreport.Report
smReportAsAnswer, err := packSecureMintReportIntoUint224ForEVM(report.Mintable, report.Block)
smReportAsAnswer, err := packSecureMintReportIntoUint224ForEVM(report.Mintable, uint64(report.Block))
if err != nil {
return nil, fmt.Errorf("failed to pack secure mint report for evm into uint224: %w", err)
}
Expand All @@ -140,19 +129,19 @@ func (f *evmReportFormatter) packReport(lggr logger.Logger, wreport *wrappedMint
return wrappedReport, nil
}

func newEVMReportFormatter(chainSelector chainSelector, config SecureMintAggregatorConfig) chainReportFormatter {
func newEVMReportFormatter(chainSelector securemint.ChainSelector, config SecureMintAggregatorConfig) chainReportFormatter {
return &evmReportFormatter{targetChainSelector: chainSelector, dataID: config.DataID}
}

type solanaReportFormatter struct {
targetChainSelector chainSelector
targetChainSelector securemint.ChainSelector
dataID [16]byte
}

func (f *solanaReportFormatter) packReport(lggr logger.Logger, wreport *wrappedMintReport) (*values.Map, error) {
report := wreport.Report
// pack answer
smReportAsAnswer, err := packSecureMintReportIntoU128ForSolana(report.Mintable, report.Block)
smReportAsAnswer, err := packSecureMintReportIntoU128ForSolana(report.Mintable, uint64(report.Block))
if err != nil {
return nil, fmt.Errorf("failed to pack secure mint report for solana into u128: %w", err)
}
Expand Down Expand Up @@ -191,24 +180,24 @@ func (f *solanaReportFormatter) packReport(lggr logger.Logger, wreport *wrappedM
return wrappedReport, nil
}

func newSolanaReportFormatter(chainSelector chainSelector, config SecureMintAggregatorConfig) chainReportFormatter {
func newSolanaReportFormatter(chainSelector securemint.ChainSelector, config SecureMintAggregatorConfig) chainReportFormatter {
return &solanaReportFormatter{targetChainSelector: chainSelector, dataID: config.DataID}
}

// chainReportFormatterBuilder is a function that returns a chainReportFormatter for a given chain selector and config
type chainReportFormatterBuilder func(chainSelector chainSelector, config SecureMintAggregatorConfig) chainReportFormatter
type chainReportFormatterBuilder func(chainSelector securemint.ChainSelector, config SecureMintAggregatorConfig) chainReportFormatter

type formatterFactory struct {
builders map[chainSelector]chainReportFormatterBuilder
builders map[securemint.ChainSelector]chainReportFormatterBuilder
}

// register registers a new chain report formatter builder for a given chain selector
func (r *formatterFactory) register(chSel chainSelector, builder chainReportFormatterBuilder) {
func (r *formatterFactory) register(chSel securemint.ChainSelector, builder chainReportFormatterBuilder) {
r.builders[chSel] = builder
}

// get uses a chain report formatter builder to create a chain report formatter
func (r *formatterFactory) get(chSel chainSelector, config SecureMintAggregatorConfig) (chainReportFormatter, error) {
func (r *formatterFactory) get(chSel securemint.ChainSelector, config SecureMintAggregatorConfig) (chainReportFormatter, error) {
b, ok := r.builders[chSel]
if !ok {
return nil, fmt.Errorf("no formatter registered for chain selector: %d", chSel)
Expand All @@ -220,17 +209,17 @@ func (r *formatterFactory) get(chSel chainSelector, config SecureMintAggregatorC
// newFormatterFactory collects all chain report formatters per chain family so that they can be used to pack reports for different chains
func newFormatterFactory() *formatterFactory {
r := formatterFactory{
builders: map[chainSelector]chainReportFormatterBuilder{},
builders: map[securemint.ChainSelector]chainReportFormatterBuilder{},
}

// EVM
for _, selector := range chainselectors.EvmChainIdToChainSelector() {
r.register(chainSelector(selector), newEVMReportFormatter)
r.register(securemint.ChainSelector(selector), newEVMReportFormatter)
}

// Solana
for _, selector := range chainselectors.SolanaChainIdToChainSelector() {
r.register(chainSelector(selector), newSolanaReportFormatter)
r.register(securemint.ChainSelector(selector), newSolanaReportFormatter)
}

return &r
Expand Down Expand Up @@ -320,7 +309,7 @@ func (a *SecureMintAggregator) extractAndValidateReports(lggr logger.Logger, obs
lggr.Debugw("Obs with context", "obs with ctx", obsWithContext)

// Deserialize the ReportWithInfo
var reportWithInfo ocr3types.ReportWithInfo[chainSelector]
var reportWithInfo ocr3types.ReportWithInfo[securemint.ChainSelector]
if err := json.Unmarshal(obsWithContext.Event.Report, &reportWithInfo); err != nil {
lggr.Errorw("failed to unmarshal ReportWithInfo", "err", err)
continue
Expand All @@ -336,9 +325,9 @@ func (a *SecureMintAggregator) extractAndValidateReports(lggr logger.Logger, obs
foundMatchingChainSelector = true

// Deserialize the inner secureMintReport
var innerReport secureMintReport
var innerReport securemint.Report
if err := json.Unmarshal(reportWithInfo.Report, &innerReport); err != nil {
lggr.Errorw("failed to unmarshal secureMintReport", "err", err)
lggr.Errorw("failed to unmarshal securemint.Report", "err", err)
continue
}
report := &wrappedMintReport{
Expand Down Expand Up @@ -432,7 +421,7 @@ func parseSecureMintConfig(config values.Map) (SecureMintAggregatorConfig, error
}

parsedConfig := SecureMintAggregatorConfig{
TargetChainSelector: chainSelector(sel),
TargetChainSelector: securemint.ChainSelector(sel),
DataID: [16]byte(decodedDataID),
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/types/chains/solana"
"github.com/smartcontractkit/chainlink-common/pkg/types/core/securemint"
ocrcommon "github.com/smartcontractkit/libocr/commontypes"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2/types"
ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
Expand All @@ -23,9 +24,9 @@ import (

var (
// Test chain selectors
ethSepoliaChainSelector = chainSelector(16015286601757825753) // Ethereum Sepolia testnet
bnbTestnetChainSelector = chainSelector(13264668187771770619) // Binance Smart Chain testnet
solDevnetChainSelector = chainSelector(16423721717087811551) // Solana devnet
ethSepoliaChainSelector = securemint.ChainSelector(16015286601757825753) // Ethereum Sepolia testnet
bnbTestnetChainSelector = securemint.ChainSelector(13264668187771770619) // Binance Smart Chain testnet
solDevnetChainSelector = securemint.ChainSelector(16423721717087811551) // Solana devnet
)

func TestSecureMintAggregator_Aggregate(t *testing.T) {
Expand Down Expand Up @@ -114,7 +115,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) {
{
chainSelector: ethSepoliaChainSelector,
seqNr: 10,
report: &secureMintReport{
report: &securemint.Report{
ConfigDigest: ocr2types.ConfigDigest{0: 1, 31: 2},
SeqNr: 10,
Block: 1000,
Expand All @@ -124,7 +125,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) {
{
chainSelector: bnbTestnetChainSelector,
seqNr: 10,
report: &secureMintReport{
report: &securemint.Report{
ConfigDigest: ocr2types.ConfigDigest{0: 2, 31: 3},
SeqNr: 10,
Block: 1100,
Expand All @@ -146,7 +147,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) {
{
chainSelector: bnbTestnetChainSelector,
seqNr: 10,
report: &secureMintReport{
report: &securemint.Report{
ConfigDigest: ocr2types.ConfigDigest{0: 1, 31: 2},
SeqNr: 10,
Block: 1000,
Expand Down Expand Up @@ -179,7 +180,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) {
{
chainSelector: solDevnetChainSelector,
seqNr: 10,
report: &secureMintReport{
report: &securemint.Report{
ConfigDigest: ocr2types.ConfigDigest{0: 1, 31: 2},
SeqNr: 10,
Block: 1000,
Expand All @@ -190,7 +191,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) {
{
chainSelector: bnbTestnetChainSelector,
seqNr: 10,
report: &secureMintReport{
report: &securemint.Report{
ConfigDigest: ocr2types.ConfigDigest{0: 2, 31: 3},
SeqNr: 10,
Block: 1100,
Expand Down Expand Up @@ -268,7 +269,7 @@ func TestSecureMintAggregatorConfig_Validation(t *testing.T) {
chainSelector string
dataID string
solanaAccounts solana.AccountMetaSlice
expectedChainSelector chainSelector
expectedChainSelector securemint.ChainSelector
expectedDataID [16]byte
expectError bool
errorMsg string
Expand Down Expand Up @@ -374,9 +375,9 @@ func TestSecureMintAggregatorConfig_Validation(t *testing.T) {
// Helper types and functions

type ocrTriggerEventData struct {
chainSelector chainSelector
chainSelector securemint.ChainSelector
seqNr uint64
report *secureMintReport
report *securemint.Report
accCtx solana.AccountMetaSlice
}

Expand All @@ -389,7 +390,7 @@ func createSecureMintObservations(t *testing.T, events []ocrTriggerEventData) ma
var oracleObservations []values.Value
for _, event := range events {
// Create the ReportWithInfo
ocr3Report := &ocr3types.ReportWithInfo[chainSelector]{
ocr3Report := &ocr3types.ReportWithInfo[securemint.ChainSelector]{
Report: createReportBytes(t, event.report),
Info: event.chainSelector,
}
Expand Down Expand Up @@ -430,7 +431,7 @@ func createSecureMintObservations(t *testing.T, events []ocrTriggerEventData) ma
return observations
}

func createReportBytes(t *testing.T, report *secureMintReport) []byte {
func createReportBytes(t *testing.T, report *securemint.Report) []byte {
reportBytes, err := json.Marshal(report)
require.NoError(t, err)
return reportBytes
Expand Down
13 changes: 11 additions & 2 deletions pkg/loop/internal/pb/reporting_plugin_service.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/loop/internal/pb/reporting_plugin_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ message NewReportingPluginFactoryRequest {
uint32 capRegistryID = 6;
uint32 keyValueStoreID = 7;
uint32 relayerSetID = 8;
uint32 secureMintExternalAdapterID = 9;
}

// NewReportingPluginFactoryReply has return arguments for [github.com/smartcontractkit/chainlink-common/pkg/loop/reporting_plugins/LOOPPService.NewReportingPluginFactory].
Expand Down
Loading
Loading