Skip to content

Commit

Permalink
[Consensus] add type and interface for transaction voting (#19280)
Browse files Browse the repository at this point in the history
## Description 

Add block variant that supports voting.
Add method to TransactionVerifier trait, for calling into the voting
logic.

## Test plan 

CI

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
mwtian authored Sep 10, 2024
1 parent 91ee7f0 commit a911368
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 7 deletions.
119 changes: 117 additions & 2 deletions consensus/core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,31 @@ impl Transaction {
}
}

/// Index of a transaction in a block.
pub type TransactionIndex = u16;

/// Votes on transactions in a specific block.
/// Reject votes are explicit. The rest of transactions in the block receive implicit accept votes.
// TODO: look into making fields `pub`.
#[derive(Clone, Deserialize, Serialize)]
pub(crate) struct BlockTransactionVotes {
pub(crate) block_ref: BlockRef,
pub(crate) rejects: Vec<TransactionIndex>,
}

/// A block includes references to previous round blocks and transactions that the authority
/// considers valid.
/// Well behaved authorities produce at most one block per round, but malicious authorities can
/// equivocate.
#[allow(private_interfaces)]
#[derive(Clone, Deserialize, Serialize)]
#[enum_dispatch(BlockAPI)]
pub enum Block {
V1(BlockV1),
V2(BlockV2),
}

