Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimistic signature verification for commit votes #14643

Merged
merged 63 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c906718
Deprecate delayed QC aggregate msg
vusirikala Sep 15, 2024
c4c2cdd
Ledger info with mixed signatures
vusirikala Sep 15, 2024
08f45c9
Minor change
vusirikala Sep 15, 2024
1e85a83
Optimistic signature verification for votes and order votes
vusirikala Sep 15, 2024
02d34f3
Optimistic signature verification for commit votes
vusirikala Sep 15, 2024
8d197db
Resetting minor changes
vusirikala Sep 15, 2024
9a43029
Resetting minor changes
vusirikala Sep 15, 2024
2237342
Minor change
vusirikala Sep 15, 2024
32d5633
Addressing PR comments
vusirikala Sep 17, 2024
1df442b
Addressing PR comments
vusirikala Sep 17, 2024
6fce605
Merge branch 'satya/ledger_info_with_mixed_signatures' into satya/osv…
vusirikala Sep 17, 2024
1e3b58d
Addressing PR comments
vusirikala Sep 17, 2024
f87fb36
Addressing PR comments
vusirikala Sep 17, 2024
ef96325
Merge branch 'satya/osv_votes_and_order_votes' into satya/osv_commit_…
vusirikala Sep 17, 2024
637311b
Addressing PR comments
vusirikala Sep 17, 2024
e744449
Addressing PR comments
vusirikala Sep 18, 2024
cd56587
Addressing PR comments
vusirikala Sep 18, 2024
16370eb
Addressing PR comments
vusirikala Sep 18, 2024
a7b5e82
Minor changes
vusirikala Sep 18, 2024
2e46bb3
Minor change
vusirikala Sep 18, 2024
a2ebb6c
Merge branch 'main' into satya/ledger_info_with_mixed_signatures
vusirikala Sep 18, 2024
065d760
Changing names
vusirikala Sep 18, 2024
5ed8ad5
Addressing PR comments
vusirikala Sep 19, 2024
3be24e2
Merge branch 'satya/ledger_info_with_mixed_signatures' into satya/osv…
vusirikala Sep 19, 2024
541d58d
comments
Sep 21, 2024
20cdb9c
Fixing typos
vusirikala Sep 23, 2024
ffb1e22
Rust lint
vusirikala Sep 23, 2024
fb72780
Changed to VerificationStatus
vusirikala Sep 23, 2024
5f8f183
Merge branch 'satya/ledger_info_with_mixed_signatures' into satya/osv…
vusirikala Sep 23, 2024
25e9031
Fixing errors with rebasing
vusirikala Sep 23, 2024
0435020
Merge branch 'satya/osv_votes_and_order_votes' into satya/osv_commit_…
vusirikala Sep 23, 2024
66dcf61
Fixing errors with rebase
vusirikala Sep 23, 2024
85c7051
Using signature with status
vusirikala Sep 24, 2024
c78c06a
Minor fixes
vusirikala Sep 24, 2024
97af917
Minor comments
vusirikala Sep 24, 2024
c441175
Adding more tests
vusirikala Sep 24, 2024
7275380
Add smoke test
vusirikala Sep 25, 2024
07cb130
Change failpoint names
vusirikala Sep 25, 2024
d5d4381
Use AtomicBool
vusirikala Sep 26, 2024
beb0f7d
Using vector instead of partialsignatures
vusirikala Sep 26, 2024
bf385f9
Use single flag
vusirikala Sep 26, 2024
7a9cce3
Moving optimistic_signature_verification from epoch manager to vote a…
vusirikala Sep 26, 2024
3ecabd7
Merge branch 'main' into satya/osv_votes_and_order_votes
vusirikala Sep 26, 2024
f34cfe9
Fixing errors with rebase
vusirikala Sep 26, 2024
15fe76d
Move optimistic signature verification to validator verifier
vusirikala Sep 30, 2024
ddc6e93
Move more code to validator verifier
vusirikala Sep 30, 2024
ce2cb9b
Minor comment
vusirikala Sep 30, 2024
9b1bd38
Minor changes
vusirikala Sep 30, 2024
edd23b8
Addressing PR comments
vusirikala Oct 1, 2024
c611001
Merge branch 'main' into satya/osv_votes_and_order_votes
vusirikala Oct 2, 2024
b8928f1
Merge branch 'main' into satya/osv_votes_and_order_votes
vusirikala Oct 3, 2024
abd1e32
Rebasing
vusirikala Oct 3, 2024
c79012e
Addressing PR comments
vusirikala Oct 4, 2024
d030c93
Disabling the flag
vusirikala Oct 4, 2024
83ff41a
Merge branch 'satya/osv_votes_and_order_votes' into satya/osv_commit_…
vusirikala Oct 7, 2024
dbcb533
Rebasing and making appropriate changes
vusirikala Oct 7, 2024
3a9a38c
Minor changes
vusirikala Oct 7, 2024
a7465e4
Add smoke test
vusirikala Oct 7, 2024
4c862bd
Enable flag
vusirikala Oct 7, 2024
d0a056d
Merge branch 'main' into satya/osv_commit_votes
vusirikala Oct 8, 2024
592c51d
Minor fix
vusirikala Oct 9, 2024
5a8269d
Add a unit test
vusirikala Oct 9, 2024
a3ba6dc
Added another unit test
vusirikala Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 8 additions & 39 deletions config/src/config/consensus_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub struct ConsensusConfig {
// must match one of the CHAIN_HEALTH_WINDOW_SIZES values.
pub window_for_chain_health: usize,
pub chain_health_backoff: Vec<ChainHealthBackoffValues>,
// Deprecated
pub qc_aggregator_type: QcAggregatorType,
// Max blocks allowed for block retrieval requests
pub max_blocks_per_sending_request: u64,
Expand All @@ -89,50 +90,16 @@ pub struct ConsensusConfig {
pub rand_rb_config: ReliableBroadcastConfig,
pub num_bounded_executor_tasks: u64,
pub enable_pre_commit: bool,
pub optimistic_sig_verification_for_votes: bool,
pub optimistic_sig_verification_for_order_votes: bool,
pub optimistic_sig_verification_for_commit_votes: bool,
}

/// Deprecated
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub enum QcAggregatorType {
#[default]
NoDelay,
Delayed(DelayedQcAggregatorConfig),
}

impl QcAggregatorType {
pub fn default_delayed() -> Self {
// TODO: Enable the delayed aggregation by default once we have tested it more.
Self::Delayed(DelayedQcAggregatorConfig::default())
}
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelayedQcAggregatorConfig {
// Maximum Delay for a QC to be aggregated after round start (in milliseconds). This assumes that
// we have enough voting power to form a QC. If we don't have enough voting power, we will wait
// until we have enough voting power to form a QC.
pub max_delay_after_round_start_ms: u64,
// Percentage of aggregated voting power to wait for before aggregating a QC. For example, if this
// is set to 95% then, a QC is formed as soon as we have 95% of the voting power aggregated without
// any additional waiting.
pub aggregated_voting_power_pct_to_wait: usize,
// This knob control what is the % of the time (as compared to time between round start and time when we
// have enough voting power to form a QC) we wait after we have enough voting power to form a QC. In a sense,
// this knobs controls how much slower we are willing to make consensus to wait for more votes.
pub pct_delay_after_qc_aggregated: usize,
// In summary, let's denote the time we have enough voting power (2f + 1) to form a QC as T1 and
// the time we have aggregated `aggregated_voting_power_pct_to_wait` as T2. Then, we wait for
// min((T1 + `pct_delay_after_qc_aggregated` * T1 / 100), `max_delay_after_round_start_ms`, T2)
// before forming a QC.
}

impl Default for DelayedQcAggregatorConfig {
fn default() -> Self {
Self {
max_delay_after_round_start_ms: 700,
aggregated_voting_power_pct_to_wait: 90,
pct_delay_after_qc_aggregated: 30,
}
}
}

/// Execution backpressure which handles gas/s variance,
Expand Down Expand Up @@ -336,7 +303,6 @@ impl Default for ConsensusConfig {
backoff_proposal_delay_ms: 300,
},
],

qc_aggregator_type: QcAggregatorType::default(),
// This needs to fit into the network message size, so with quorum store it can be much bigger
max_blocks_per_sending_request: 10,
Expand All @@ -354,6 +320,9 @@ impl Default for ConsensusConfig {
},
num_bounded_executor_tasks: 16,
enable_pre_commit: true,
optimistic_sig_verification_for_votes: true,
optimistic_sig_verification_for_order_votes: true,
optimistic_sig_verification_for_commit_votes: true,
}
}
}
Expand Down
32 changes: 0 additions & 32 deletions consensus/consensus-types/src/delayed_qc_msg.rs

