From af41868e87212ca87bc5515cba2ea9eac9021748 Mon Sep 17 00:00:00 2001 From: Ryan Stout Date: Fri, 9 Aug 2024 09:10:46 -0700 Subject: [PATCH] Clean up --- commitrmnocb/observation.go | 149 +++++---------------------- commitrmnocb/outcome.go | 111 +++++--------------- commitrmnocb/plugin.go | 21 ++-- commitrmnocb/query.go | 28 +---- commitrmnocb/report.go | 7 +- commitrmnocb/types.go | 78 +++++--------- commitrmnocb/validate_observation.go | 4 +- plugintypes/commit.go | 11 +- 8 files changed, 94 insertions(+), 315 deletions(-) diff --git a/commitrmnocb/observation.go b/commitrmnocb/observation.go index 9a43a853a..ea57b254a 100644 --- a/commitrmnocb/observation.go +++ b/commitrmnocb/observation.go @@ -8,12 +8,12 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink-ccip/plugintypes" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-ccip/plugintypes" ) func (p *Plugin) ObservationQuorum(_ ocr3types.OutcomeContext, _ types.Query) (ocr3types.Quorum, error) { @@ -26,56 +26,40 @@ func (p *Plugin) Observation( ) (types.Observation, error) { previousOutcome, nextState := p.decodeOutcome(outCtx.PreviousOutcome) - observation := CommitPluginObservation{} + observation := Observation{} switch nextState { case SelectingRangesForReport: offRampNextSeqNums := p.ObserveOffRampNextSeqNums(ctx) - observation = CommitPluginObservation{ - OnRampMaxSeqNums: offRampNextSeqNums, // TODO: change + observation = Observation{ + OnRampMaxSeqNums: offRampNextSeqNums, OffRampNextSeqNums: offRampNextSeqNums, FChain: p.ObserveFChain(), } case BuildingReport: - observation = CommitPluginObservation{ + observation = Observation{ MerkleRoots: p.ObserveMerkleRoots(ctx, previousOutcome.RangesSelectedForReport), - GasPrices: p.ObserveGasPrices(ctx), - TokenPrices: p.ObserveTokenPrices(ctx), + GasPrices: []cciptypes.GasPriceChain{}, + TokenPrices: []cciptypes.TokenPrice{}, FChain: p.ObserveFChain(), } case WaitingForReportTransmission: - observation = CommitPluginObservation{ + observation = Observation{ OffRampNextSeqNums: p.ObserveOffRampNextSeqNums(ctx), FChain: p.ObserveFChain(), } default: p.lggr.Warnw("Unexpected state", "state", nextState) - return types.Observation{}, nil + return observation.Encode() } p.lggr.Infow("Observation", "observation", observation) return observation.Encode() } -// ObserveOnRampMaxSeqNums Simply add NewMsgScanBatchSize to the offRampNextSeqNums -// TODO: read from the source chain OnRamps to get their OnRampMaxSeqNums -func (p *Plugin) ObserveOnRampMaxSeqNums(offRampNextSeqNums []plugintypes.SeqNumChain) []plugintypes.SeqNumChain { - onRampMaxSeqNums := make([]plugintypes.SeqNumChain, len(offRampNextSeqNums)) - copy(onRampMaxSeqNums, offRampNextSeqNums) - - for i := range onRampMaxSeqNums { - onRampMaxSeqNums[i] = plugintypes.NewSeqNumChain( - onRampMaxSeqNums[i].ChainSel, - onRampMaxSeqNums[i].SeqNum+cciptypes.SeqNum(p.cfg.NewMsgScanBatchSize), - ) - } - - return onRampMaxSeqNums -} - -// ObserveOffRampNextSeqNums TODO: impl +// ObserveOffRampNextSeqNums Observe the next sequence numbers for each source chain from the OffRamp func (p *Plugin) ObserveOffRampNextSeqNums(ctx context.Context) []plugintypes.SeqNumChain { supportsDestChain, err := p.supportsDestChain(p.nodeID) if err != nil { @@ -108,7 +92,7 @@ func (p *Plugin) ObserveOffRampNextSeqNums(ctx context.Context) []plugintypes.Se return nil } -// ObserveMerkleRoots TODO: doc +// ObserveMerkleRoots Compute the merkle roots for the given sequence number ranges func (p *Plugin) ObserveMerkleRoots(ctx context.Context, ranges []ChainRange) []cciptypes.MerkleRootChain { roots := make([]cciptypes.MerkleRootChain, 0) supportedChains, err := p.supportedChains(p.nodeID) @@ -143,44 +127,31 @@ func (p *Plugin) ObserveMerkleRoots(ctx context.Context, ranges []ChainRange) [] // computeMerkleRoot Compute the merkle root of a list of messages func (p *Plugin) computeMerkleRoot(ctx context.Context, msgs []cciptypes.Message) (cciptypes.Bytes32, error) { - msgSeqNumToHash := make(map[cciptypes.SeqNum]cciptypes.Bytes32) - seqNums := make([]cciptypes.SeqNum, 0) + hashes := make([][32]byte, 0) + sort.Slice(msgs, func(i, j int) bool { return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber }) + + for i, msg := range msgs { + // Assert there are no sequence number gaps in msgs + if i > 0 { + if msg.Header.SequenceNumber != msgs[i-1].Header.SequenceNumber+1 { + return [32]byte{}, fmt.Errorf("found non-consecutive sequence numbers when computing merkle root, "+ + "gap between sequence nums %d and %d, messages: %v", msgs[i-1].Header.SequenceNumber, + msg.Header.SequenceNumber, msgs) + } + } - for _, msg := range msgs { msgHash, err := p.msgHasher.Hash(ctx, msg) if err != nil { p.lggr.Warnw("failed to hash message", "msg", msg, "err", err) return cciptypes.Bytes32{}, err } - seqNum := msg.Header.SequenceNumber - seqNums = append(seqNums, seqNum) - msgSeqNumToHash[seqNum] = msgHash - } - - sort.Slice(seqNums, func(i, j int) bool { return seqNums[i] < seqNums[j] }) - - // Assert there are no gaps in the seq num range - if len(seqNums) >= 2 { - for i := 1; i < len(seqNums); i++ { - if seqNums[i] != seqNums[i-1]+1 { - return [32]byte{}, fmt.Errorf("found non-consecutive sequence numbers when computing merkle root, "+ - "gap between seq nums %d and %d, messages: %v", seqNums[i-1], seqNums[i], msgs) - } - } - } - treeLeaves := make([][32]byte, 0) - for _, seqNum := range seqNums { - msgHash, ok := msgSeqNumToHash[seqNum] - if !ok { - return [32]byte{}, fmt.Errorf("msg hash not found for seq num %d", seqNum) - } - treeLeaves = append(treeLeaves, msgHash) + hashes = append(hashes, msgHash) } - tree, err := merklemulti.NewTree(hashutil.NewKeccak(), treeLeaves) + tree, err := merklemulti.NewTree(hashutil.NewKeccak(), hashes) if err != nil { - return [32]byte{}, fmt.Errorf("failed to construct merkle tree from %d leaves: %w", len(treeLeaves), err) + return [32]byte{}, fmt.Errorf("failed to construct merkle tree from %d leaves: %w", len(hashes), err) } root := tree.Root() @@ -189,72 +160,6 @@ func (p *Plugin) computeMerkleRoot(ctx context.Context, msgs []cciptypes.Message return root, nil } -// ObserveGasPrices TODO: doc -func (p *Plugin) ObserveGasPrices(ctx context.Context) []cciptypes.GasPriceChain { - // TODO: Should this be sourceChains or supportedChains? - chains := p.knownSourceChainsSlice() - if len(chains) == 0 { - return []cciptypes.GasPriceChain{} - } - - gasPrices, err := p.ccipReader.GasPrices(ctx, chains) - if err != nil { - p.lggr.Warnw("failed to get gas prices", "err", err) - return []cciptypes.GasPriceChain{} - } - - if len(gasPrices) != len(chains) { - p.lggr.Warnw( - "gas prices length mismatch", - "len(gasPrices)", len(gasPrices), - "len(chains)", len(chains), - ) - return []cciptypes.GasPriceChain{} - } - - gasPricesGwei := make([]cciptypes.GasPriceChain, 0, len(chains)) - for i, chain := range chains { - gasPricesGwei = append(gasPricesGwei, cciptypes.NewGasPriceChain(gasPrices[i].Int, chain)) - } - - return gasPricesGwei -} - -// ObserveTokenPrices TODO: doc -func (p *Plugin) ObserveTokenPrices(ctx context.Context) []cciptypes.TokenPrice { - tokenPrices, err := p.observeTokenPricesHelper(ctx) - if err != nil { - p.lggr.Warnw("call to ObserveTokenPrices failed", "err", err) - } - return tokenPrices -} - -// ObserveTokenPricesHelper TODO: doc -func (p *Plugin) observeTokenPricesHelper(ctx context.Context) ([]cciptypes.TokenPrice, error) { - if supportTPChain, err := p.supportsTokenPriceChain(); err == nil && supportTPChain { - tokens := maps.Keys(p.cfg.OffchainConfig.PriceSources) - - tokenPrices, err := p.tokenPricesReader.GetTokenPricesUSD(ctx, tokens) - if err != nil { - return nil, fmt.Errorf("get token prices: %w", err) - } - - if len(tokenPrices) != len(tokens) { - return nil, fmt.Errorf("internal critical error token prices length mismatch: got %d, want %d", - len(tokenPrices), len(tokens)) - } - - tokenPricesUSD := make([]cciptypes.TokenPrice, 0, len(tokens)) - for i, token := range tokens { - tokenPricesUSD = append(tokenPricesUSD, cciptypes.NewTokenPrice(token, tokenPrices[i])) - } - - return tokenPricesUSD, nil - } - - return nil, nil -} - func (p *Plugin) ObserveFChain() map[cciptypes.ChainSelector]int { fChain, err := p.homeChain.GetFChain() if err != nil { diff --git a/commitrmnocb/outcome.go b/commitrmnocb/outcome.go index 2045fb1db..1385418a7 100644 --- a/commitrmnocb/outcome.go +++ b/commitrmnocb/outcome.go @@ -9,7 +9,6 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-ccip/internal/libs/slicelib" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) @@ -21,14 +20,14 @@ func (p *Plugin) Outcome( outCtx ocr3types.OutcomeContext, query types.Query, aos []types.AttributedObservation, ) (ocr3types.Outcome, error) { previousOutcome, nextState := p.decodeOutcome(outCtx.PreviousOutcome) - commitQuery := CommitQuery{} + commitQuery := Query{} consensusObservation, err := p.getConsensusObservation(aos) if err != nil { return ocr3types.Outcome{}, err } - outcome := CommitPluginOutcome{} + outcome := Outcome{} switch nextState { case SelectingRangesForReport: @@ -41,7 +40,8 @@ func (p *Plugin) Outcome( outcome = p.checkForReportTransmission(previousOutcome, consensusObservation) default: - return nil, fmt.Errorf("outcome unexpected state: %d", nextState) + p.lggr.Warnw("Unexpected state in Outcome", "state", nextState) + return outcome.Encode() } p.lggr.Infow("Commit Plugin Outcome", "outcome", outcome, "oid", p.nodeID) @@ -50,9 +50,9 @@ func (p *Plugin) Outcome( // ReportRangesOutcome determines the sequence number ranges for each chain to build a report from in the next round func (p *Plugin) ReportRangesOutcome( - query CommitQuery, + query Query, consensusObservation ConsensusObservation, -) CommitPluginOutcome { +) Outcome { rangesToReport := make([]ChainRange, 0) rmnOnRampMaxSeqNumsMap := make(map[cciptypes.ChainSelector]cciptypes.SeqNum) @@ -85,7 +85,7 @@ func (p *Plugin) ReportRangesOutcome( // We sort here so that Outcome serializes deterministically sort.Slice(rangesToReport, func(i, j int) bool { return rangesToReport[i].ChainSel < rangesToReport[j].ChainSel }) - outcome := CommitPluginOutcome{ + outcome := Outcome{ OutcomeType: ReportIntervalsSelected, RangesSelectedForReport: rangesToReport, } @@ -96,14 +96,9 @@ func (p *Plugin) ReportRangesOutcome( // Given a set of observed merkle roots, gas prices and token prices, and roots from RMN, construct a report // to transmit on-chain func (p *Plugin) buildReport( - query CommitQuery, + _ Query, consensusObservation ConsensusObservation, -) CommitPluginOutcome { - // TODO: Only include chains in the report that have gas prices? - - // TODO: token prices validation - // exclude merkle roots if expected token prices don't exist? - +) Outcome { roots := maps.Values(consensusObservation.MerkleRoots) // We sort here so that Outcome serializes deterministically @@ -116,7 +111,7 @@ func (p *Plugin) buildReport( outcomeType = ReportEmpty } - outcome := CommitPluginOutcome{ + outcome := Outcome{ OutcomeType: outcomeType, RootsToReport: roots, GasPrices: consensusObservation.GasPricesSortedArray(), @@ -130,13 +125,13 @@ func (p *Plugin) buildReport( // were observed when the most recent report was generated. If an update to these max seq sums is detected, it means // that the previous report has been transmitted, and we output ReportTransmitted to dictate that a new report // generation phase should begin. If no update is detected, and we've exhausted our check attempts, output -// ReportNotTransmitted to signify we stop checking for updates and start a new report generation phase. If no update -// is detected, and we haven't exhausted our check attempts, output ReportNotYetTransmitted to signify that we should +// ReportTransmissionFailed to signify we stop checking for updates and start a new report generation phase. If no +// update is detected, and we haven't exhausted our check attempts, output ReportInFlight to signify that we should // check again next round. func (p *Plugin) checkForReportTransmission( - previousOutcome CommitPluginOutcome, + previousOutcome Outcome, consensusObservation ConsensusObservation, -) CommitPluginOutcome { +) Outcome { offRampUpdated := false for _, previousSeqNumChain := range previousOutcome.OffRampNextSeqNums { @@ -149,20 +144,20 @@ func (p *Plugin) checkForReportTransmission( } if offRampUpdated { - return CommitPluginOutcome{ + return Outcome{ OutcomeType: ReportTransmitted, } } if previousOutcome.ReportTransmissionCheckAttempts+1 >= p.cfg.MaxReportTransmissionCheckAttempts { p.lggr.Warnw("Failed to detect report transmission") - return CommitPluginOutcome{ - OutcomeType: ReportNotTransmitted, + return Outcome{ + OutcomeType: ReportTransmissionFailed, } } - return CommitPluginOutcome{ - OutcomeType: ReportNotYetTransmitted, + return Outcome{ + OutcomeType: ReportInFlight, OffRampNextSeqNums: previousOutcome.OffRampNextSeqNums, ReportTransmissionCheckAttempts: previousOutcome.ReportTransmissionCheckAttempts + 1, } @@ -179,17 +174,12 @@ func (p *Plugin) getConsensusObservation(aos []types.AttributedObservation) (Con fmt.Errorf("no consensus value for fDestChain, DestChain: %d", p.cfg.DestChain) } - //fTokenChain, exists := fChains[cciptypes.ChainSelector(p.cfg.OffchainConfig.TokenPriceChainSelector)] - //if !exists { - // return ConsensusObservation{}, - // fmt.Errorf("no consensus value for fTokenChain, TokenPriceChain: %d", - // p.cfg.OffchainConfig.TokenPriceChainSelector) - //} - consensusObs := ConsensusObservation{ - MerkleRoots: p.merkleRootConsensus(aggObs.MerkleRoots, fChains), - GasPrices: make(map[cciptypes.ChainSelector]cciptypes.BigInt), // p.gasPriceConsensus(aggObs.GasPrices, fChains), - TokenPrices: make(map[types.Account]cciptypes.BigInt), // p.tokenPriceConsensus(aggObs.TokenPrices, fTokenChain), + MerkleRoots: p.merkleRootConsensus(aggObs.MerkleRoots, fChains), + // TODO: use consensus of observed gas prices + GasPrices: make(map[cciptypes.ChainSelector]cciptypes.BigInt), + // TODO: use consensus of observed token prices + TokenPrices: make(map[types.Account]cciptypes.BigInt), OnRampMaxSeqNums: p.onRampMaxSeqNumsConsensus(aggObs.OnRampMaxSeqNums, fChains), OffRampNextSeqNums: p.offRampMaxSeqNumsConsensus(aggObs.OffRampNextSeqNums, fDestChain), FChain: fChains, @@ -229,59 +219,6 @@ func (p *Plugin) merkleRootConsensus( return consensus } -// Given a mapping from chains to a list of gas prices, return a mapping from chains to a single consensus gas price. -// The consensus gas price for a given chain is the median gas price if the number of gas price observations is -// greater or equal than 2f+1, where f is the FChain of the corresponding source chain. -func (p *Plugin) gasPriceConsensus( - pricesByChain map[cciptypes.ChainSelector][]cciptypes.BigInt, - fChains map[cciptypes.ChainSelector]int, -) map[cciptypes.ChainSelector]cciptypes.BigInt { - consensus := make(map[cciptypes.ChainSelector]cciptypes.BigInt) - - for chain, prices := range pricesByChain { - if f, exists := fChains[chain]; exists { - if len(prices) < 2*f+1 { - // TODO: metrics - p.lggr.Warnf("could not reach consensus on gas prices for chain %d "+ - "because we did not receive more than 2f+1 observed prices, 2f+1: %d, len(prices): %d, prices: %v", - chain, 2*f+1, len(prices), prices) - } - - consensus[chain] = slicelib.BigIntSortedMiddle(prices) - } else { - // TODO: metrics - p.lggr.Warnf("could not reach consensus on gas prices for chain %d because "+ - "there was no consensus f value for this chain", chain) - } - } - - return consensus -} - -// Given a mapping from token IDs to a list of token prices, return a mapping from token IDs to a single consensus -// token price. The consensus token price for a given token ID is the median token price if the number of token price -// observations is greater or equal than 2f+1, where f is the FChain of the chain that token prices were retrieved -// from. -func (p *Plugin) tokenPriceConsensus( - pricesByToken map[types.Account][]cciptypes.BigInt, - fTokenChain int, -) map[types.Account]cciptypes.BigInt { - consensus := make(map[types.Account]cciptypes.BigInt) - - for tokenID, prices := range pricesByToken { - if len(prices) < 2*fTokenChain+1 { - // TODO: metrics - p.lggr.Warnf("could not reach consensus on token prices for token %s because "+ - "we did not receive more than 2f+1 observed prices, 2f+1: %d, len(prices): %d, prices: %v", - tokenID, 2*fTokenChain+1, len(prices), prices) - } - - consensus[tokenID] = slicelib.BigIntSortedMiddle(prices) - } - - return consensus -} - // Given a mapping from chains to a list of max seq nums on their corresponding OnRamp, return a mapping from chains // to a single max seq num. The consensus max seq num for a given chain is the f'th lowest max seq num if the number // of max seq num observations is greater or equal than 2f+1, where f is the FChain of the corresponding source chain. diff --git a/commitrmnocb/plugin.go b/commitrmnocb/plugin.go index f067101ec..230fd0cbd 100644 --- a/commitrmnocb/plugin.go +++ b/commitrmnocb/plugin.go @@ -11,11 +11,12 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/internal/libs/slicelib" "github.com/smartcontractkit/chainlink-ccip/internal/plugincommon" "github.com/smartcontractkit/chainlink-ccip/internal/reader" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -90,21 +91,20 @@ func (p *Plugin) Close() error { return nil } -func (p *Plugin) decodeOutcome(outcome ocr3types.Outcome) (CommitPluginOutcome, CommitPluginState) { +func (p *Plugin) decodeOutcome(outcome ocr3types.Outcome) (Outcome, CommitPluginState) { if len(outcome) == 0 { - return CommitPluginOutcome{}, SelectingRangesForReport + return Outcome{}, SelectingRangesForReport } decodedOutcome, err := DecodeCommitPluginOutcome(outcome) if err != nil { - p.lggr.Errorw("Failed to decode CommitPluginOutcome", "outcome", outcome, "err", err) - return CommitPluginOutcome{}, SelectingRangesForReport + p.lggr.Errorw("Failed to decode Outcome", "outcome", outcome, "err", err) + return Outcome{}, SelectingRangesForReport } return decodedOutcome, decodedOutcome.NextState() } -// TODO: doc func (p *Plugin) knownSourceChainsSlice() []cciptypes.ChainSelector { knownSourceChains, err := p.homeChain.GetKnownCCIPChains() if err != nil { @@ -143,15 +143,6 @@ func (p *Plugin) supportsDestChain(oracle commontypes.OracleID) (bool, error) { return destChainConfig.SupportedNodes.Contains(p.oracleIDToP2pID[oracle]), nil } -func (p *Plugin) supportsTokenPriceChain() (bool, error) { - tokPriceChainConfig, err := p.homeChain.GetChainConfig( - cciptypes.ChainSelector(p.cfg.OffchainConfig.TokenPriceChainSelector)) - if err != nil { - return false, fmt.Errorf("get token price chain config: %w", err) - } - return tokPriceChainConfig.SupportedNodes.Contains(p.oracleIDToP2pID[p.nodeID]), nil -} - func syncFrequency(configuredValue time.Duration) time.Duration { if configuredValue.Milliseconds() == 0 { return 10 * time.Second diff --git a/commitrmnocb/query.go b/commitrmnocb/query.go index 24fa8f847..471e0e228 100644 --- a/commitrmnocb/query.go +++ b/commitrmnocb/query.go @@ -5,34 +5,8 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-ccip/plugintypes" ) -// Query Depending on the current state, queries RMN for sequence numbers or signed roots func (p *Plugin) Query(_ context.Context, outCtx ocr3types.OutcomeContext) (types.Query, error) { - _, nextState := p.decodeOutcome(outCtx.PreviousOutcome) - - switch nextState { - case SelectingRangesForReport: - return p.BuildRmnSeqNumsQuery() - - case BuildingReport: - return types.Query{}, nil - - default: - return types.Query{}, nil - } -} - -// BuildRmnSeqNumsQuery builds a Query that contains OnRamp max seq nums from RMN -func (p *Plugin) BuildRmnSeqNumsQuery() (types.Query, error) { - rmnMaxSourceSeqNums := make([]plugintypes.SeqNumChain, 0) - - encodedQuery, err := NewCommitQuery(rmnMaxSourceSeqNums, nil).Encode() - if err != nil { - return types.Query{}, err - } - - return encodedQuery, nil + return types.Query{}, nil } diff --git a/commitrmnocb/report.go b/commitrmnocb/report.go index 6ad8c0f73..eb0f214c9 100644 --- a/commitrmnocb/report.go +++ b/commitrmnocb/report.go @@ -6,16 +6,17 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - "github.com/smartcontractkit/chainlink-ccip/commit" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-ccip/commit" ) func (p *Plugin) Reports(seqNr uint64, outcomeBytes ocr3types.Outcome) ([]ocr3types.ReportWithInfo[[]byte], error) { outcome, err := DecodeCommitPluginOutcome(outcomeBytes) if err != nil { // TODO: metrics - p.lggr.Errorw("failed to decode CommitPluginOutcome", "outcomeBytes", outcomeBytes, "err", err) - return nil, fmt.Errorf("failed to decode CommitPluginOutcome: %w", err) + p.lggr.Errorw("failed to decode Outcome", "outcomeBytes", outcomeBytes, "err", err) + return nil, fmt.Errorf("failed to decode Outcome: %w", err) } if outcome.OutcomeType != ReportGenerated { diff --git a/commitrmnocb/types.go b/commitrmnocb/types.go index ac216add1..7548cefa2 100644 --- a/commitrmnocb/types.go +++ b/commitrmnocb/types.go @@ -12,33 +12,29 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) -type RmnSig struct { - sig []byte -} - -type CommitQuery struct { +type Query struct { RmnOnRampMaxSeqNums []plugintypes.SeqNumChain MerkleRoots []cciptypes.MerkleRootChain } -func (q CommitQuery) Encode() ([]byte, error) { +func (q Query) Encode() ([]byte, error) { return json.Marshal(q) } -func DecodeCommitPluginQuery(encodedQuery []byte) (CommitQuery, error) { - q := CommitQuery{} +func DecodeCommitPluginQuery(encodedQuery []byte) (Query, error) { + q := Query{} err := json.Unmarshal(encodedQuery, &q) return q, err } -func NewCommitQuery(rmnOnRampMaxSeqNums []plugintypes.SeqNumChain, merkleRoots []cciptypes.MerkleRootChain) CommitQuery { - return CommitQuery{ +func NewCommitQuery(rmnOnRampMaxSeqNums []plugintypes.SeqNumChain, merkleRoots []cciptypes.MerkleRootChain) Query { + return Query{ RmnOnRampMaxSeqNums: rmnOnRampMaxSeqNums, MerkleRoots: merkleRoots, } } -type CommitPluginObservation struct { +type Observation struct { MerkleRoots []cciptypes.MerkleRootChain `json:"merkleRoots"` GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` TokenPrices []cciptypes.TokenPrice `json:"tokenPrices"` @@ -47,17 +43,17 @@ type CommitPluginObservation struct { FChain map[cciptypes.ChainSelector]int `json:"fChain"` } -func (obs CommitPluginObservation) Encode() ([]byte, error) { +func (obs Observation) Encode() ([]byte, error) { encodedObservation, err := json.Marshal(obs) if err != nil { - return nil, fmt.Errorf("failed to encode CommitPluginObservation: %w", err) + return nil, fmt.Errorf("failed to encode Observation: %w", err) } return encodedObservation, nil } -func DecodeCommitPluginObservation(encodedObservation []byte) (CommitPluginObservation, error) { - o := CommitPluginObservation{} +func DecodeCommitPluginObservation(encodedObservation []byte) (Observation, error) { + o := Observation{} err := json.Unmarshal(encodedObservation, &o) return o, err } @@ -189,19 +185,19 @@ func (co ConsensusObservation) TokenPricesSortedArray() []cciptypes.TokenPrice { return tokenPrices } -type CommitPluginOutcomeType int +type OutcomeType int const ( - ReportIntervalsSelected CommitPluginOutcomeType = iota + ReportIntervalsSelected OutcomeType = iota ReportGenerated ReportEmpty - ReportNotYetTransmitted + ReportInFlight ReportTransmitted - ReportNotTransmitted + ReportTransmissionFailed ) -type CommitPluginOutcome struct { - OutcomeType CommitPluginOutcomeType `json:"outcomeType"` +type Outcome struct { + OutcomeType OutcomeType `json:"outcomeType"` RangesSelectedForReport []ChainRange `json:"rangesSelectedForReport"` RootsToReport []cciptypes.MerkleRootChain `json:"rootsToReport"` OffRampNextSeqNums []plugintypes.SeqNumChain `json:"offRampNextSeqNums"` @@ -211,22 +207,22 @@ type CommitPluginOutcome struct { } // Encode TODO: sort all lists here to ensure deterministic serialization -func (o CommitPluginOutcome) Encode() ([]byte, error) { +func (o Outcome) Encode() ([]byte, error) { encodedOutcome, err := json.Marshal(o) if err != nil { - return nil, fmt.Errorf("failed to encode CommitPluginOutcome: %w", err) + return nil, fmt.Errorf("failed to encode Outcome: %w", err) } return encodedOutcome, nil } -func DecodeCommitPluginOutcome(b []byte) (CommitPluginOutcome, error) { - o := CommitPluginOutcome{} +func DecodeCommitPluginOutcome(b []byte) (Outcome, error) { + o := Outcome{} err := json.Unmarshal(b, &o) return o, err } -func (o CommitPluginOutcome) NextState() CommitPluginState { +func (o Outcome) NextState() CommitPluginState { switch o.OutcomeType { case ReportIntervalsSelected: return BuildingReport @@ -234,11 +230,11 @@ func (o CommitPluginOutcome) NextState() CommitPluginState { return WaitingForReportTransmission case ReportEmpty: return SelectingRangesForReport - case ReportNotYetTransmitted: + case ReportInFlight: return WaitingForReportTransmission case ReportTransmitted: return SelectingRangesForReport - case ReportNotTransmitted: + case ReportTransmissionFailed: return SelectingRangesForReport default: return SelectingRangesForReport @@ -257,29 +253,3 @@ type ChainRange struct { ChainSel cciptypes.ChainSelector `json:"chain"` SeqNumRange cciptypes.SeqNumRange `json:"seqNumRange"` } - -// CommitPluginReport is the report that will be transmitted by the Commit Plugin -type CommitPluginReport struct { - MerkleRoots []cciptypes.MerkleRootChain - TokenPrices []cciptypes.TokenPrice `json:"tokenPrices"` - GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` -} - -func (r CommitPluginReport) IsEmpty() bool { - return len(r.MerkleRoots) == 0 && len(r.TokenPrices) == 0 && len(r.GasPrices) == 0 -} - -func (r CommitPluginReport) Encode() ([]byte, error) { - encodedReport, err := json.Marshal(r) - if err != nil { - return nil, fmt.Errorf("failed to encode CommitPluginReport: %w", err) - } - - return encodedReport, nil -} - -func DecodeCommitPluginReport(b []byte) (CommitPluginReport, error) { - r := CommitPluginReport{} - err := json.Unmarshal(b, &r) - return r, err -} diff --git a/commitrmnocb/validate_observation.go b/commitrmnocb/validate_observation.go index a6bfeaa91..5afcd5966 100644 --- a/commitrmnocb/validate_observation.go +++ b/commitrmnocb/validate_observation.go @@ -4,13 +4,15 @@ import ( "fmt" mapset "github.com/deckarep/golang-set/v2" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/plugintypes" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) // ValidateObservation validates an observation to ensure it is well-formed diff --git a/plugintypes/commit.go b/plugintypes/commit.go index 980eccd4b..ea38dee6f 100644 --- a/plugintypes/commit.go +++ b/plugintypes/commit.go @@ -11,12 +11,11 @@ import ( // ---[ Observation ]----------------------------------------------------------- type CommitPluginObservation struct { - NewMsgs []cciptypes.RampMessageHeader `json:"newMsgs"` - GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` - TokenPrices []cciptypes.TokenPrice `json:"tokenPrices"` - MaxSeqNums []SeqNumChain `json:"maxSeqNums"` - // TODO: Why is this a map and not a list? - FChain map[cciptypes.ChainSelector]int `json:"fChain"` + NewMsgs []cciptypes.RampMessageHeader `json:"newMsgs"` + GasPrices []cciptypes.GasPriceChain `json:"gasPrices"` + TokenPrices []cciptypes.TokenPrice `json:"tokenPrices"` + MaxSeqNums []SeqNumChain `json:"maxSeqNums"` + FChain map[cciptypes.ChainSelector]int `json:"fChain"` } func NewCommitPluginObservation(