#[allow(private_interfaces)]
#[enum_dispatch]
pub trait BlockAPI {
fn epoch(&self) -> Epoch;
Expand All @@ -70,15 +85,15 @@ pub trait BlockAPI {
fn ancestors(&self) -> &[BlockRef];
fn transactions(&self) -> &[Transaction];
fn commit_votes(&self) -> &[CommitVote];
fn transaction_votes(&self) -> &[BlockTransactionVotes];
fn misbehavior_reports(&self) -> &[MisbehaviorReport];
}

#[derive(Clone, Default, Deserialize, Serialize)]
pub struct BlockV1 {
pub(crate) struct BlockV1 {
epoch: Epoch,
round: Round,
author: AuthorityIndex,
// TODO: during verification ensure that timestamp_ms >= ancestors.timestamp
timestamp_ms: BlockTimestampMs,
ancestors: Vec<BlockRef>,
transactions: Vec<Transaction>,
Expand Down Expand Up @@ -156,6 +171,106 @@ impl BlockAPI for BlockV1 {
&self.commit_votes
}

fn transaction_votes(&self) -> &[BlockTransactionVotes] {
&[]
}

fn misbehavior_reports(&self) -> &[MisbehaviorReport] {
&self.misbehavior_reports
}
}

#[derive(Clone, Default, Deserialize, Serialize)]
pub(crate) struct BlockV2 {
epoch: Epoch,
round: Round,
author: AuthorityIndex,
timestamp_ms: BlockTimestampMs,
ancestors: Vec<BlockRef>,
transactions: Vec<Transaction>,
transaction_votes: Vec<BlockTransactionVotes>,
commit_votes: Vec<CommitVote>,
misbehavior_reports: Vec<MisbehaviorReport>,
}

#[allow(unused)]
impl BlockV2 {
pub(crate) fn new(
epoch: Epoch,
round: Round,
author: AuthorityIndex,
timestamp_ms: BlockTimestampMs,
ancestors: Vec<BlockRef>,
transactions: Vec<Transaction>,
commit_votes: Vec<CommitVote>,
transaction_votes: Vec<BlockTransactionVotes>,
misbehavior_reports: Vec<MisbehaviorReport>,
) -> BlockV2 {
Self {
epoch,
round,
author,
timestamp_ms,
ancestors,
transactions,
commit_votes,
transaction_votes,
misbehavior_reports,
}
}

fn genesis_block(epoch: Epoch, author: AuthorityIndex) -> Self {
Self {
epoch,
round: GENESIS_ROUND,
author,
timestamp_ms: 0,
ancestors: vec![],
transactions: vec![],
commit_votes: vec![],
transaction_votes: vec![],
misbehavior_reports: vec![],
}
}
}

impl BlockAPI for BlockV2 {
fn epoch(&self) -> Epoch {
self.epoch
}

fn round(&self) -> Round {
self.round
}

fn author(&self) -> AuthorityIndex {
self.author
}

fn slot(&self) -> Slot {
Slot::new(self.round, self.author)
}

fn timestamp_ms(&self) -> BlockTimestampMs {
self.timestamp_ms
}

fn ancestors(&self) -> &[BlockRef] {
&self.ancestors
}

fn transactions(&self) -> &[Transaction] {
&self.transactions
}

fn transaction_votes(&self) -> &[BlockTransactionVotes] {
&self.transaction_votes
}

fn commit_votes(&self) -> &[CommitVote] {
&self.commit_votes
}

fn misbehavior_reports(&self) -> &[MisbehaviorReport] {
&self.misbehavior_reports
}
Expand Down
6 changes: 5 additions & 1 deletion consensus/core/src/block_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ mod test {

use super::*;
use crate::{
block::{BlockDigest, BlockRef, TestBlock, Transaction},
block::{BlockDigest, BlockRef, TestBlock, Transaction, TransactionIndex},
context::Context,
transaction::{TransactionVerifier, ValidationError},
};
Expand All @@ -247,6 +247,10 @@ mod test {
}
Ok(())
}

fn vote_batch(&self, _batch: &[&[u8]]) -> Vec<TransactionIndex> {
vec![]
}
}

#[tokio::test]
Expand Down
2 changes: 1 addition & 1 deletion consensus/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ mod test_dag_parser;

/// Exported consensus API.
pub use authority_node::ConsensusAuthority;
pub use block::{BlockAPI, Round};
pub use block::{BlockAPI, Round, TransactionIndex};
pub use commit::{CommitDigest, CommitIndex, CommitRef, CommittedSubDag};
pub use commit_consumer::{CommitConsumer, CommitConsumerMonitor};
pub use transaction::{ClientError, TransactionClient, TransactionVerifier, ValidationError};
Expand Down
15 changes: 13 additions & 2 deletions consensus/core/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tokio::sync::oneshot;
use tracing::{error, warn};

use crate::{
block::{BlockRef, Transaction},
block::{BlockRef, Transaction, TransactionIndex},
context::Context,
};

Expand Down Expand Up @@ -211,8 +211,15 @@ impl TransactionClient {
/// `TransactionVerifier` implementation is supplied by Sui to validate transactions in a block,
/// before acceptance of the block.
pub trait TransactionVerifier: Send + Sync + 'static {
/// Determines if this batch can be voted on
/// Determines if this batch of transactions is valid.
/// Fails if any one of the transactions is invalid.
fn verify_batch(&self, batch: &[&[u8]]) -> Result<(), ValidationError>;

/// Returns indices of transactions to reject.
/// Currently only uncertified user transactions can be rejected.
/// The rest of transactions are implicitly voted to accept.
// TODO: add rejection reasons, add VoteError and wrap the return in Result<>.
fn vote_batch(&self, batch: &[&[u8]]) -> Vec<TransactionIndex>;
}

#[derive(Debug, Error)]
Expand All @@ -229,6 +236,10 @@ impl TransactionVerifier for NoopTransactionVerifier {
fn verify_batch(&self, _batch: &[&[u8]]) -> Result<(), ValidationError> {
Ok(())
}

fn vote_batch(&self, _batch: &[&[u8]]) -> Vec<TransactionIndex> {
vec![]
}
}

#[cfg(test)]
Expand Down
6 changes: 5 additions & 1 deletion crates/sui-core/src/consensus_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use std::sync::Arc;

use consensus_core::{TransactionVerifier, ValidationError};
use consensus_core::{TransactionIndex, TransactionVerifier, ValidationError};
use eyre::WrapErr;
use fastcrypto_tbls::dkg;
use mysten_metrics::monitored_scope;
Expand Down Expand Up @@ -152,6 +152,10 @@ impl TransactionVerifier for SuiTxValidator {
self.validate_transactions(txs)
.map_err(|e| ValidationError::InvalidTransaction(e.to_string()))
}

fn vote_batch(&self, _batch: &[&[u8]]) -> Vec<TransactionIndex> {
vec![]
}
}

pub struct SuiTxValidatorMetrics {
Expand Down

0 comments on commit a911368

Please sign in to comment.