From 2b61c021238fbefa9426f9ad2f61873303e9143c Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Tue, 18 Jan 2022 13:19:25 +0100 Subject: [PATCH] Try to adapt 7550 to v0.34.14 --- consensus/metrics.go | 29 ++++++++++++++++++++++------- consensus/state.go | 15 +++++++++++++++ consensus/types/round_state.go | 17 +++++++++-------- types/proposal.go | 15 ++++++++------- 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/consensus/metrics.go b/consensus/metrics.go index bbd823a3f..ee37cc98e 100644 --- a/consensus/metrics.go +++ b/consensus/metrics.go @@ -60,6 +60,11 @@ type Metrics struct { // Number of blockparts transmitted by peer. BlockParts metrics.Counter + + // ProposalTimestampDifference is the difference between the timestamp in + // the proposal message and the local time of the validator at the time + // that the validator received the message. + ProposalTimestampDifference metrics.Histogram } // PrometheusMetrics returns Metrics build using Prometheus client library. @@ -186,6 +191,15 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "block_parts", Help: "Number of blockparts transmitted by peer.", }, append(labels, "peer_id")).With(labelsAndValues...), + ProposalTimestampDifference: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_timestamp_difference", + Help: "Difference in seconds between the timestamp in the proposal " + + "message and the local time when the message was received. " + + "Only calculated when a new block is proposed.", + Buckets: []float64{-10, -.5, -.025, 0, .1, .5, 1, 1.5, 2, 10}, + }, append(labels, "is_timely")).With(labelsAndValues...), } } @@ -209,12 +223,13 @@ func NopMetrics() *Metrics { BlockIntervalSeconds: discard.NewHistogram(), - NumTxs: discard.NewGauge(), - BlockSizeBytes: discard.NewGauge(), - TotalTxs: discard.NewGauge(), - CommittedHeight: discard.NewGauge(), - FastSyncing: discard.NewGauge(), - StateSyncing: discard.NewGauge(), - BlockParts: discard.NewCounter(), + NumTxs: discard.NewGauge(), + BlockSizeBytes: discard.NewGauge(), + TotalTxs: discard.NewGauge(), + CommittedHeight: discard.NewGauge(), + FastSyncing: discard.NewGauge(), + StateSyncing: discard.NewGauge(), + BlockParts: discard.NewCounter(), + ProposalTimestampDifference: discard.NewHistogram(), } } diff --git a/consensus/state.go b/consensus/state.go index ac016c91a..2f143870e 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -661,6 +661,7 @@ func (cs *State) updateToState(state sm.State) { cs.Validators = validators cs.Proposal = nil + cs.ProposalReceiveTime = time.Time{} cs.ProposalBlock = nil cs.ProposalBlockParts = nil cs.LockedRound = -1 @@ -993,6 +994,7 @@ func (cs *State) enterNewRound(height int64, round int32) { } else { logger.Debug("resetting proposal info") cs.Proposal = nil + cs.ProposalReceiveTime = time.Time{} cs.ProposalBlock = nil cs.ProposalBlockParts = nil } @@ -1787,6 +1789,8 @@ func (cs *State) recordMetrics(height int64, block *types.Block) { //----------------------------------------------------------------------------- func (cs *State) defaultSetProposal(proposal *types.Proposal) error { + recvTime := tmtime.Now() + // Already have one // TODO: possibly catch double proposals if cs.Proposal != nil { @@ -1814,6 +1818,9 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error { proposal.Signature = p.Signature cs.Proposal = proposal + cs.ProposalReceiveTime = recvTime + cs.calculateProposalTimestampDifferenceMetric() + // We don't update cs.ProposalBlockParts if it is already set. // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. // TODO: We can check if Proposal is for a different block as this is a sign of misbehavior! @@ -2330,3 +2337,11 @@ func repairWalFile(src, dst string) error { return nil } + +func (cs *State) calculateProposalTimestampDifferenceMetric() { + if cs.Proposal != nil && cs.Proposal.POLRound == -1 { + isTimely := true + cs.metrics.ProposalTimestampDifference.With("is_timely", fmt.Sprintf("%t", isTimely)). + Observe(cs.ProposalReceiveTime.Sub(cs.Proposal.Timestamp).Seconds()) + } +} diff --git a/consensus/types/round_state.go b/consensus/types/round_state.go index 9e67b76c0..190f8576f 100644 --- a/consensus/types/round_state.go +++ b/consensus/types/round_state.go @@ -71,14 +71,15 @@ type RoundState struct { StartTime time.Time `json:"start_time"` // Subjective time when +2/3 precommits for Block at Round were found - CommitTime time.Time `json:"commit_time"` - Validators *types.ValidatorSet `json:"validators"` - Proposal *types.Proposal `json:"proposal"` - ProposalBlock *types.Block `json:"proposal_block"` - ProposalBlockParts *types.PartSet `json:"proposal_block_parts"` - LockedRound int32 `json:"locked_round"` - LockedBlock *types.Block `json:"locked_block"` - LockedBlockParts *types.PartSet `json:"locked_block_parts"` + CommitTime time.Time `json:"commit_time"` + Validators *types.ValidatorSet `json:"validators"` + Proposal *types.Proposal `json:"proposal"` + ProposalReceiveTime time.Time `json:"proposal_receive_time"` + ProposalBlock *types.Block `json:"proposal_block"` + ProposalBlockParts *types.PartSet `json:"proposal_block_parts"` + LockedRound int32 `json:"locked_round"` + LockedBlock *types.Block `json:"locked_block"` + LockedBlockParts *types.PartSet `json:"locked_block_parts"` // Last known round with POL for non-nil valid block. ValidRound int32 `json:"valid_round"` diff --git a/types/proposal.go b/types/proposal.go index 20f9e5fbe..a827df01a 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -23,13 +23,14 @@ var ( // a so-called Proof-of-Lock (POL) round, as noted in the POLRound. // If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound. type Proposal struct { - Type tmproto.SignedMsgType - Height int64 `json:"height"` - Round int32 `json:"round"` // there can not be greater than 2_147_483_647 rounds - POLRound int32 `json:"pol_round"` // -1 if null. - BlockID BlockID `json:"block_id"` - Timestamp time.Time `json:"timestamp"` - Signature []byte `json:"signature"` + Type tmproto.SignedMsgType + Height int64 `json:"height"` + Round int32 `json:"round"` // there can not be greater than 2_147_483_647 rounds + POLRound int32 `json:"pol_round"` // -1 if null. + BlockID BlockID `json:"block_id"` + Timestamp time.Time `json:"timestamp"` + ProposalReceiveTime time.Time `json:"received_timestamp"` + Signature []byte `json:"signature"` } // NewProposal returns a new Proposal.