Skip to content

Commit

Permalink
feat: sign proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
Cifko committed Dec 29, 2023
1 parent cd0f704 commit 3eb5ce1
Show file tree
Hide file tree
Showing 18 changed files with 81 additions and 17 deletions.
2 changes: 1 addition & 1 deletion applications/tari_validator_node/src/consensus/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ impl ConsensusSpec for TariConsensusSpec {
type Addr = PeerAddress;
type EpochManager = EpochManagerHandle<Self::Addr>;
type LeaderStrategy = RoundRobinLeaderStrategy;
type SignatureService = TariSignatureService;
type StateManager = TariStateManager;
type StateStore = SqliteStateStore<Self::Addr>;
type SyncManager = CommsRpcStateSyncManager<Self::EpochManager, Self::StateStore>;
type VoteSignatureService = TariSignatureService;
}
24 changes: 24 additions & 0 deletions dan_layer/consensus/src/block_validations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ pub fn check_proposed_by_leader<TAddr: DerivableFromPublicKey, TLeaderStrategy:
Ok(())
}

pub fn check_signature(candidate_block: &Block) -> Result<(), ProposalValidationError> {
if candidate_block.is_dummy() {
// Dummy blocks don't have signatures
return Ok(());
}
if candidate_block.is_genesis() {
// Genesis block doesn't have signatures
return Ok(());
}
let validator_signature = candidate_block
.get_signature()
.ok_or(ProposalValidationError::MissingSignature {
block_id: *candidate_block.id(),
height: candidate_block.height(),
})?;
if !validator_signature.verify(candidate_block.proposed_by(), candidate_block.id()) {
return Err(ProposalValidationError::InvalidSignature {
block_id: *candidate_block.id(),
height: candidate_block.height(),
});
}
Ok(())
}

pub fn check_quorum_certificate<TAddr: NodeAddressable>(
_local_committee: &Committee<TAddr>,
candidate_block: &Block,
Expand Down
4 changes: 4 additions & 0 deletions dan_layer/consensus/src/hotstuff/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,8 @@ pub enum ProposalValidationError {
},
#[error("Proposed block {block_id} {height} already has been processed")]
BlockAlreadyProcessed { block_id: BlockId, height: NodeHeight },
#[error("Proposed block {block_id} {height} doesn't have signature")]
MissingSignature { block_id: BlockId, height: NodeHeight },
#[error("Proposed block {block_id} {height} has invalid signature")]
InvalidSignature { block_id: BlockId, height: NodeHeight },
}
3 changes: 2 additions & 1 deletion dan_layer/consensus/src/hotstuff/on_inbound_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use tari_transaction::TransactionId;
use tokio::{sync::mpsc, time};