This file was deleted.

1 change: 0 additions & 1 deletion consensus/consensus-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pub mod block;
pub mod block_data;
pub mod block_retrieval;
pub mod common;
pub mod delayed_qc_msg;
pub mod epoch_retrieval;
pub mod order_vote;
pub mod order_vote_msg;
Expand Down
15 changes: 13 additions & 2 deletions consensus/consensus-types/src/order_vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,27 @@ impl OrderVote {
self.ledger_info.epoch()
}

/// Verifies the signature on LedgerInfo.
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
/// Performs basic checks, excluding the signature verification.
pub fn partial_verify(&self) -> anyhow::Result<()> {
ensure!(
self.ledger_info.consensus_data_hash() == HashValue::zero(),
"Failed to verify OrderVote. Consensus data hash is not Zero"
);
Ok(())
}

/// Verifies the signature on the LedgerInfo.
pub fn signature_verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
validator
.verify(self.author(), &self.ledger_info, &self.signature)
.context("Failed to verify OrderVote")?;
Ok(())
}

/// Performs full verification including the signature verification.
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
self.partial_verify()?;
self.signature_verify(validator)?;
Ok(())
}
}
12 changes: 9 additions & 3 deletions consensus/consensus-types/src/order_vote_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ impl OrderVoteMsg {
self.order_vote.epoch()
}

