diff --git a/.golangci.yml b/.golangci.yml index 6c33e04..81c28fb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,6 +10,11 @@ linters: - misspell - rowserrcheck - errorlint + - unconvert + - sqlclosecheck + - noctx + - whitespace + - depguard linters-settings: exhaustive: default-signifies-exhaustive: true @@ -26,7 +31,7 @@ linters-settings: # - G404 govet: # report about shadowed variables - check-shadowing: false + check-shadowing: true errorlint: # Allow formatting of errors without %w errorf: false @@ -40,9 +45,10 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming + - name: exported - name: if-return - name: increment-decrement - # - name: var-naming + - name: var-naming - name: var-declaration - name: package-comments - name: range @@ -61,23 +67,54 @@ linters-settings: - name: struct-tag # - name: string-format - name: string-of-int - # - name: range-val-address + - name: range-val-address - name: range-val-in-closure - name: modifies-value-receiver - name: modifies-parameter - name: identical-branches - name: get-return # - name: flag-parameter - # - name: early-return + - name: early-return - name: defer - name: constant-logical-expr # - name: confusing-naming # - name: confusing-results - name: bool-literal-in-expr - name: atomic + depguard: + rules: + main: + list-mode: lax + deny: + - pkg: "cosmossdk.io/errors" + desc: Use the standard library instead + - pkg: "github.com/ethereum/go-ethereum" + desc: This is a chain-agnostic repo + - pkg: "github.com/go-gorm/gorm" + desc: Use github.com/jmoiron/sqlx directly instead + - pkg: "github.com/gofrs/uuid" + desc: Use github.com/google/uuid instead + - pkg: "github.com/pkg/errors" + desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join + - pkg: "github.com/satori/go.uuid" + desc: Use github.com/google/uuid instead + - pkg: "github.com/test-go/testify/assert" + desc: Use github.com/stretchr/testify/assert instead + - pkg: "github.com/test-go/testify/mock" + desc: Use github.com/stretchr/testify/mock instead + - pkg: "github.com/test-go/testify/require" + desc: Use github.com/stretchr/testify/require instead + - pkg: "go.uber.org/multierr" + desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join + - pkg: "gopkg.in/guregu/null.v1" + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: "gopkg.in/guregu/null.v2" + desc: Use gopkg.in/guregu/null.v4 instead + - pkg: "gopkg.in/guregu/null.v3" + desc: Use gopkg.in/guregu/null.v4 instead issues: exclude-rules: - path: test text: "^G404:" linters: - - gosec + - gosec \ No newline at end of file diff --git a/llo/plugin.go b/llo/plugin.go index db58c10..a34919f 100644 --- a/llo/plugin.go +++ b/llo/plugin.go @@ -33,12 +33,12 @@ import ( // Additional limits so we can more effectively bound the size of observations const ( - MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH = 5 - MAX_OBSERVATION_ADD_CHANNEL_DEFINITIONS_LENGTH = 5 - MAX_OBSERVATION_STREAM_VALUES_LENGTH = 1_000 + MaxObservationRemoveChannelIDsLength = 5 + MaxObservationAddChannelDefinitionsLength = 5 + MaxObservationStreamValuesLength = 1_000 ) -const MAX_OUTCOME_CHANNEL_DEFINITIONS_LENGTH = 500 +const MaxOutcomeChannelDefinitionsLength = 500 // Values for a set of streams, e.g. "eth-usd", "link-usd", and "eur-chf" // TODO: generalize from *big.Int to anything @@ -185,7 +185,7 @@ func (f *PluginFactory) NewReportingPlugin(cfg ocr3types.ReportingPluginConfig) return nil, ocr3types.ReportingPluginInfo{}, fmt.Errorf("NewReportingPlugin failed to decode offchain config; got: 0x%x (len: %d); %w", cfg.OffchainConfig, len(cfg.OffchainConfig), err) } - return &LLOPlugin{ + return &Plugin{ offchainCfg.PredecessorConfigDigest, cfg.ConfigDigest, f.PredecessorRetirementReportCache, @@ -207,7 +207,7 @@ func (f *PluginFactory) NewReportingPlugin(cfg ocr3types.ReportingPluginConfig) }, nil } -var _ ocr3types.ReportingPlugin[llotypes.ReportInfo] = &LLOPlugin{} +var _ ocr3types.ReportingPlugin[llotypes.ReportInfo] = &Plugin{} type ReportCodec interface { Encode(Report) ([]byte, error) @@ -215,7 +215,7 @@ type ReportCodec interface { // TODO: max length check? https://smartcontract-it.atlassian.net/browse/MERC-3524 } -type LLOPlugin struct { +type Plugin struct { PredecessorConfigDigest *types.ConfigDigest ConfigDigest types.ConfigDigest PredecessorRetirementReportCache PredecessorRetirementReportCache @@ -240,7 +240,7 @@ type LLOPlugin struct { // *not* strictly) across the lifetime of a protocol instance and that // outctx.previousOutcome contains the consensus outcome with sequence // number (outctx.SeqNr-1). -func (p *LLOPlugin) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (types.Query, error) { +func (p *Plugin) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (types.Query, error) { return nil, nil } @@ -256,7 +256,7 @@ type Observation struct { RemoveChannelIDs map[llotypes.ChannelID]struct{} AddChannelDefinitions llotypes.ChannelDefinitions // Observed (numeric) stream values. Subject to - // MAX_OBSERVATION_STREAM_VALUES_LENGTH limit + // MaxObservationStreamValuesLength limit StreamValues StreamValues } @@ -269,7 +269,7 @@ type Observation struct { // number (outctx.SeqNr-1). // // Should return a serialized Observation struct. -func (p *LLOPlugin) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query) (types.Observation, error) { +func (p *Plugin) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query types.Query) (types.Observation, error) { // send empty observation in initial round // NOTE: First sequence number is always 1 if outctx.SeqNr < 1 { @@ -313,13 +313,13 @@ func (p *LLOPlugin) Observation(ctx context.Context, outctx ocr3types.OutcomeCon { expectedChannelDefs := p.ChannelDefinitionCache.Definitions() - removeChannelDefinitions := subtractChannelDefinitions(previousOutcome.ChannelDefinitions, expectedChannelDefs, MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH) + removeChannelDefinitions := subtractChannelDefinitions(previousOutcome.ChannelDefinitions, expectedChannelDefs, MaxObservationRemoveChannelIDsLength) for channelID := range removeChannelDefinitions { removeChannelIDs[channelID] = struct{}{} } for channelID := range previousOutcome.ValidAfterSeconds { - if len(removeChannelIDs) >= MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH { + if len(removeChannelIDs) >= MaxObservationRemoveChannelIDsLength { break } if _, ok := expectedChannelDefs[channelID]; !ok { @@ -327,7 +327,7 @@ func (p *LLOPlugin) Observation(ctx context.Context, outctx ocr3types.OutcomeCon } } - addChannelDefinitions = subtractChannelDefinitions(expectedChannelDefs, previousOutcome.ChannelDefinitions, MAX_OBSERVATION_ADD_CHANNEL_DEFINITIONS_LENGTH) + addChannelDefinitions = subtractChannelDefinitions(expectedChannelDefs, previousOutcome.ChannelDefinitions, MaxObservationAddChannelDefinitionsLength) } var streamValues StreamValues @@ -374,7 +374,7 @@ func (p *LLOPlugin) Observation(ctx context.Context, outctx ocr3types.OutcomeCon // *not* strictly) across the lifetime of a protocol instance and that // outctx.previousOutcome contains the consensus outcome with sequence // number (outctx.SeqNr-1). -func (p *LLOPlugin) ValidateObservation(outctx ocr3types.OutcomeContext, query types.Query, ao types.AttributedObservation) error { +func (p *Plugin) ValidateObservation(outctx ocr3types.OutcomeContext, query types.Query, ao types.AttributedObservation) error { if outctx.SeqNr <= 1 { if len(ao.Observation) != 0 { return fmt.Errorf("Observation is not empty") @@ -394,16 +394,16 @@ func (p *LLOPlugin) ValidateObservation(outctx ocr3types.OutcomeContext, query t return fmt.Errorf("AttestedPredecessorRetirement is not empty even though this instance has no predecessor") } - if len(observation.AddChannelDefinitions) > MAX_OBSERVATION_ADD_CHANNEL_DEFINITIONS_LENGTH { - return fmt.Errorf("AddChannelDefinitions is too long: %v vs %v", len(observation.AddChannelDefinitions), MAX_OBSERVATION_ADD_CHANNEL_DEFINITIONS_LENGTH) + if len(observation.AddChannelDefinitions) > MaxObservationAddChannelDefinitionsLength { + return fmt.Errorf("AddChannelDefinitions is too long: %v vs %v", len(observation.AddChannelDefinitions), MaxObservationAddChannelDefinitionsLength) } - if len(observation.RemoveChannelIDs) > MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH { - return fmt.Errorf("RemoveChannelIDs is too long: %v vs %v", len(observation.RemoveChannelIDs), MAX_OBSERVATION_REMOVE_CHANNEL_IDS_LENGTH) + if len(observation.RemoveChannelIDs) > MaxObservationRemoveChannelIDsLength { + return fmt.Errorf("RemoveChannelIDs is too long: %v vs %v", len(observation.RemoveChannelIDs), MaxObservationRemoveChannelIDsLength) } - if len(observation.StreamValues) > MAX_OBSERVATION_STREAM_VALUES_LENGTH { - return fmt.Errorf("StreamValues is too long: %v vs %v", len(observation.StreamValues), MAX_OBSERVATION_STREAM_VALUES_LENGTH) + if len(observation.StreamValues) > MaxObservationStreamValuesLength { + return fmt.Errorf("StreamValues is too long: %v vs %v", len(observation.StreamValues), MaxObservationStreamValuesLength) } for streamID, obsResult := range observation.StreamValues { @@ -515,7 +515,7 @@ func (out *Outcome) ReportableChannels() []llotypes.ChannelID { // // libocr guarantees that this will always be called with at least 2f+1 // AttributedObservations -func (p *LLOPlugin) Outcome(outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation) (ocr3types.Outcome, error) { +func (p *Plugin) Outcome(outctx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation) (ocr3types.Outcome, error) { if len(aos) < 2*p.F+1 { return nil, fmt.Errorf("invariant violation: expected at least 2f+1 attributed observations, got %d (f: %d)", len(aos), p.F) } @@ -673,9 +673,9 @@ func (p *LLOPlugin) Outcome(outctx ocr3types.OutcomeContext, query types.Query, ) continue } - if len(outcome.ChannelDefinitions) > MAX_OUTCOME_CHANNEL_DEFINITIONS_LENGTH { + if len(outcome.ChannelDefinitions) > MaxOutcomeChannelDefinitionsLength { p.Logger.Warn("Cannot add channel, outcome already contains maximum number of channels", - "maxOutcomeChannelDefinitionsLength", MAX_OUTCOME_CHANNEL_DEFINITIONS_LENGTH, + "maxOutcomeChannelDefinitionsLength", MaxOutcomeChannelDefinitionsLength, "addChannelDefinition", defWithID, ) continue @@ -776,7 +776,7 @@ type Report struct { Specimen bool } -func (p *LLOPlugin) encodeReport(r Report, format llotypes.ReportFormat) (types.Report, error) { +func (p *Plugin) encodeReport(r Report, format llotypes.ReportFormat) (types.Report, error) { codec, exists := p.Codecs[format] if !exists { return nil, fmt.Errorf("codec missing for ReportFormat=%d", format) @@ -797,7 +797,7 @@ func (p *LLOPlugin) encodeReport(r Report, format llotypes.ReportFormat) (types. // *not* strictly) across the lifetime of a protocol instance and that // outctx.previousOutcome contains the consensus outcome with sequence // number (outctx.SeqNr-1). -func (p *LLOPlugin) Reports(seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3types.ReportWithInfo[llotypes.ReportInfo], error) { +func (p *Plugin) Reports(seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3types.ReportWithInfo[llotypes.ReportInfo], error) { if seqNr <= 1 { // no reports for initial round return nil, nil @@ -870,12 +870,12 @@ func (p *LLOPlugin) Reports(seqNr uint64, rawOutcome ocr3types.Outcome) ([]ocr3t return rwis, nil } -func (p *LLOPlugin) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error) { +func (p *Plugin) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error) { // Transmit it all to the Mercury server return true, nil } -func (p *LLOPlugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error) { +func (p *Plugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[llotypes.ReportInfo]) (bool, error) { // Transmit it all to the Mercury server return true, nil } @@ -888,11 +888,11 @@ func (p *LLOPlugin) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3ty // This is an advanced feature. The "default" approach (what OCR1 & OCR2 // did) is to have an empty ValidateObservation function and return // QuorumTwoFPlusOne from this function. -func (p *LLOPlugin) ObservationQuorum(outctx ocr3types.OutcomeContext, query types.Query) (ocr3types.Quorum, error) { +func (p *Plugin) ObservationQuorum(outctx ocr3types.OutcomeContext, query types.Query) (ocr3types.Quorum, error) { return ocr3types.QuorumTwoFPlusOne, nil } -func (p *LLOPlugin) Close() error { +func (p *Plugin) Close() error { return nil } diff --git a/mercury/fees.go b/mercury/fees.go index d3bac56..5d54d44 100644 --- a/mercury/fees.go +++ b/mercury/fees.go @@ -8,12 +8,12 @@ import ( // PriceScalingFactor indicates the multiplier applied to token prices that we expect from data source // e.g. for a 1e8 multiplier, a LINK/USD value of 7.42 will be derived from a data source value of 742000000 -var PRICE_SCALING_FACTOR = decimal.NewFromInt(1e18) //nolint:revive +var PriceScalingFactor = decimal.NewFromInt(1e18) //nolint:revive // FeeScalingFactor indicates the multiplier applied to fees. // e.g. for a 1e18 multiplier, a LINK fee of 7.42 will be represented as 7.42e18 // This is what will be baked into the report for use on-chain. -var FEE_SCALING_FACTOR = decimal.NewFromInt(1e18) +var FeeScalingFactor = decimal.NewFromInt(1e18) // CalculateFee outputs a fee in wei according to the formula: baseUSDFee * scaleFactor / tokenPriceInUSD func CalculateFee(tokenPriceInUSD *big.Int, baseUSDFee decimal.Decimal) *big.Int { @@ -23,7 +23,7 @@ func CalculateFee(tokenPriceInUSD *big.Int, baseUSDFee decimal.Decimal) *big.Int } // scale baseFee in USD - baseFeeScaled := baseUSDFee.Mul(PRICE_SCALING_FACTOR) + baseFeeScaled := baseUSDFee.Mul(PriceScalingFactor) tokenPrice := decimal.NewFromBigInt(tokenPriceInUSD, 0) @@ -31,7 +31,7 @@ func CalculateFee(tokenPriceInUSD *big.Int, baseUSDFee decimal.Decimal) *big.Int fee := baseFeeScaled.Div(tokenPrice) // scale fee to the expected format - fee = fee.Mul(FEE_SCALING_FACTOR) + fee = fee.Mul(FeeScalingFactor) // convert to big.Int return fee.BigInt() diff --git a/mercury/onchain_config.go b/mercury/onchain_config.go index 977f0a3..6632b5d 100644 --- a/mercury/onchain_config.go +++ b/mercury/onchain_config.go @@ -1,10 +1,9 @@ package mercury import ( + "fmt" "math/big" - pkgerrors "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/bigbigendian" "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" @@ -29,7 +28,7 @@ type StandardOnchainConfigCodec struct{} func (StandardOnchainConfigCodec) Decode(b []byte) (mercury.OnchainConfig, error) { if len(b) != onchainConfigEncodedLength { - return mercury.OnchainConfig{}, pkgerrors.Errorf("unexpected length of OnchainConfig, expected %v, got %v", onchainConfigEncodedLength, len(b)) + return mercury.OnchainConfig{}, fmt.Errorf("unexpected length of OnchainConfig, expected %v, got %v", onchainConfigEncodedLength, len(b)) } v, err := bigbigendian.DeserializeSigned(32, b[:32]) @@ -37,7 +36,7 @@ func (StandardOnchainConfigCodec) Decode(b []byte) (mercury.OnchainConfig, error return mercury.OnchainConfig{}, err } if v.Cmp(onchainConfigVersionBig) != 0 { - return mercury.OnchainConfig{}, pkgerrors.Errorf("unexpected version of OnchainConfig, expected %v, got %v", onchainConfigVersion, v) + return mercury.OnchainConfig{}, fmt.Errorf("unexpected version of OnchainConfig, expected %v, got %v", onchainConfigVersion, v) } min, err := bigbigendian.DeserializeSigned(32, b[32:64]) @@ -50,7 +49,7 @@ func (StandardOnchainConfigCodec) Decode(b []byte) (mercury.OnchainConfig, error } if !(min.Cmp(max) <= 0) { - return mercury.OnchainConfig{}, pkgerrors.Errorf("OnchainConfig min (%v) should not be greater than max(%v)", min, max) + return mercury.OnchainConfig{}, fmt.Errorf("OnchainConfig min (%v) should not be greater than max(%v)", min, max) } return mercury.OnchainConfig{Min: min, Max: max}, nil diff --git a/mercury/onchain_config_test.go b/mercury/onchain_config_test.go index 1d1d09c..bee9f9e 100644 --- a/mercury/onchain_config_test.go +++ b/mercury/onchain_config_test.go @@ -15,7 +15,7 @@ func FuzzDecodeOnchainConfig(f *testing.F) { } f.Add([]byte{}) - f.Add([]byte(valid)) + f.Add(valid) f.Fuzz(func(t *testing.T, encoded []byte) { decoded, err := StandardOnchainConfigCodec{}.Decode(encoded) if err != nil { diff --git a/mercury/v1/aggregate_functions.go b/mercury/v1/aggregate_functions.go index 41989d1..c03da99 100644 --- a/mercury/v1/aggregate_functions.go +++ b/mercury/v1/aggregate_functions.go @@ -76,7 +76,6 @@ func GetConsensusLatestBlock(paos []PAO, f int) (hash []byte, num int64, ts uint }) return usableBlocks[0].HashBytes(), usableBlocks[0].Num, usableBlocks[0].Ts, nil - } // this grouping does not have any identical blocks with at least f+1 in agreement, try next block number down } diff --git a/mercury/v1/mercury.go b/mercury/v1/mercury.go index 0fd90ea..c0d257a 100644 --- a/mercury/v1/mercury.go +++ b/mercury/v1/mercury.go @@ -7,7 +7,6 @@ import ( "sort" "time" - pkgerrors "github.com/pkg/errors" "google.golang.org/protobuf/proto" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" @@ -133,7 +132,7 @@ type reportingPlugin struct { func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTimestamp, previousReport types.Report) (types.Observation, error) { obs, err := rp.dataSource.Observe(ctx, repts, previousReport == nil) if err != nil { - return nil, pkgerrors.Errorf("DataSource.Observe returned an error: %s", err) + return nil, fmt.Errorf("DataSource.Observe returned an error: %s", err) } p := MercuryObservationProto{Timestamp: uint32(time.Now().Unix())} @@ -144,7 +143,7 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi if obs.MaxFinalizedBlockNumber.Err != nil { obsErrors = append(obsErrors, err) } else if obs.CurrentBlockNum.Err == nil && obs.CurrentBlockNum.Val < obs.MaxFinalizedBlockNumber.Val { - obsErrors = append(obsErrors, pkgerrors.Errorf("failed to observe ValidFromBlockNum; current block number %d (hash: 0x%x) < max finalized block number %d; ignoring observation for out-of-date RPC", obs.CurrentBlockNum.Val, obs.CurrentBlockHash.Val, obs.MaxFinalizedBlockNumber.Val)) + obsErrors = append(obsErrors, fmt.Errorf("failed to observe ValidFromBlockNum; current block number %d (hash: 0x%x) < max finalized block number %d; ignoring observation for out-of-date RPC", obs.CurrentBlockNum.Val, obs.CurrentBlockHash.Val, obs.MaxFinalizedBlockNumber.Val)) } else { p.MaxFinalizedBlockNumber = obs.MaxFinalizedBlockNumber.Val // MaxFinalizedBlockNumber comes as -1 if unset p.MaxFinalizedBlockNumberValid = true @@ -153,30 +152,30 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var bpErr, bidErr, askErr error if obs.BenchmarkPrice.Err != nil { - bpErr = pkgerrors.Wrap(obs.BenchmarkPrice.Err, "failed to observe BenchmarkPrice") + bpErr = fmt.Errorf("failed to observe BenchmarkPrice: %w", obs.BenchmarkPrice.Err) obsErrors = append(obsErrors, bpErr) } else if benchmarkPrice, err := mercury.EncodeValueInt192(obs.BenchmarkPrice.Val); err != nil { - bpErr = pkgerrors.Wrap(err, "failed to observe BenchmarkPrice; encoding failed") + bpErr = fmt.Errorf("failed to observe BenchmarkPrice; encoding failed: %w", err) obsErrors = append(obsErrors, bpErr) } else { p.BenchmarkPrice = benchmarkPrice } if obs.Bid.Err != nil { - bidErr = pkgerrors.Wrap(obs.Bid.Err, "failed to observe Bid") + bidErr = fmt.Errorf("failed to observe Bid: %w", obs.Bid.Err) obsErrors = append(obsErrors, bidErr) } else if bid, err := mercury.EncodeValueInt192(obs.Bid.Val); err != nil { - bidErr = pkgerrors.Wrap(err, "failed to observe Bid; encoding failed") + bidErr = fmt.Errorf("failed to observe Bid; encoding failed: %w", err) obsErrors = append(obsErrors, bidErr) } else { p.Bid = bid } if obs.Ask.Err != nil { - askErr = pkgerrors.Wrap(obs.Ask.Err, "failed to observe Ask") + askErr = fmt.Errorf("failed to observe Ask: %w", obs.Ask.Err) obsErrors = append(obsErrors, askErr) } else if ask, err := mercury.EncodeValueInt192(obs.Ask.Val); err != nil { - askErr = pkgerrors.Wrap(err, "failed to observe Ask; encoding failed") + askErr = fmt.Errorf("failed to observe Ask; encoding failed: %w", err) obsErrors = append(obsErrors, askErr) } else { p.Ask = ask @@ -187,19 +186,19 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi } if obs.CurrentBlockNum.Err != nil { - obsErrors = append(obsErrors, pkgerrors.Wrap(obs.CurrentBlockNum.Err, "failed to observe CurrentBlockNum")) + obsErrors = append(obsErrors, fmt.Errorf("failed to observe CurrentBlockNum: %w", obs.CurrentBlockNum.Err)) } else { p.CurrentBlockNum = obs.CurrentBlockNum.Val } if obs.CurrentBlockHash.Err != nil { - obsErrors = append(obsErrors, pkgerrors.Wrap(obs.CurrentBlockHash.Err, "failed to observe CurrentBlockHash")) + obsErrors = append(obsErrors, fmt.Errorf("failed to observe CurrentBlockHash: %w", obs.CurrentBlockHash.Err)) } else { p.CurrentBlockHash = obs.CurrentBlockHash.Val } if obs.CurrentBlockTimestamp.Err != nil { - obsErrors = append(obsErrors, pkgerrors.Wrap(obs.CurrentBlockTimestamp.Err, "failed to observe CurrentBlockTimestamp")) + obsErrors = append(obsErrors, fmt.Errorf("failed to observe CurrentBlockTimestamp: %w", obs.CurrentBlockTimestamp.Err)) } else { p.CurrentBlockTimestamp = obs.CurrentBlockTimestamp.Val } @@ -227,7 +226,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var pao parsedAttributedObservation var obs MercuryObservationProto if err := proto.Unmarshal(ao.Observation, &obs); err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("attributed observation cannot be unmarshaled: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("attributed observation cannot be unmarshaled: %s", err) } pao.Timestamp = obs.Timestamp @@ -237,22 +236,22 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.BenchmarkPrice, err = mercury.DecodeValueInt192(obs.BenchmarkPrice) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) } pao.Bid, err = mercury.DecodeValueInt192(obs.Bid) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("bid cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("bid cannot be converted to big.Int: %s", err) } pao.Ask, err = mercury.DecodeValueInt192(obs.Ask) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("ask cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("ask cannot be converted to big.Int: %s", err) } pao.PricesValid = true } if len(obs.LatestBlocks) > 0 { if len(obs.LatestBlocks) > MaxAllowedBlocks { - return parsedAttributedObservation{}, pkgerrors.Errorf("LatestBlocks too large; got: %d, max: %d", len(obs.LatestBlocks), MaxAllowedBlocks) + return parsedAttributedObservation{}, fmt.Errorf("LatestBlocks too large; got: %d, max: %d", len(obs.LatestBlocks), MaxAllowedBlocks) } for _, b := range obs.LatestBlocks { pao.LatestBlocks = append(pao.LatestBlocks, v1.NewBlock(b.Num, b.Hash, b.Ts)) @@ -264,19 +263,19 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { hashes := make(map[string]struct{}, len(pao.LatestBlocks)) for _, block := range pao.LatestBlocks { if _, exists := nums[block.Num]; exists { - return parsedAttributedObservation{}, pkgerrors.Errorf("observation invalid for observer %d; got duplicate block number: %d", ao.Observer, block.Num) + return parsedAttributedObservation{}, fmt.Errorf("observation invalid for observer %d; got duplicate block number: %d", ao.Observer, block.Num) } if _, exists := hashes[block.Hash]; exists { - return parsedAttributedObservation{}, pkgerrors.Errorf("observation invalid for observer %d; got duplicate block hash: 0x%x", ao.Observer, block.HashBytes()) + return parsedAttributedObservation{}, fmt.Errorf("observation invalid for observer %d; got duplicate block hash: 0x%x", ao.Observer, block.HashBytes()) } nums[block.Num] = struct{}{} hashes[block.Hash] = struct{}{} if len(block.Hash) != mercury.EvmHashLen { - return parsedAttributedObservation{}, pkgerrors.Errorf("wrong len for hash: %d (expected: %d)", len(block.Hash), mercury.EvmHashLen) + return parsedAttributedObservation{}, fmt.Errorf("wrong len for hash: %d (expected: %d)", len(block.Hash), mercury.EvmHashLen) } if block.Num < 0 { - return parsedAttributedObservation{}, pkgerrors.Errorf("negative block number: %d", block.Num) + return parsedAttributedObservation{}, fmt.Errorf("negative block number: %d", block.Num) } } @@ -292,11 +291,11 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { // DEPRECATED // TODO: Remove this handling after deployment (https://smartcontract-it.atlassian.net/browse/MERC-2272) if len(obs.CurrentBlockHash) != mercury.EvmHashLen { - return parsedAttributedObservation{}, pkgerrors.Errorf("wrong len for hash: %d (expected: %d)", len(obs.CurrentBlockHash), mercury.EvmHashLen) + return parsedAttributedObservation{}, fmt.Errorf("wrong len for hash: %d (expected: %d)", len(obs.CurrentBlockHash), mercury.EvmHashLen) } pao.CurrentBlockHash = obs.CurrentBlockHash if obs.CurrentBlockNum < 0 { - return parsedAttributedObservation{}, pkgerrors.Errorf("negative block number: %d", obs.CurrentBlockNum) + return parsedAttributedObservation{}, fmt.Errorf("negative block number: %d", obs.CurrentBlockNum) } pao.CurrentBlockNum = obs.CurrentBlockNum pao.CurrentBlockTimestamp = obs.CurrentBlockTimestamp @@ -337,7 +336,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty // By assumption, we have at most f malicious oracles, so there should be at least f+1 valid paos if !(rp.f+1 <= len(paos)) { - return false, nil, pkgerrors.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) + return false, nil, fmt.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) } rf, err := rp.buildReportFields(previousReport, paos) @@ -365,7 +364,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty return false, nil, err } if !(len(report) <= rp.maxReportLength) { - return false, nil, pkgerrors.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) + return false, nil, fmt.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) } else if len(report) == 0 { return false, nil, errors.New("report may not have zero length (invariant violation)") } @@ -398,16 +397,24 @@ func (rp *reportingPlugin) buildReportFields(previousReport types.Report, paos [ rf.Timestamp = mercury.GetConsensusTimestamp(mPaos) rf.BenchmarkPrice, err = mercury.GetConsensusBenchmarkPrice(mPaos, rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusBenchmarkPrice failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusBenchmarkPrice failed: %w", err)) + } rf.Bid, err = mercury.GetConsensusBid(convertBid(paos), rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusBid failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusBid failed: %w", err)) + } rf.Ask, err = mercury.GetConsensusAsk(convertAsk(paos), rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusAsk failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusAsk failed: %w", err)) + } rf.CurrentBlockHash, rf.CurrentBlockNum, rf.CurrentBlockTimestamp, err = GetConsensusLatestBlock(paos, rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusCurrentBlock failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusCurrentBlock failed: %w", err)) + } return rf, merr } diff --git a/mercury/v1/mercury_test.go b/mercury/v1/mercury_test.go index b3786fa..798fee5 100644 --- a/mercury/v1/mercury_test.go +++ b/mercury/v1/mercury_test.go @@ -3,6 +3,7 @@ package v1 import ( "context" crand "crypto/rand" + "errors" "fmt" "math" "math/big" @@ -12,7 +13,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" @@ -443,7 +443,6 @@ func Test_Plugin_Observation(t *testing.T) { assert.True(t, p.CurrentBlockValid) assert.True(t, p.MaxFinalizedBlockNumberValid) }) - } func newAttributedObservation(t *testing.T, p *MercuryObservationProto) types.AttributedObservation { diff --git a/mercury/v1/validation.go b/mercury/v1/validation.go index eec7594..79574b1 100644 --- a/mercury/v1/validation.go +++ b/mercury/v1/validation.go @@ -3,8 +3,6 @@ package v1 import ( "fmt" - "github.com/pkg/errors" - v1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" "github.com/smartcontractkit/chainlink-data-streams/mercury" @@ -23,7 +21,7 @@ func ValidateCurrentBlock(rf v1.ReportFields) error { } // NOTE: hardcoded ethereum hash if len(rf.CurrentBlockHash) != mercury.EvmHashLen { - return errors.Errorf("invalid length for hash; expected %d (got: %d)", mercury.EvmHashLen, len(rf.CurrentBlockHash)) + return fmt.Errorf("invalid length for hash; expected %d (got: %d)", mercury.EvmHashLen, len(rf.CurrentBlockHash)) } return nil diff --git a/mercury/v2/mercury.go b/mercury/v2/mercury.go index ec5f592..87a4f50 100644 --- a/mercury/v2/mercury.go +++ b/mercury/v2/mercury.go @@ -8,7 +8,6 @@ import ( "math/big" "time" - pkgerrors "github.com/pkg/errors" "google.golang.org/protobuf/proto" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" @@ -123,7 +122,7 @@ var MissingPrice = big.NewInt(-1) func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTimestamp, previousReport types.Report) (types.Observation, error) { obs, err := rp.dataSource.Observe(ctx, repts, previousReport == nil) if err != nil { - return nil, pkgerrors.Errorf("DataSource.Observe returned an error: %s", err) + return nil, fmt.Errorf("DataSource.Observe returned an error: %s", err) } observationTimestamp := time.Now() @@ -135,10 +134,10 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var bpErr error if obs.BenchmarkPrice.Err != nil { - bpErr = pkgerrors.Wrap(obs.BenchmarkPrice.Err, "failed to observe BenchmarkPrice") + bpErr = fmt.Errorf("failed to observe BenchmarkPrice: %w", obs.BenchmarkPrice.Err) obsErrors = append(obsErrors, bpErr) } else if benchmarkPrice, err := mercury.EncodeValueInt192(obs.BenchmarkPrice.Val); err != nil { - bpErr = pkgerrors.Wrapf(err, "failed to encode BenchmarkPrice; val=%s", obs.BenchmarkPrice.Val) + bpErr = fmt.Errorf("failed to encode BenchmarkPrice; val=%s: %w", obs.BenchmarkPrice.Val, err) obsErrors = append(obsErrors, bpErr) } else { p.BenchmarkPrice = benchmarkPrice @@ -147,7 +146,7 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var maxFinalizedTimestampErr error if obs.MaxFinalizedTimestamp.Err != nil { - maxFinalizedTimestampErr = pkgerrors.Wrap(obs.MaxFinalizedTimestamp.Err, "failed to observe MaxFinalizedTimestamp") + maxFinalizedTimestampErr = fmt.Errorf("failed to observe MaxFinalizedTimestamp: %w", obs.MaxFinalizedTimestamp.Err) obsErrors = append(obsErrors, maxFinalizedTimestampErr) } else { p.MaxFinalizedTimestamp = obs.MaxFinalizedTimestamp.Val @@ -156,14 +155,14 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var linkErr error if obs.LinkPrice.Err != nil { - linkErr = pkgerrors.Wrap(obs.LinkPrice.Err, "failed to observe LINK price") + linkErr = fmt.Errorf("failed to observe LINK price: %w", obs.LinkPrice.Err) obsErrors = append(obsErrors, linkErr) } else if obs.LinkPrice.Val.Cmp(MissingPrice) <= 0 { p.LinkFee = mercury.MaxInt192Enc } else { linkFee := mercury.CalculateFee(obs.LinkPrice.Val, rp.offchainConfig.BaseUSDFee) if linkFeeEncoded, err := mercury.EncodeValueInt192(linkFee); err != nil { - linkErr = pkgerrors.Wrapf(err, "failed to encode LINK fee; val=%s", linkFee) + linkErr = fmt.Errorf("failed to encode LINK fee; val=%s: %w", linkFee, err) obsErrors = append(obsErrors, linkErr) } else { p.LinkFee = linkFeeEncoded @@ -176,14 +175,14 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var nativeErr error if obs.NativePrice.Err != nil { - nativeErr = pkgerrors.Wrap(obs.NativePrice.Err, "failed to observe native price") + nativeErr = fmt.Errorf("failed to observe native price: %w", obs.NativePrice.Err) obsErrors = append(obsErrors, nativeErr) } else if obs.NativePrice.Val.Cmp(MissingPrice) <= 0 { p.NativeFee = mercury.MaxInt192Enc } else { nativeFee := mercury.CalculateFee(obs.NativePrice.Val, rp.offchainConfig.BaseUSDFee) if nativeFeeEncoded, err := mercury.EncodeValueInt192(nativeFee); err != nil { - nativeErr = pkgerrors.Wrapf(err, "failed to encode native fee; val=%s", nativeFee) + nativeErr = fmt.Errorf("failed to encode native fee; val=%s: %w", nativeFee, err) obsErrors = append(obsErrors, nativeErr) } else { p.NativeFee = nativeFeeEncoded @@ -205,7 +204,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var pao parsedAttributedObservation var obs MercuryObservationProto if err := proto.Unmarshal(ao.Observation, &obs); err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("attributed observation cannot be unmarshaled: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("attributed observation cannot be unmarshaled: %s", err) } pao.Timestamp = obs.Timestamp @@ -215,7 +214,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.BenchmarkPrice, err = mercury.DecodeValueInt192(obs.BenchmarkPrice) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) } pao.PricesValid = true } @@ -229,7 +228,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.LinkFee, err = mercury.DecodeValueInt192(obs.LinkFee) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("link price cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("link price cannot be converted to big.Int: %s", err) } pao.LinkFeeValid = true } @@ -237,7 +236,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.NativeFee, err = mercury.DecodeValueInt192(obs.NativeFee) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("native price cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("native price cannot be converted to big.Int: %s", err) } pao.NativeFeeValid = true } @@ -271,7 +270,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty // By assumption, we have at most f malicious oracles, so there should be at least f+1 valid paos if !(rp.f+1 <= len(paos)) { - return false, nil, pkgerrors.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) + return false, nil, fmt.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) } rf, err := rp.buildReportFields(previousReport, paos) @@ -298,7 +297,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty } if !(len(report) <= rp.maxReportLength) { - return false, nil, pkgerrors.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) + return false, nil, fmt.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) } else if len(report) == 0 { return false, nil, errors.New("report may not have zero length (invariant violation)") } @@ -333,7 +332,9 @@ func (rp *reportingPlugin) buildReportFields(previousReport types.Report, paos [ } rf.BenchmarkPrice, err = mercury.GetConsensusBenchmarkPrice(mPaos, rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusBenchmarkPrice failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusBenchmarkPrice failed: %w", err)) + } rf.LinkFee, err = mercury.GetConsensusLinkFee(convertLinkFee(paos), rp.f) if err != nil { diff --git a/mercury/v2/mercury_test.go b/mercury/v2/mercury_test.go index 0bf6984..4f87408 100644 --- a/mercury/v2/mercury_test.go +++ b/mercury/v2/mercury_test.go @@ -2,6 +2,7 @@ package v2 import ( "context" + "errors" "math" "math/big" "math/rand" @@ -9,7 +10,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -272,7 +272,6 @@ func Test_Plugin_Report(t *testing.T) { BenchmarkPrice: big.NewInt(345), }, *codec.builtReportFields) }) - }) t.Run("when previous report is present", func(t *testing.T) { @@ -304,7 +303,6 @@ func Test_Plugin_Report(t *testing.T) { ExpiresAt: ts + 1, BenchmarkPrice: big.NewInt(345), }, *codec.builtReportFields) - }) t.Run("errors if cannot extract timestamp from previous report", func(t *testing.T) { codec.err = errors.New("something exploded trying to extract timestamp") diff --git a/mercury/v3/mercury.go b/mercury/v3/mercury.go index 853b7a1..9853ebc 100644 --- a/mercury/v3/mercury.go +++ b/mercury/v3/mercury.go @@ -8,7 +8,6 @@ import ( "math/big" "time" - pkgerrors "github.com/pkg/errors" "google.golang.org/protobuf/proto" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -125,7 +124,7 @@ var MissingPrice = big.NewInt(-1) func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTimestamp, previousReport types.Report) (types.Observation, error) { obs, err := rp.dataSource.Observe(ctx, repts, previousReport == nil) if err != nil { - return nil, pkgerrors.Errorf("DataSource.Observe returned an error: %s", err) + return nil, fmt.Errorf("DataSource.Observe returned an error: %s", err) } observationTimestamp := time.Now() @@ -137,30 +136,30 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var bpErr, bidErr, askErr error if obs.BenchmarkPrice.Err != nil { - bpErr = pkgerrors.Wrap(obs.BenchmarkPrice.Err, "failed to observe BenchmarkPrice") + bpErr = fmt.Errorf("failed to observe BenchmarkPrice: %w", obs.BenchmarkPrice.Err) obsErrors = append(obsErrors, bpErr) } else if benchmarkPrice, err := mercury.EncodeValueInt192(obs.BenchmarkPrice.Val); err != nil { - bpErr = pkgerrors.Wrapf(err, "failed to encode BenchmarkPrice; val=%s", obs.BenchmarkPrice.Val) + bpErr = fmt.Errorf("failed to encode BenchmarkPrice; val=%s: %w", obs.BenchmarkPrice.Val, err) obsErrors = append(obsErrors, bpErr) } else { p.BenchmarkPrice = benchmarkPrice } if obs.Bid.Err != nil { - bidErr = pkgerrors.Wrap(obs.Bid.Err, "failed to observe Bid") + bidErr = fmt.Errorf("failed to observe Bid: %w", obs.Bid.Err) obsErrors = append(obsErrors, bidErr) } else if bid, err := mercury.EncodeValueInt192(obs.Bid.Val); err != nil { - bidErr = pkgerrors.Wrapf(err, "failed to encode Bid; val=%s", obs.Bid.Val) + bidErr = fmt.Errorf("failed to encode Bid; val=%s: %w", obs.Bid.Val, err) obsErrors = append(obsErrors, bidErr) } else { p.Bid = bid } if obs.Ask.Err != nil { - askErr = pkgerrors.Wrap(obs.Ask.Err, "failed to observe Ask") + askErr = fmt.Errorf("failed to observe Ask: %w", obs.Ask.Err) obsErrors = append(obsErrors, askErr) } else if ask, err := mercury.EncodeValueInt192(obs.Ask.Val); err != nil { - askErr = pkgerrors.Wrapf(err, "failed to encode Ask; val=%s", obs.Ask.Val) + askErr = fmt.Errorf("failed to encode Ask; val=%s: %w", obs.Ask.Val, err) obsErrors = append(obsErrors, askErr) } else { p.Ask = ask @@ -172,7 +171,7 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var maxFinalizedTimestampErr error if obs.MaxFinalizedTimestamp.Err != nil { - maxFinalizedTimestampErr = pkgerrors.Wrap(obs.MaxFinalizedTimestamp.Err, "failed to observe MaxFinalizedTimestamp") + maxFinalizedTimestampErr = fmt.Errorf("failed to observe MaxFinalizedTimestamp: %w", obs.MaxFinalizedTimestamp.Err) obsErrors = append(obsErrors, maxFinalizedTimestampErr) } else { p.MaxFinalizedTimestamp = obs.MaxFinalizedTimestamp.Val @@ -181,14 +180,14 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var linkErr error if obs.LinkPrice.Err != nil { - linkErr = pkgerrors.Wrap(obs.LinkPrice.Err, "failed to observe LINK price") + linkErr = fmt.Errorf("failed to observe LINK price: %w", obs.LinkPrice.Err) obsErrors = append(obsErrors, linkErr) } else if obs.LinkPrice.Val.Cmp(MissingPrice) <= 0 { p.LinkFee = mercury.MaxInt192Enc } else { linkFee := mercury.CalculateFee(obs.LinkPrice.Val, rp.offchainConfig.BaseUSDFee) if linkFeeEncoded, err := mercury.EncodeValueInt192(linkFee); err != nil { - linkErr = pkgerrors.Wrapf(err, "failed to encode LINK fee; val=%s", linkFee) + linkErr = fmt.Errorf("failed to encode LINK fee; val=%s: %w", linkFee, err) obsErrors = append(obsErrors, linkErr) } else { p.LinkFee = linkFeeEncoded @@ -201,14 +200,14 @@ func (rp *reportingPlugin) Observation(ctx context.Context, repts types.ReportTi var nativeErr error if obs.NativePrice.Err != nil { - nativeErr = pkgerrors.Wrap(obs.NativePrice.Err, "failed to observe native price") + nativeErr = fmt.Errorf("failed to observe native price: %w", obs.NativePrice.Err) obsErrors = append(obsErrors, nativeErr) } else if obs.NativePrice.Val.Cmp(MissingPrice) <= 0 { p.NativeFee = mercury.MaxInt192Enc } else { nativeFee := mercury.CalculateFee(obs.NativePrice.Val, rp.offchainConfig.BaseUSDFee) if nativeFeeEncoded, err := mercury.EncodeValueInt192(nativeFee); err != nil { - nativeErr = pkgerrors.Wrapf(err, "failed to encode native fee; val=%s", nativeFee) + nativeErr = fmt.Errorf("failed to encode native fee; val=%s: %w", nativeFee, err) obsErrors = append(obsErrors, nativeErr) } else { p.NativeFee = nativeFeeEncoded @@ -230,7 +229,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var pao parsedAttributedObservation var obs MercuryObservationProto if err := proto.Unmarshal(ao.Observation, &obs); err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("attributed observation cannot be unmarshaled: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("attributed observation cannot be unmarshaled: %s", err) } pao.Timestamp = obs.Timestamp @@ -240,15 +239,15 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.BenchmarkPrice, err = mercury.DecodeValueInt192(obs.BenchmarkPrice) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("benchmarkPrice cannot be converted to big.Int: %s", err) } pao.Bid, err = mercury.DecodeValueInt192(obs.Bid) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("bid cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("bid cannot be converted to big.Int: %s", err) } pao.Ask, err = mercury.DecodeValueInt192(obs.Ask) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("ask cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("ask cannot be converted to big.Int: %s", err) } pao.PricesValid = true } @@ -262,7 +261,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.LinkFee, err = mercury.DecodeValueInt192(obs.LinkFee) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("link price cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("link price cannot be converted to big.Int: %s", err) } pao.LinkFeeValid = true } @@ -270,7 +269,7 @@ func parseAttributedObservation(ao types.AttributedObservation) (PAO, error) { var err error pao.NativeFee, err = mercury.DecodeValueInt192(obs.NativeFee) if err != nil { - return parsedAttributedObservation{}, pkgerrors.Errorf("native price cannot be converted to big.Int: %s", err) + return parsedAttributedObservation{}, fmt.Errorf("native price cannot be converted to big.Int: %s", err) } pao.NativeFeeValid = true } @@ -304,7 +303,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty // By assumption, we have at most f malicious oracles, so there should be at least f+1 valid paos if !(rp.f+1 <= len(paos)) { - return false, nil, pkgerrors.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) + return false, nil, fmt.Errorf("only received %v valid attributed observations, but need at least f+1 (%v)", len(paos), rp.f+1) } rf, err := rp.buildReportFields(previousReport, paos) @@ -331,7 +330,7 @@ func (rp *reportingPlugin) Report(repts types.ReportTimestamp, previousReport ty } if !(len(report) <= rp.maxReportLength) { - return false, nil, pkgerrors.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) + return false, nil, fmt.Errorf("report with len %d violates MaxReportLength limit set by ReportCodec (%d)", len(report), rp.maxReportLength) } else if len(report) == 0 { return false, nil, errors.New("report may not have zero length (invariant violation)") } @@ -366,13 +365,19 @@ func (rp *reportingPlugin) buildReportFields(previousReport types.Report, paos [ } rf.BenchmarkPrice, err = mercury.GetConsensusBenchmarkPrice(mPaos, rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusBenchmarkPrice failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusBenchmarkPrice failed: %w", err)) + } rf.Bid, err = mercury.GetConsensusBid(convertBid(paos), rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusBid failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusBid failed: %w", err)) + } rf.Ask, err = mercury.GetConsensusAsk(convertAsk(paos), rp.f) - merr = errors.Join(merr, pkgerrors.Wrap(err, "GetConsensusAsk failed")) + if err != nil { + merr = errors.Join(merr, fmt.Errorf("GetConsensusAsk failed: %w", err)) + } rf.LinkFee, err = mercury.GetConsensusLinkFee(convertLinkFee(paos), rp.f) if err != nil { diff --git a/mercury/v3/mercury_test.go b/mercury/v3/mercury_test.go index 1d01f61..2df6e73 100644 --- a/mercury/v3/mercury_test.go +++ b/mercury/v3/mercury_test.go @@ -2,6 +2,7 @@ package v3 import ( "context" + "errors" "math" "math/big" "math/rand" @@ -9,7 +10,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -289,7 +289,6 @@ func Test_Plugin_Report(t *testing.T) { Ask: big.NewInt(350), }, *codec.builtReportFields) }) - }) t.Run("when previous report is present", func(t *testing.T) { @@ -323,7 +322,6 @@ func Test_Plugin_Report(t *testing.T) { Bid: big.NewInt(340), Ask: big.NewInt(350), }, *codec.builtReportFields) - }) t.Run("errors if cannot extract timestamp from previous report", func(t *testing.T) { codec.err = errors.New("something exploded trying to extract timestamp") diff --git a/mercury/validation.go b/mercury/validation.go index d566631..a059630 100644 --- a/mercury/validation.go +++ b/mercury/validation.go @@ -3,8 +3,6 @@ package mercury import ( "fmt" "math/big" - - pkgerrors "github.com/pkg/errors" ) // NOTE: hardcoded for now, this may need to change if we support block range on chains other than eth @@ -16,7 +14,7 @@ func ValidateBetween(name string, answer *big.Int, min, max *big.Int) error { return fmt.Errorf("%s: got nil value", name) } if !(min.Cmp(answer) <= 0 && answer.Cmp(max) <= 0) { - return pkgerrors.Errorf("%s (Value: %s) is outside of allowable range (Min: %s, Max: %s)", name, answer, min, max) + return fmt.Errorf("%s (Value: %s) is outside of allowable range (Min: %s, Max: %s)", name, answer, min, max) } return nil @@ -24,7 +22,7 @@ func ValidateBetween(name string, answer *big.Int, min, max *big.Int) error { func ValidateValidFromTimestamp(observationTimestamp uint32, validFromTimestamp uint32) error { if observationTimestamp < validFromTimestamp { - return pkgerrors.Errorf("observationTimestamp (Value: %d) must be >= validFromTimestamp (Value: %d)", observationTimestamp, validFromTimestamp) + return fmt.Errorf("observationTimestamp (Value: %d) must be >= validFromTimestamp (Value: %d)", observationTimestamp, validFromTimestamp) } return nil @@ -32,7 +30,7 @@ func ValidateValidFromTimestamp(observationTimestamp uint32, validFromTimestamp func ValidateExpiresAt(observationTimestamp uint32, expiresAt uint32) error { if observationTimestamp > expiresAt { - return pkgerrors.Errorf("expiresAt (Value: %d) must be ahead of observation timestamp (Value: %d)", expiresAt, observationTimestamp) + return fmt.Errorf("expiresAt (Value: %d) must be ahead of observation timestamp (Value: %d)", expiresAt, observationTimestamp) } return nil