use crate::{
block_validations::{check_hash_and_height, check_proposed_by_leader, check_quorum_certificate},
block_validations::{check_hash_and_height, check_proposed_by_leader, check_quorum_certificate, check_signature},
hotstuff::{error::HotStuffError, pacemaker_handle::PaceMakerHandle},
messages::{HotstuffMessage, ProposalMessage, RequestMissingTransactionsMessage},
traits::ConsensusSpec,
Expand Down Expand Up @@ -163,6 +163,7 @@ where TConsensusSpec: ConsensusSpec
.get_committee_by_validator_public_key(block.epoch(), block.proposed_by())
.await?;
check_proposed_by_leader(&self.leader_strategy, &committee_for_block, &block)?;
check_signature(&block)?;
check_quorum_certificate(&committee_for_block, &block)?;

let Some(ready_block) = self.handle_missing_transactions(block).await? else {
Expand Down
11 changes: 9 additions & 2 deletions dan_layer/consensus/src/hotstuff/on_propose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use super::common::CommitteeAndMessage;
use crate::{
hotstuff::{common::EXHAUST_DIVISOR, error::HotStuffError, proposer},
messages::{HotstuffMessage, ProposalMessage},
traits::ConsensusSpec,
traits::{ConsensusSpec, ValidatorSignatureService},
};

const LOG_TARGET: &str = "tari::dan::consensus::hotstuff::on_propose_locally";
Expand All @@ -44,6 +44,7 @@ pub struct OnPropose<TConsensusSpec: ConsensusSpec> {
store: TConsensusSpec::StateStore,
epoch_manager: TConsensusSpec::EpochManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
signing_service: TConsensusSpec::SignatureService,
tx_broadcast: mpsc::Sender<CommitteeAndMessage<TConsensusSpec::Addr>>,
}

Expand All @@ -54,12 +55,14 @@ where TConsensusSpec: ConsensusSpec
store: TConsensusSpec::StateStore,
epoch_manager: TConsensusSpec::EpochManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
signing_service: TConsensusSpec::SignatureService,
tx_broadcast: mpsc::Sender<CommitteeAndMessage<TConsensusSpec::Addr>>,
) -> Self {
Self {
store,
epoch_manager,
transaction_pool,
signing_service,
tx_broadcast,
}
}
Expand Down Expand Up @@ -269,7 +272,7 @@ where TConsensusSpec: ConsensusSpec
.map(|bucket| (*bucket, foreign_counters.increment_counter(*bucket)))
.collect();

let next_block = Block::new(
let mut next_block = Block::new(
*parent_block.block_id(),
high_qc,
parent_block.height() + NodeHeight(1),
Expand All @@ -278,8 +281,12 @@ where TConsensusSpec: ConsensusSpec
commands,
total_leader_fee,
foreign_indexes,
None,
);

let signature = self.signing_service.sign(next_block.id());
next_block.set_signature(signature);

Ok(next_block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub struct OnReadyToVoteOnLocalBlock<TConsensusSpec: ConsensusSpec> {
validator_addr: TConsensusSpec::Addr,
store: TConsensusSpec::StateStore,
epoch_manager: TConsensusSpec::EpochManager,
vote_signing_service: TConsensusSpec::VoteSignatureService,
vote_signing_service: TConsensusSpec::SignatureService,
leader_strategy: TConsensusSpec::LeaderStrategy,
state_manager: TConsensusSpec::StateManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
Expand All @@ -68,7 +68,7 @@ where TConsensusSpec: ConsensusSpec
validator_addr: TConsensusSpec::Addr,
store: TConsensusSpec::StateStore,
epoch_manager: TConsensusSpec::EpochManager,
vote_signing_service: TConsensusSpec::VoteSignatureService,
vote_signing_service: TConsensusSpec::SignatureService,
leader_strategy: TConsensusSpec::LeaderStrategy,
state_manager: TConsensusSpec::StateManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<TConsensusSpec: ConsensusSpec> OnReceiveProposalHandler<TConsensusSpec> {
leader_strategy: TConsensusSpec::LeaderStrategy,
pacemaker: PaceMakerHandle,
tx_leader: mpsc::Sender<(TConsensusSpec::Addr, HotstuffMessage)>,
vote_signing_service: TConsensusSpec::VoteSignatureService,
vote_signing_service: TConsensusSpec::SignatureService,
state_manager: TConsensusSpec::StateManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
tx_events: broadcast::Sender<HotstuffEvent>,
Expand Down
4 changes: 2 additions & 2 deletions dan_layer/consensus/src/hotstuff/vote_receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct VoteReceiver<TConsensusSpec: ConsensusSpec> {
store: TConsensusSpec::StateStore,
leader_strategy: TConsensusSpec::LeaderStrategy,
epoch_manager: TConsensusSpec::EpochManager,
vote_signature_service: TConsensusSpec::VoteSignatureService,
vote_signature_service: TConsensusSpec::SignatureService,
pacemaker: PaceMakerHandle,
}

Expand All @@ -36,7 +36,7 @@ where TConsensusSpec: ConsensusSpec
store: TConsensusSpec::StateStore,
leader_strategy: TConsensusSpec::LeaderStrategy,
epoch_manager: TConsensusSpec::EpochManager,
vote_signature_service: TConsensusSpec::VoteSignatureService,
vote_signature_service: TConsensusSpec::SignatureService,
pacemaker: PaceMakerHandle,
) -> Self {
Self {
Expand Down
5 changes: 3 additions & 2 deletions dan_layer/consensus/src/hotstuff/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<TConsensusSpec: ConsensusSpec> HotstuffWorker<TConsensusSpec> {
state_store: TConsensusSpec::StateStore,
epoch_manager: TConsensusSpec::EpochManager,
leader_strategy: TConsensusSpec::LeaderStrategy,
signing_service: TConsensusSpec::VoteSignatureService,
signing_service: TConsensusSpec::SignatureService,
state_manager: TConsensusSpec::StateManager,
transaction_pool: TransactionPool<TConsensusSpec::StateStore>,
tx_broadcast: mpsc::Sender<CommitteeAndMessage<TConsensusSpec::Addr>>,
Expand Down Expand Up @@ -127,7 +127,7 @@ impl<TConsensusSpec: ConsensusSpec> HotstuffWorker<TConsensusSpec> {
leader_strategy.clone(),
pacemaker.clone_handle(),
tx_leader.clone(),
signing_service,
signing_service.clone(),
state_manager,
transaction_pool.clone(),
tx_events,
Expand Down Expand Up @@ -157,6 +157,7 @@ impl<TConsensusSpec: ConsensusSpec> HotstuffWorker<TConsensusSpec> {
state_store.clone(),
epoch_manager.clone(),
transaction_pool.clone(),
signing_service,
tx_broadcast,
),

Expand Down
2 changes: 1 addition & 1 deletion dan_layer/consensus/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub trait ConsensusSpec: Send + Sync + Clone + 'static {
type StateStore: StateStore<Addr = Self::Addr> + Send + Sync + Clone + 'static;
type EpochManager: EpochManagerReader<Addr = Self::Addr> + Send + Sync + Clone + 'static;
type LeaderStrategy: LeaderStrategy<Self::Addr> + Send + Sync + Clone + 'static;
type VoteSignatureService: VoteSignatureService + Send + Sync + Clone + 'static;
type SignatureService: VoteSignatureService + ValidatorSignatureService + Send + Sync + Clone + 'static;
type StateManager: StateManager<Self::StateStore> + Send + Sync + 'static;
type SyncManager: SyncManager + Send + Sync + 'static;
}
2 changes: 1 addition & 1 deletion dan_layer/consensus_tests/src/support/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ impl ConsensusSpec for TestConsensusSpec {
type Addr = TestAddress;
type EpochManager = TestEpochManager;
type LeaderStrategy = RoundRobinLeaderStrategy;
type SignatureService = TestVoteSignatureService;
type StateManager = NoopStateManager;
type StateStore = SqliteStateStore<Self::Addr>;
type SyncManager = AlwaysSyncedSyncManager;
type VoteSignatureService = TestVoteSignatureService;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ create table blocks
is_processed boolean not NULL,
is_dummy boolean not NULL,
foreign_indexes text not NULL,
signature text NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (qc_id) REFERENCES quorum_certificates (qc_id)
);
Expand Down
2 changes: 2 additions & 0 deletions dan_layer/state_store_sqlite/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ diesel::table! {
is_processed -> Bool,
is_dummy -> Bool,
foreign_indexes -> Text,
signature -> Nullable<Text>,
created_at -> Timestamp,
}
}
Expand Down Expand Up @@ -149,6 +150,7 @@ diesel::table! {
commands -> Text,
total_leader_fee -> BigInt,
foreign_indexes -> Text,
signature -> Nullable<Text>,
created_at -> Timestamp,
}
}
Expand Down
4 changes: 4 additions & 0 deletions dan_layer/state_store_sqlite/src/sql_models/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub struct Block {
pub is_processed: bool,
pub is_dummy: bool,
pub foreign_indexes: String,
pub signature: Option<String>,
pub created_at: PrimitiveDateTime,
}

Expand All @@ -54,6 +55,7 @@ impl Block {
self.is_processed,
self.is_committed,
deserialize_json(&self.foreign_indexes)?,
self.signature.map(|val| deserialize_json(&val)).transpose()?,
self.created_at,
))
}
Expand All @@ -72,6 +74,7 @@ pub struct ParkedBlock {
pub commands: String,
pub total_leader_fee: i64,
pub foreign_indexes: String,
pub signature: Option<String>,
pub created_at: PrimitiveDateTime,
}

Expand All @@ -98,6 +101,7 @@ impl TryFrom<ParkedBlock> for consensus_models::Block {
false,
false,
deserialize_json(&value.foreign_indexes)?,
value.signature.map(|val| deserialize_json(&val)).transpose()?,
value.created_at,
))
}
Expand Down
19 changes: 18 additions & 1 deletion dan_layer/storage/src/consensus_models/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use tari_dan_common_types::{
use tari_transaction::TransactionId;
use time::PrimitiveDateTime;

use super::{ForeignProposal, QuorumCertificate};
use super::{ForeignProposal, QuorumCertificate, ValidatorSchnorrSignature};
use crate::{
consensus_models::{
Command,
Expand Down Expand Up @@ -72,6 +72,8 @@ pub struct Block {
foreign_indexes: HashMap<ShardBucket, u64>,
/// Timestamp when was this stored.
stored_at: Option<PrimitiveDateTime>,
/// Signature of block by the proposer.
signature: Option<ValidatorSchnorrSignature>,
}

impl Block {
Expand All @@ -84,6 +86,7 @@ impl Block {
commands: BTreeSet<Command>,
total_leader_fee: u64,
foreign_indexes: HashMap<ShardBucket, u64>,
signature: Option<ValidatorSchnorrSignature>,
) -> Self {
let mut block = Self {
id: BlockId::genesis(),
Expand All @@ -101,6 +104,7 @@ impl Block {
is_committed: false,
foreign_indexes,
stored_at: None,
signature,
};
block.id = block.calculate_hash().into();
block
Expand All @@ -119,6 +123,7 @@ impl Block {
is_processed: bool,
is_committed: bool,
foreign_indexes: HashMap<ShardBucket, u64>,
signature: Option<ValidatorSchnorrSignature>,
created_at: PrimitiveDateTime,
) -> Self {
Self {
Expand All @@ -137,6 +142,7 @@ impl Block {
is_committed,
foreign_indexes,
stored_at: Some(created_at),
signature,
}
}

Expand All @@ -150,6 +156,7 @@ impl Block {
Default::default(),
0,
HashMap::new(),
None,
)
}

Expand All @@ -170,6 +177,7 @@ impl Block {
is_committed: true,
foreign_indexes: HashMap::new(),
stored_at: None,
signature: None,
}
}

Expand All @@ -189,6 +197,7 @@ impl Block {
Default::default(),
0,
HashMap::new(),
None,
);
block.is_dummy = true;
block.is_processed = false;
Expand Down Expand Up @@ -326,6 +335,14 @@ impl Block {
pub fn get_foreign_indexes(&self) -> &HashMap<ShardBucket, u64> {
&self.foreign_indexes
}

pub fn get_signature(&self) -> Option<&ValidatorSchnorrSignature> {
self.signature.as_ref()
}

pub fn set_signature(&mut self, signature: ValidatorSchnorrSignature) {
self.signature = Some(signature);
}
}

impl Block {
Expand Down
1 change: 1 addition & 0 deletions dan_layer/validator_node_rpc/proto/consensus.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ message Block {
repeated Command commands = 8;
uint64 total_leader_fee = 9;
bytes foreign_indexes = 10;
tari.dan.common.Signature signature = 11;
}

message Command {
Expand Down
4 changes: 2 additions & 2 deletions dan_layer/validator_node_rpc/src/conversions/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ impl<H: DomainSeparation> TryFrom<proto::common::Signature> for SchnorrSignature
}
}

impl<H: DomainSeparation> From<SchnorrSignature<PublicKey, PrivateKey, H>> for proto::common::Signature {
fn from(sig: SchnorrSignature<PublicKey, PrivateKey, H>) -> Self {
impl<H: DomainSeparation> From<&SchnorrSignature<PublicKey, PrivateKey, H>> for proto::common::Signature {
fn from(sig: &SchnorrSignature<PublicKey, PrivateKey, H>) -> Self {
Self {
public_nonce: sig.get_public_nonce().to_vec(),
signature: sig.get_signature().to_vec(),
Expand Down
4 changes: 3 additions & 1 deletion dan_layer/validator_node_rpc/src/conversions/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ impl From<&tari_dan_storage::consensus_models::Block> for proto::consensus::Bloc
total_leader_fee: value.total_leader_fee(),
commands: value.commands().iter().map(Into::into).collect(),
foreign_indexes: encode(value.get_foreign_indexes()).unwrap(),
signature: value.get_signature().map(Into::into),
}
}
}
Expand All @@ -284,6 +285,7 @@ impl TryFrom<proto::consensus::Block> for tari_dan_storage::consensus_models::Bl
.collect::<Result<_, _>>()?,
value.total_leader_fee,
decode_exact(&value.foreign_indexes)?,
value.signature.map(TryInto::try_into).transpose()?,
))
}
}
Expand Down Expand Up @@ -505,7 +507,7 @@ impl From<ValidatorMetadata> for proto::consensus::ValidatorMetadata {
Self {
public_key: msg.public_key.to_vec(),
vn_shard_key: msg.vn_shard_key.as_bytes().to_vec(),
signature: Some(msg.signature.into()),
signature: Some((&msg.signature).into()),
}
}
}
Expand Down

0 comments on commit 3eb5ce1

Please sign in to comment.