/// This function verifies the order_vote component in the order_vote_msg.
/// The quorum cert is verified in the round manager when the quorum certificate is used.
pub fn verify_order_vote(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
/// Performs basic checks, excluding the signature verification.
pub fn partial_verify(&self) -> anyhow::Result<()> {
ensure!(
self.quorum_cert().certified_block() == self.order_vote().ledger_info().commit_info(),
"QuorumCert and OrderVote do not match"
);
self.order_vote.partial_verify()
}

/// This function verifies the order_vote component in the order_vote_msg.
/// The quorum cert is verified in the round manager when the quorum certificate is used.
pub fn verify_order_vote(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
self.partial_verify()?;
self.order_vote
.verify(validator)
.context("[OrderVoteMsg] OrderVote verification failed")?;
Expand Down
23 changes: 17 additions & 6 deletions consensus/consensus-types/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,13 @@ impl Vote {
self.two_chain_timeout.is_some()
}

/// Verifies that the consensus data hash of LedgerInfo corresponds to the vote info,
/// and then verifies the signature.
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
/// Peforms basic verification such as verifying that the consensus data hash of LedgerInfo
/// corresponds to the vote info. Does not verify signature on the LedgerInfo.
pub fn partial_verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
ensure!(
self.ledger_info.consensus_data_hash() == self.vote_data.hash(),
"Vote's hash mismatch with LedgerInfo"
);
validator
.verify(self.author(), &self.ledger_info, &self.signature)
.context("Failed to verify Vote")?;
if let Some((timeout, signature)) = &self.two_chain_timeout {
ensure!(
(timeout.epoch(), timeout.round())
Expand All @@ -162,4 +159,18 @@ impl Vote {
self.vote_data().verify()?;
Ok(())
}

/// Verifies the signature on the LedgerInfo.
pub fn signature_verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
validator
.verify(self.author(), &self.ledger_info, &self.signature)
.context("Failed to verify Vote signature")?;
Ok(())
}

/// Performs full verification including the signature verification.
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
self.partial_verify(validator)?;
self.signature_verify(validator)
}
}
12 changes: 10 additions & 2 deletions consensus/consensus-types/src/vote_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ impl VoteMsg {
self.vote.vote_data().proposed().id()
}

pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
// Performs the basic checks on the vote message, excluding the signature verification on
// the vote.
pub fn partial_verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
ensure!(
self.vote().epoch() == self.sync_info.epoch(),
"VoteMsg has different epoch"
Expand All @@ -72,6 +74,12 @@ impl VoteMsg {
// 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.vote().verify(validator)
self.vote().partial_verify(validator)
}

/// Verifies the vote message, including the signature verification on the vote.
pub fn verify(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
self.partial_verify(validator)?;
self.vote().signature_verify(validator)
}
}
18 changes: 7 additions & 11 deletions consensus/src/block_storage/block_store_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use crate::{
test_utils::{
build_empty_tree, build_simple_tree, consensus_runtime, timed_block_on, TreeInserter,
},
util::mock_time_service::SimulatedTimeService,
};
use aptos_config::config::QcAggregatorType;
use aptos_consensus_types::{
block::{
block_test_utils::{
Expand All @@ -25,9 +23,9 @@ use aptos_consensus_types::{
};
use aptos_crypto::{HashValue, PrivateKey};
use aptos_types::{
validator_signer::ValidatorSigner, validator_verifier::random_validator_verifier,
epoch_state::EpochState, validator_signer::ValidatorSigner,
validator_verifier::random_validator_verifier,
};
use futures_channel::mpsc::unbounded;
use proptest::prelude::*;
use std::{cmp::min, collections::HashSet, sync::Arc};

Expand Down Expand Up @@ -277,18 +275,16 @@ async fn test_insert_vote() {
::aptos_logger::Logger::init_for_testing();
// Set up enough different authors to support different votes for the same block.
let (signers, validator_verifier) = random_validator_verifier(11, Some(10), false);
let epoch_state = Arc::new(EpochState::new(5, validator_verifier));
let my_signer = signers[10].clone();
let mut inserter = TreeInserter::new(my_signer);
let block_store = inserter.block_store();
let genesis = block_store.ordered_root();
let block = inserter
.insert_block_with_qc(certificate_for_genesis(), &genesis, 1)
.await;
let time_service = Arc::new(SimulatedTimeService::new());
let (delayed_qc_tx, _) = unbounded();

let mut pending_votes =
PendingVotes::new(time_service, delayed_qc_tx, QcAggregatorType::NoDelay);
let mut pending_votes = PendingVotes::new();

assert!(block_store.get_quorum_cert_for_block(block.id()).is_none());
for (i, voter) in signers.iter().enumerate().take(10).skip(1) {
Expand All @@ -306,13 +302,13 @@ async fn test_insert_vote() {
voter,
)
.unwrap();
let vote_res = pending_votes.insert_vote(&vote, &validator_verifier);
let vote_res = pending_votes.insert_vote(&vote, epoch_state.clone(), true);

// first vote of an author is accepted
assert_eq!(vote_res, VoteReceptionResult::VoteAdded(i as u128));
// filter out duplicates
assert_eq!(
pending_votes.insert_vote(&vote, &validator_verifier),
pending_votes.insert_vote(&vote, epoch_state.clone(), true),
VoteReceptionResult::DuplicateVote,
);
// qc is still not there
Expand All @@ -335,7 +331,7 @@ async fn test_insert_vote() {
final_voter,
)
.unwrap();
match pending_votes.insert_vote(&vote, &validator_verifier) {
match pending_votes.insert_vote(&vote, epoch_state.clone(), true) {
VoteReceptionResult::NewQuorumCertificate(qc) => {
assert_eq!(qc.certified_block().id(), block.id());
block_store
Expand Down
Loading
Loading