Skip to content

Commit

Permalink
Add new job spec params (#14973)
Browse files Browse the repository at this point in the history
* -Add new job spec params
-Add tests
-Add key validation

* -Remove unused method

* -Fix lint
  • Loading branch information
george-dorin authored Oct 28, 2024
1 parent 8433007 commit 7cdce3c
Show file tree
Hide file tree
Showing 6 changed files with 458 additions and 0 deletions.
40 changes: 40 additions & 0 deletions core/services/job/job_orm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2013,3 +2013,43 @@ func mustInsertPipelineRun(t *testing.T, orm pipeline.ORM, j job.Job) pipeline.R
require.NoError(t, err)
return run
}

func TestORM_CreateJob_OCR2_With_OEV(t *testing.T) {
ctx := testutils.Context(t)
customChainID := big.New(testutils.NewRandomEVMChainID())

config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
enabled := true
c.EVM = append(c.EVM, &evmcfg.EVMConfig{
ChainID: customChainID,
Chain: evmcfg.Defaults(customChainID),
Enabled: &enabled,
Nodes: evmcfg.EVMNodes{{}},
})
})
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db)
require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key))

_, transmitterID := cltest.MustInsertRandomKey(t, keyStore.Eth())

lggr := logger.TestLogger(t)
pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)

jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore)

oevTransmitterKey := cltest.MustGenerateRandomKey(t)

jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMWithOEVSpecMinimal(cltest.DefaultOCR2Key.ID(), transmitterID.String(), oevTransmitterKey.EIP55Address.String()), nil)
require.NoError(t, err)

t.Run("unknown transmitter address", func(t *testing.T) {
require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "failed to validate oev.TransmitterAddress: no EVM key matching")
})

t.Run("multiple jobs", func(t *testing.T) {
keyStore.Eth().XXXTestingOnlyAdd(ctx, oevTransmitterKey)
require.NoError(t, jobORM.CreateJob(ctx, &jb), "failed to validate oev.TransmitterAddress: no EVM key matching")
})
}
87 changes: 87 additions & 0 deletions core/services/job/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ type Job struct {
CCIPSpecID *int32
CCIPSpec *CCIPSpec
CCIPBootstrapSpecID *int32
OEVConfig *OEVConfig `toml:"oev"`
JobSpecErrors []SpecError
Type Type `toml:"type"`
SchemaVersion uint32 `toml:"schemaVersion"`
Expand Down Expand Up @@ -1040,3 +1041,89 @@ type CCIPSpec struct {
// and RMN network info for offchain blessing.
PluginConfig JSONConfig `toml:"pluginConfig"`
}

type OEVConfig struct {
TransmitterAddress *evmtypes.EIP55Address `toml:"transmitterAddress"`
ContractAddress *evmtypes.EIP55Address `toml:"contractAddress"`
Builders []string `toml:"builders"`
Hints []string `toml:"hints"`
Refund []OEVRefund `toml:"refund"`
PriceDelay time.Duration `toml:"priceDelay"`
}

type OEVRefund struct {
Address *evmtypes.EIP55Address `toml:"address"`
Percent int `toml:"percent"`
}

func (o *OEVConfig) Validate() error {
if o.TransmitterAddress == nil {
return errors.New("no OEVTransmitterAddress found")
}

if o.ContractAddress == nil {
return errors.New("no OEVContractAddress found")
}

if o.Builders == nil {
return errors.New("no OEVBuilders found")
}

if len(o.Builders) == 0 {
return errors.New("OEVBuilders expects at least one builder, none given")
}

if containsEmptyElement(o.Builders) {
return errors.Errorf("OEVBuilders should not contain empty element %q", o.Builders)
}

if o.Hints == nil {
return errors.New("no OEVHints found")
}
if len(o.Hints) == 0 {
return errors.New("OEVHints expects at least one hint, none given")
}

if containsEmptyElement(o.Hints) {
return errors.Errorf("OEVHints should not contain empty element %q", o.Hints)
}

if o.Refund == nil {
return errors.New("no OEVRefund found")
}

if o.PriceDelay.Seconds() <= 1 {
return errors.New("OEVPriceDelay not set or smaller than 1s")
}

if o.Refund == nil {
return errors.New("no OEVRefund found")
}

totalRefundPercent := 0
for _, r := range o.Refund {
if r.Address == nil {
return errors.New("OEVRefund.Address should not be empty")
}

if r.Percent <= 0 || r.Percent > 100 {
return errors.New("OEVRefund.Percent should be between 1 and 100")
}
totalRefundPercent += r.Percent
}

if totalRefundPercent > 100 {
return errors.New("the sum of all OEVRefund.Percent should not be greater than 100")
}

return nil
}

func containsEmptyElement(s []string) bool {
for _, str := range s {
if str == "" {
return true
}
}
return false
}
Loading

0 comments on commit 7cdce3c

Please sign in to comment.