-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[consensus] split round timeout msg out of vote msg (#14433)
* [consensus] split round timeout msg out of vote msg * Smoke test for round timeout msg rollout * update goldenfiles
- Loading branch information
1 parent
6c5ef3a
commit 628e88b
Showing
17 changed files
with
658 additions
and
102 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
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,177 @@ | ||
// Copyright (c) Aptos Foundation | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::{ | ||
common::{Author, Round}, | ||
sync_info::SyncInfo, | ||
timeout_2chain::TwoChainTimeout, | ||
}; | ||
use anyhow::{ensure, Context}; | ||
use aptos_crypto::bls12381; | ||
use aptos_short_hex_str::AsShortHexStr; | ||
use aptos_types::validator_verifier::ValidatorVerifier; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq)] | ||
pub enum RoundTimeoutReason { | ||
Unknown, | ||
ProposalNotReceived, | ||
} | ||
|
||
impl std::fmt::Display for RoundTimeoutReason { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
match self { | ||
RoundTimeoutReason::Unknown => write!(f, "Unknown"), | ||
RoundTimeoutReason::ProposalNotReceived => write!(f, "ProposalNotReceived"), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq)] | ||
pub struct RoundTimeout { | ||
// The timeout | ||
timeout: TwoChainTimeout, | ||
author: Author, | ||
reason: RoundTimeoutReason, | ||
/// Signature on the Timeout | ||
signature: bls12381::Signature, | ||
} | ||
|
||
// this is required by structured log | ||
impl std::fmt::Debug for RoundTimeout { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
write!(f, "{}", self) | ||
} | ||
} | ||
|
||
impl std::fmt::Display for RoundTimeout { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
write!( | ||
f, | ||
"RoundTimeoutV2: [timeout: {}, author: {}, reason: {}]", | ||
self.timeout, | ||
self.author.short_str(), | ||
self.reason | ||
) | ||
} | ||
} | ||
|
||
impl RoundTimeout { | ||
pub fn new( | ||
timeout: TwoChainTimeout, | ||
author: Author, | ||
reason: RoundTimeoutReason, | ||
signature: bls12381::Signature, | ||
) -> Self { | ||
Self { | ||
timeout, | ||
author, | ||
reason, | ||
signature, | ||
} | ||
} | ||
|
||
pub fn epoch(&self) -> u64 { | ||
self.timeout.epoch() | ||
} | ||
|
||
pub fn round(&self) -> Round { | ||
self.timeout.round() | ||
} | ||
|
||
pub fn two_chain_timeout(&self) -> &TwoChainTimeout { | ||
&self.timeout | ||
} | ||
|
||
pub fn author(&self) -> Author { | ||
self.author | ||
} | ||
|
||
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> { | ||
self.timeout.verify(validator)?; | ||
validator | ||
.verify( | ||
self.author(), | ||
&self.timeout.signing_format(), | ||
&self.signature, | ||
) | ||
.context("Failed to verify 2-chain timeout signature")?; | ||
Ok(()) | ||
} | ||
|
||
pub fn reason(&self) -> &RoundTimeoutReason { | ||
&self.reason | ||
} | ||
|
||
pub fn signature(&self) -> &bls12381::Signature { | ||
&self.signature | ||
} | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] | ||
pub struct RoundTimeoutMsg { | ||
/// The container for the vote (VoteData, LedgerInfo, Signature) | ||
round_timeout: RoundTimeout, | ||
/// Sync info carries information about highest QC, TC and LedgerInfo | ||
sync_info: SyncInfo, | ||
} | ||
|
||
impl std::fmt::Display for RoundTimeoutMsg { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
write!( | ||
f, | ||
"RoundTimeoutV2Msg: [{}], SyncInfo: [{}]", | ||
self.round_timeout, self.sync_info | ||
) | ||
} | ||
} | ||
|
||
impl RoundTimeoutMsg { | ||
pub fn new(round_timeout: RoundTimeout, sync_info: SyncInfo) -> Self { | ||
Self { | ||
round_timeout, | ||
sync_info, | ||
} | ||
} | ||
|
||
/// SyncInfo of the given vote message | ||
pub fn sync_info(&self) -> &SyncInfo { | ||
&self.sync_info | ||
} | ||
|
||
pub fn epoch(&self) -> u64 { | ||
self.round_timeout.epoch() | ||
} | ||
|
||
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> { | ||
ensure!( | ||
self.round_timeout.epoch() == self.sync_info.epoch(), | ||
"RoundTimeoutV2Msg has different epoch" | ||
); | ||
ensure!( | ||
self.round_timeout.round() > self.sync_info.highest_round(), | ||
"Timeout Round should be higher than SyncInfo" | ||
); | ||
ensure!( | ||
self.round_timeout.two_chain_timeout().hqc_round() | ||
<= self.sync_info.highest_certified_round(), | ||
"2-chain Timeout hqc should be less or equal than the sync info hqc" | ||
); | ||
// We're not verifying SyncInfo here yet: we are going to verify it only in case we need | ||
// it. This way we avoid verifying O(n) SyncInfo messages while aggregating the votes | ||
// (O(n^2) signature verifications). | ||
self.round_timeout.verify(validator) | ||
} | ||
|
||
pub fn round(&self) -> u64 { | ||
self.round_timeout.round() | ||
} | ||
|
||
pub fn author(&self) -> Author { | ||
self.round_timeout.author() | ||
} | ||
|
||
pub fn timeout(&self) -> RoundTimeout { | ||
self.round_timeout.clone() | ||
} | ||
} |
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
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
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
Oops, something went wrong.