-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SubPlugin interface to create multiple SubPlugins/Processors under OCR plugin. The idea is to separate the logic of different types of observations and outcomes into separate processors. This makes it easier to manage and test the logic of each type of observation/outcome without affecting each others. Some of them will implement state machines (e.g. merkleroot), others might implement simpler logic. (e.g. token) Also makes running them in parallel more streamlined. The OCR plugin becomes a coordinator/collector of these SubPlugins. Example Pseudo code: ``` OCRPlugin { nodeID merkleProcessor tokenProcessor feeProcessor ... } OCRPlugin.Observer { mObs := merkleProcessor.Observer tObs := tokenProcessor.Observer fObs := feeProcessor.Observer return Observation{mObs, tObs, fObs} } OCRPlugin.Validate { mObs := merkleProcessor.Validate tObs := tokenProcessor.Validate fObs := feeProcessor.Validate check errors for each return nil } OCRPlugin.Outcome { mOut := merkleProcessor.Outcome tOut := tokenProcessor.Outcome fOut := feeProcessor.Outcome return Outcome{mOut, tOut, fOut} } OCRPlugin.Report { return Report{mOut.X, tOut.Y, fOut.Z} } ``` Notice all SubPlugin interface functions are using `prevOutcome` instead of `outCtx`. We're interested in the prevOutcome, and it makes it easier to have all decoding on the top level (OCR plugin), otherwise there might be cyclic dependencies or just complicating the code more.
- Loading branch information
1 parent
70b5719
commit f8a43b7
Showing
33 changed files
with
1,694 additions
and
1,083 deletions.
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
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,65 @@ | ||
package chainfee | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
mapset "github.com/deckarep/golang-set/v2" | ||
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" | ||
|
||
"github.com/smartcontractkit/chainlink-ccip/shared" | ||
) | ||
|
||
type Processor struct { | ||
} | ||
|
||
func NewProcessor() *Processor { | ||
return &Processor{} | ||
} | ||
|
||
func (w *Processor) Query(ctx context.Context, prevOutcome Outcome) (Query, error) { | ||
return Query{}, nil | ||
} | ||
|
||
func (w *Processor) Observation( | ||
ctx context.Context, | ||
prevOutcome Outcome, | ||
query Query, | ||
) (Observation, error) { | ||
return Observation{}, nil | ||
} | ||
|
||
func (w *Processor) Outcome( | ||
prevOutcome Outcome, | ||
query Query, | ||
aos []shared.AttributedObservation[Observation], | ||
) (Outcome, error) { | ||
return Outcome{}, nil | ||
} | ||
|
||
func (w *Processor) ValidateObservation( | ||
prevOutcome Outcome, | ||
query Query, | ||
ao shared.AttributedObservation[Observation], | ||
) error { | ||
//TODO: Validate token prices | ||
return nil | ||
} | ||
|
||
func validateObservedGasPrices(gasPrices []cciptypes.GasPriceChain) error { | ||
// Duplicate gas prices must not appear for the same chain and must not be empty. | ||
gasPriceChains := mapset.NewSet[cciptypes.ChainSelector]() | ||
for _, g := range gasPrices { | ||
if gasPriceChains.Contains(g.ChainSel) { | ||
return fmt.Errorf("duplicate gas price for chain %d", g.ChainSel) | ||
} | ||
gasPriceChains.Add(g.ChainSel) | ||
if g.GasPrice.IsEmpty() { | ||
return fmt.Errorf("gas price must not be empty") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
var _ shared.PluginProcessor[Query, Observation, Outcome] = &Processor{} |
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,16 @@ | ||
package chainfee | ||
|
||
import ( | ||
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" | ||
) | ||
|
||
type Query struct { | ||
} | ||
|
||
type Outcome struct { | ||
GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` | ||
} | ||
|
||
type Observation struct { | ||
GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` | ||
} |
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,62 @@ | ||
package chainfee | ||
|
||
import ( | ||
"math/big" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" | ||
) | ||
|
||
func Test_validateObservedGasPrices(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
gasPrices []cciptypes.GasPriceChain | ||
expErr bool | ||
}{ | ||
{ | ||
name: "empty is valid", | ||
gasPrices: []cciptypes.GasPriceChain{}, | ||
expErr: false, | ||
}, | ||
{ | ||
name: "all valid", | ||
gasPrices: []cciptypes.GasPriceChain{ | ||
cciptypes.NewGasPriceChain(big.NewInt(10), 1), | ||
cciptypes.NewGasPriceChain(big.NewInt(20), 2), | ||
cciptypes.NewGasPriceChain(big.NewInt(1312), 3), | ||
}, | ||
expErr: false, | ||
}, | ||
{ | ||
name: "duplicate gas price", | ||
gasPrices: []cciptypes.GasPriceChain{ | ||
cciptypes.NewGasPriceChain(big.NewInt(10), 1), | ||
cciptypes.NewGasPriceChain(big.NewInt(20), 2), | ||
cciptypes.NewGasPriceChain(big.NewInt(1312), 1), // notice we already have a gas price for chain 1 | ||
}, | ||
expErr: true, | ||
}, | ||
{ | ||
name: "empty gas price", | ||
gasPrices: []cciptypes.GasPriceChain{ | ||
cciptypes.NewGasPriceChain(big.NewInt(10), 1), | ||
cciptypes.NewGasPriceChain(big.NewInt(20), 2), | ||
cciptypes.NewGasPriceChain(nil, 3), // nil | ||
}, | ||
expErr: true, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
err := validateObservedGasPrices(tc.gasPrices) | ||
if tc.expErr { | ||
assert.Error(t, err) | ||
return | ||
} | ||
assert.NoError(t, err) | ||
}) | ||
} | ||
} |
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
Oops, something went wrong.