From f8fbcd8bbbd3350f079c787b9e620891cb718548 Mon Sep 17 00:00:00 2001 From: Kristijan Rebernisak Date: Mon, 17 Oct 2022 18:27:40 +0200 Subject: [PATCH] Check if observations sorted before taking median --- .../pkg/chainlink/ocr2/medianreport/report.go | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/relayer/pkg/chainlink/ocr2/medianreport/report.go b/relayer/pkg/chainlink/ocr2/medianreport/report.go index c26e0aa4b..ad88f9b21 100644 --- a/relayer/pkg/chainlink/ocr2/medianreport/report.go +++ b/relayer/pkg/chainlink/ocr2/medianreport/report.go @@ -90,6 +90,7 @@ func (c ReportCodec) MedianFromReport(report types.Report) (*big.Int, error) { return nil, errors.New("invalid report length") } + // Decode the number of observations numBig := junotypes.BytesToFelt(report[(timestampSizeBytes + observersSizeBytes):prefixSizeBytes]).Big() if !numBig.IsUint64() { return nil, errors.New("length of observations is invalid") @@ -102,22 +103,34 @@ func (c ReportCodec) MedianFromReport(report types.Report) (*big.Int, error) { return nil, errors.New("length of observations is invalid") } + // Check if the report is big enough n := int(n64) - - if rLen < prefixSizeBytes+(observationSizeBytes*n)+juelsPerFeeCoinSizeBytes { - return nil, errors.New("report does not contain enough observations or is missing juels/feeCoin observation") + expectedLen := prefixSizeBytes + (observationSizeBytes * n) + juelsPerFeeCoinSizeBytes + if rLen < expectedLen { + return nil, errors.New("invalid report length, missing main or juelsPerFeeCoin observations") } - var observations []*big.Int + // Decode observations + var oo []*big.Int for i := 0; i < n; i++ { start := prefixSizeBytes + observationSizeBytes*i end := start + observationSizeBytes - o := junotypes.BytesToFelt(report[start:end]).Big() - o = starknet.FeltToSignedBig(&caigotypes.Felt{Int: o}) - observations = append(observations, o) + o := starknet.FeltToSignedBig(&caigotypes.Felt{ + Int: junotypes.BytesToFelt(report[start:end]).Big(), + }) + oo = append(oo, o) + } + + // Check if the report contains sorted observations + _less := func(i, j int) bool { + return oo[i].Cmp(oo[j]) < 0 + } + sorted := sort.SliceIsSorted(oo, _less) + if !sorted { + return nil, errors.New("observations not sorted") } - return observations[n/2], nil + return oo[n/2], nil } func (c ReportCodec) MaxReportLength(n int) int { @@ -127,7 +140,7 @@ func (c ReportCodec) MaxReportLength(n int) int { func SplitReport(report types.Report) ([][]byte, error) { chunkSize := junotypes.FeltLength if len(report)%chunkSize != 0 { - return [][]byte{}, errors.New("invalid length of the report") + return [][]byte{}, errors.New("invalid report length") } // order is guaranteed by buildReport: