diff --git a/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator.go b/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator.go index 16be897bcf..0a7adf901f 100644 --- a/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator.go +++ b/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "math/big" + "strconv" ocrcommon "github.com/smartcontractkit/libocr/commontypes" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2/types" @@ -31,7 +32,7 @@ type secureMintReport struct { } // chainSelector represents the chain selector type, mimics the ChainSelector type in the SM plugin repo -type chainSelector int64 +type chainSelector uint64 // SecureMintAggregatorConfig is the config for the SecureMint aggregator. // This aggregator is designed to pick out reports for a specific chain selector. @@ -51,15 +52,6 @@ func (c SecureMintAggregatorConfig) ToMap() (*values.Map, error) { return v, nil } -func NewSecureMintConfig(m values.Map) (SecureMintAggregatorConfig, error) { - var config SecureMintAggregatorConfig - if err := m.UnwrapTo(&config); err != nil { - return SecureMintAggregatorConfig{}, fmt.Errorf("failed to unwrap values.Map %+v to SecureMintAggregatorConfig: %w", m, err) - } - - return config, nil -} - var _ types.Aggregator = (*SecureMintAggregator)(nil) type SecureMintAggregator struct { @@ -241,14 +233,26 @@ func (a *SecureMintAggregator) createOutcome(lggr logger.Logger, report *secureM // parseSecureMintConfig parses the user-facing, type-less, SecureMint aggregator config into the internal typed config. func parseSecureMintConfig(config values.Map) (SecureMintAggregatorConfig, error) { - var parsedConfig SecureMintAggregatorConfig - if err := config.UnwrapTo(&parsedConfig); err != nil { - return SecureMintAggregatorConfig{}, fmt.Errorf("failed to unwrap config: %w", err) + type rawConfig struct { + TargetChainSelector string `mapstructure:"targetChainSelector"` + } + + var rawCfg rawConfig + if err := config.UnwrapTo(&rawCfg); err != nil { + return SecureMintAggregatorConfig{}, fmt.Errorf("failed to unwrap values.Map %+v: %w", config, err) + } + + if rawCfg.TargetChainSelector == "" { + return SecureMintAggregatorConfig{}, errors.New("targetChainSelector is required") + } + + sel, err := strconv.ParseUint(rawCfg.TargetChainSelector, 10, 64) + if err != nil { + return SecureMintAggregatorConfig{}, fmt.Errorf("invalid chain selector: %w", err) } - // Validate configuration - if parsedConfig.TargetChainSelector <= 0 { - return SecureMintAggregatorConfig{}, fmt.Errorf("targetChainSelector is required") + parsedConfig := SecureMintAggregatorConfig{ + TargetChainSelector: chainSelector(sel), } return parsedConfig, nil diff --git a/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator_test.go b/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator_test.go index 88b6518810..a15b8eec61 100644 --- a/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator_test.go +++ b/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator_test.go @@ -9,14 +9,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - 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/values" + ocrcommon "github.com/smartcontractkit/libocr/commontypes" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ) var ( @@ -30,7 +29,7 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { tests := []struct { name string - config SecureMintAggregatorConfig + config *values.Map previousOutcome *types.AggregationOutcome observations map[ocrcommon.OracleID][]values.Value f int @@ -40,10 +39,8 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { errorContains string }{ { - name: "successful eth report extraction", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, + name: "successful eth report extraction", + config: configWithChainSelector(t, "1"), observations: createSecureMintObservations(t, []ocrTriggerEventData{ { chainSelector: ethChainSelector, @@ -72,10 +69,8 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { expectError: false, }, { - name: "no matching chain selector found", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, + name: "no matching chain selector found", + config: configWithChainSelector(t, "1"), observations: createSecureMintObservations(t, []ocrTriggerEventData{ { chainSelector: bnbChainSelector, @@ -93,10 +88,8 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { expectedShouldReport: false, }, { - name: "sequence number too low", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, + name: "sequence number too low", + config: configWithChainSelector(t, "1"), previousOutcome: &types.AggregationOutcome{ LastSeenAt: 10, // Previous sequence number }, @@ -117,20 +110,16 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { errorContains: "sequence number too low", }, { - name: "no observations", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, + name: "no observations", + config: configWithChainSelector(t, "1"), observations: map[ocrcommon.OracleID][]values.Value{}, f: 1, expectError: true, errorContains: "no observations", }, { - name: "sequence number equal to previous (should be ignored)", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, + name: "sequence number equal to previous (should be ignored)", + config: configWithChainSelector(t, "1"), previousOutcome: &types.AggregationOutcome{ LastSeenAt: 10, // Previous sequence number }, @@ -154,12 +143,8 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - // Create config map - cfgMap, err := tc.config.ToMap() - require.NoErrorf(t, err, "Failed to convert config %+v to values.Map", tc.config) - // Create aggregator - aggregator, err := NewSecureMintAggregator(*cfgMap) + aggregator, err := NewSecureMintAggregator(*tc.config) require.NoError(t, err) // Run aggregation @@ -220,95 +205,66 @@ func TestSecureMintAggregator_Aggregate(t *testing.T) { } } -func TestSecureMintAggregatorConfig_RoundTrip(t *testing.T) { - testCases := []struct { - name string - config SecureMintAggregatorConfig - }{ - { - name: "default eth config", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, - }, - { - name: "custom target chain selector", - config: SecureMintAggregatorConfig{ - TargetChainSelector: bnbChainSelector, - }, - }, - { - name: "large chain selector", - config: SecureMintAggregatorConfig{ - TargetChainSelector: 999999, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Step 1: Convert original config to values.Map - configMap, err := tc.config.ToMap() - require.NoError(t, err, "ToMap should not error") - require.NotNil(t, configMap, "ToMap should return non-nil map") - - // Step 2: Convert values.Map back to config - roundTrippedConfig, err := NewSecureMintConfig(*configMap) - require.NoError(t, err, "NewSecureMintConfig should not error") - - // Step 3: Compare original and round-tripped configs - assert.Equal(t, tc.config.TargetChainSelector, roundTrippedConfig.TargetChainSelector, - "TargetChainSelector should match") - }) - } +func configWithChainSelector(t *testing.T, chainSelector string) *values.Map { + m, err := values.NewMap(map[string]any{ + "targetChainSelector": chainSelector, + }) + require.NoError(t, err) + return m } func TestSecureMintAggregatorConfig_Validation(t *testing.T) { tests := []struct { - name string - config SecureMintAggregatorConfig - expectError bool - errorMsg string + name string + chainSelector string + expected chainSelector + expectError bool + errorMsg string }{ { - name: "valid config", - config: SecureMintAggregatorConfig{ - TargetChainSelector: ethChainSelector, - }, - expectError: false, + name: "valid chain selector", + chainSelector: "1", + expected: 1, + expectError: false, }, { - name: "zero target chain selector", - config: SecureMintAggregatorConfig{ - TargetChainSelector: 0, - }, - expectError: true, - errorMsg: "targetChainSelector is required", + name: "invalid chain selector", + chainSelector: "invalid", + expectError: true, + errorMsg: "invalid chain selector", }, { - name: "negative chain selector", - config: SecureMintAggregatorConfig{ - TargetChainSelector: -1, - }, - expectError: true, - errorMsg: "targetChainSelector is required", + name: "large chain selector", + chainSelector: "16015286601757825753", // ethereum-testnet-sepolia + expected: 16015286601757825753, + expectError: false, + }, + { + name: "negative chain selector", + chainSelector: "-1", + expectError: true, + errorMsg: "invalid chain selector", }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - configMap, err := tc.config.ToMap() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + configMap, err := values.WrapMap(map[string]any{ + "targetChainSelector": tt.chainSelector, + }) require.NoError(t, err) - _, err = NewSecureMintAggregator(*configMap) - if tc.expectError { + aggregator, err := NewSecureMintAggregator(*configMap) + if tt.expectError { require.Error(t, err) - if tc.errorMsg != "" { - require.Contains(t, err.Error(), tc.errorMsg) + if tt.errorMsg != "" { + require.Contains(t, err.Error(), tt.errorMsg) } - } else { - require.NoError(t, err) + return } + + require.NoError(t, err) + assert.Equal(t, tt.expected, aggregator.(*SecureMintAggregator).config.TargetChainSelector) }) } }