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

feat(indexer): quorum certificate validation #893

Open
wants to merge 11 commits into
base: development
Choose a base branch
from
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions applications/tari_dan_app_utilities/Cargo.toml
Expand Up @@ -13,6 +13,7 @@ tari_core = { workspace = true, default-features = false, features = ["transacti
tari_crypto = { workspace = true }
tari_shutdown = { workspace = true }

tari_consensus = { workspace = true }
tari_dan_common_types = { workspace = true }
tari_state_store_sqlite = { workspace = true }
tari_dan_engine = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions applications/tari_dan_app_utilities/src/lib.rs
Expand Up @@ -26,6 +26,7 @@ pub mod consensus_constants;
pub mod keypair;
pub mod p2p_config;
pub mod seed_peer;
pub mod signature_service;
pub mod substate_file_cache;
pub mod template_manager;
pub mod transaction_executor;
62 changes: 62 additions & 0 deletions applications/tari_dan_app_utilities/src/signature_service.rs
@@ -0,0 +1,62 @@
// Copyright 2024. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use rand::rngs::OsRng;
use tari_common_types::types::{FixedHash, PublicKey};
use tari_consensus::traits::{ValidatorSignatureService, VoteSignatureService};
use tari_dan_storage::consensus_models::{BlockId, QuorumDecision, ValidatorSchnorrSignature, ValidatorSignature};

use crate::keypair::RistrettoKeypair;

#[derive(Debug, Clone)]
pub struct TariSignatureService {
keypair: RistrettoKeypair,
}

impl TariSignatureService {
pub fn new(keypair: RistrettoKeypair) -> Self {
Self { keypair }
}
}

impl ValidatorSignatureService for TariSignatureService {
fn sign<M: AsRef<[u8]>>(&self, message: M) -> ValidatorSchnorrSignature {
ValidatorSchnorrSignature::sign(self.keypair.secret_key(), message, &mut OsRng).unwrap()
}

fn public_key(&self) -> &PublicKey {
self.keypair.public_key()
}
}

impl VoteSignatureService for TariSignatureService {
fn verify(
&self,
signature: &ValidatorSignature,
leaf_hash: &FixedHash,
block_id: &BlockId,
decision: &QuorumDecision,
) -> bool {
let challenge = self.create_challenge(leaf_hash, block_id, decision);
signature.verify(challenge)
}
}
1 change: 1 addition & 0 deletions applications/tari_indexer/Cargo.toml
Expand Up @@ -14,6 +14,7 @@ tari_common_types = { workspace = true }
tari_crypto = { workspace = true }
tari_shutdown = { workspace = true }

tari_consensus = { workspace = true }
tari_bor = { workspace = true, default-features = true }
tari_dan_app_utilities = { workspace = true }
tari_dan_common_types = { workspace = true }
Expand Down
16 changes: 13 additions & 3 deletions applications/tari_indexer/src/dry_run/processor.rs
Expand Up @@ -24,6 +24,7 @@ use std::{collections::HashMap, sync::Arc};

use log::info;
use tari_dan_app_utilities::{
signature_service::TariSignatureService,
template_manager::implementation::TemplateManager,
transaction_executor::{TariDanTransactionProcessor, TransactionExecutor},
};
Expand Down Expand Up @@ -61,8 +62,12 @@ const LOG_TARGET: &str = "tari::indexer::dry_run_transaction_processor";
pub struct DryRunTransactionProcessor<TSubstateCache> {
epoch_manager: EpochManagerHandle<PeerAddress>,
client_provider: TariValidatorNodeRpcClientFactory,
transaction_autofiller:
TransactionAutofiller<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, TSubstateCache>,
transaction_autofiller: TransactionAutofiller<
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
TSubstateCache,
TariSignatureService,
>,
template_manager: TemplateManager<PeerAddress>,
}

Expand All @@ -73,7 +78,12 @@ where TSubstateCache: SubstateCache + 'static
epoch_manager: EpochManagerHandle<PeerAddress>,
client_provider: TariValidatorNodeRpcClientFactory,
substate_scanner: Arc<
SubstateScanner<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, TSubstateCache>,
SubstateScanner<
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
TSubstateCache,
TariSignatureService,
>,
>,
template_manager: TemplateManager<PeerAddress>,
) -> Self {
Expand Down
16 changes: 13 additions & 3 deletions applications/tari_indexer/src/json_rpc/handlers.rs
Expand Up @@ -32,7 +32,11 @@ use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
use log::{error, warn};
use serde_json::{self as json, json, Value};
use tari_base_node_client::{grpc::GrpcBaseNodeClient, types::BaseLayerConsensusConstants, BaseNodeClient};
use tari_dan_app_utilities::{keypair::RistrettoKeypair, substate_file_cache::SubstateFileCache};
use tari_dan_app_utilities::{
keypair::RistrettoKeypair,
signature_service::TariSignatureService,
substate_file_cache::SubstateFileCache,
};
use tari_dan_common_types::{optional::Optional, public_key_to_peer_id, Epoch, PeerAddress};
use tari_dan_storage::consensus_models::Decision;
use tari_epoch_manager::{base_layer::EpochManagerHandle, EpochManagerReader};
Expand Down Expand Up @@ -92,8 +96,12 @@ pub struct JsonRpcHandlers {
base_node_client: GrpcBaseNodeClient,
substate_manager: Arc<SubstateManager>,
epoch_manager: EpochManagerHandle<PeerAddress>,
transaction_manager:
TransactionManager<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, SubstateFileCache>,
transaction_manager: TransactionManager<
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
SubstateFileCache,
TariSignatureService,
>,
dry_run_transaction_processor: DryRunTransactionProcessor<SubstateFileCache>,
}

Expand All @@ -107,6 +115,7 @@ impl JsonRpcHandlers {
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
SubstateFileCache,
TariSignatureService,
>,
dry_run_transaction_processor: DryRunTransactionProcessor<SubstateFileCache>,
) -> Self {
Expand Down Expand Up @@ -317,6 +326,7 @@ impl JsonRpcHandlers {
address,
substate,
created_by_tx,
quorum_certificates: _,
} => Ok(JsonRpcResponse::success(answer_id, GetSubstateResponse {
address,
version: substate.version(),
Expand Down
3 changes: 3 additions & 0 deletions applications/tari_indexer/src/lib.rs
Expand Up @@ -50,6 +50,7 @@ use tari_common::{
use tari_dan_app_utilities::{
consensus_constants::ConsensusConstants,
keypair::setup_keypair_prompt,
signature_service::TariSignatureService,
substate_file_cache::SubstateFileCache,
};
use tari_dan_storage::global::DbFactory;
Expand Down Expand Up @@ -104,10 +105,12 @@ pub async fn run_indexer(config: ApplicationConfig, mut shutdown_signal: Shutdow
let substate_cache = SubstateFileCache::new(substate_cache_dir)
.map_err(|e| ExitError::new(ExitCode::ConfigError, format!("Substate cache error: {}", e)))?;

let signing_service = TariSignatureService::new(keypair.clone());
let dan_layer_scanner = Arc::new(SubstateScanner::new(
services.epoch_manager.clone(),
services.validator_node_client_factory.clone(),
substate_cache,
signing_service,
));

let substate_manager = Arc::new(SubstateManager::new(
Expand Down
20 changes: 16 additions & 4 deletions applications/tari_indexer/src/substate_manager.rs
Expand Up @@ -27,7 +27,7 @@ use log::info;
use serde::{Deserialize, Serialize};
use tari_common_types::types::FixedHash;
use tari_crypto::tari_utilities::message_format::MessageFormat;
use tari_dan_app_utilities::substate_file_cache::SubstateFileCache;
use tari_dan_app_utilities::{signature_service::TariSignatureService, substate_file_cache::SubstateFileCache};
use tari_dan_common_types::PeerAddress;
use tari_engine_types::{
events::Event,
Expand Down Expand Up @@ -81,15 +81,26 @@ pub struct EventResponse {
}

pub struct SubstateManager {
substate_scanner:
Arc<SubstateScanner<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, SubstateFileCache>>,
substate_scanner: Arc<
SubstateScanner<
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
SubstateFileCache,
TariSignatureService,
>,
>,
substate_store: SqliteSubstateStore,
}

impl SubstateManager {
pub fn new(
dan_layer_scanner: Arc<
SubstateScanner<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, SubstateFileCache>,
SubstateScanner<
EpochManagerHandle<PeerAddress>,
TariValidatorNodeRpcClientFactory,
SubstateFileCache,
TariSignatureService,
>,
>,
substate_store: SqliteSubstateStore,
) -> Self {
Expand Down Expand Up @@ -229,6 +240,7 @@ impl SubstateManager {
address,
substate,
created_by_tx,
quorum_certificates: _,
} => Ok(Some(SubstateResponse {
address,
version: substate.version(),
Expand Down
16 changes: 9 additions & 7 deletions applications/tari_indexer/src/transaction_manager/mod.rs
Expand Up @@ -25,9 +25,10 @@ mod error;
use std::{collections::HashSet, fmt::Display, future::Future, iter, sync::Arc};

use log::*;
use tari_consensus::traits::VoteSignatureService;
use tari_dan_common_types::{
optional::{IsNotFoundError, Optional},
NodeAddressable,
DerivableFromPublicKey,
ShardId,
};
use tari_engine_types::substate::SubstateAddress;
Expand All @@ -49,25 +50,26 @@ use crate::transaction_manager::error::TransactionManagerError;

const LOG_TARGET: &str = "tari::indexer::transaction_manager";

pub struct TransactionManager<TEpochManager, TClientFactory, TSubstateCache> {
pub struct TransactionManager<TEpochManager, TClientFactory, TSubstateCache, TSignatureService> {
epoch_manager: TEpochManager,
client_provider: TClientFactory,
transaction_autofiller: TransactionAutofiller<TEpochManager, TClientFactory, TSubstateCache>,
transaction_autofiller: TransactionAutofiller<TEpochManager, TClientFactory, TSubstateCache, TSignatureService>,
}

impl<TEpochManager, TClientFactory, TAddr, TSubstateCache>
TransactionManager<TEpochManager, TClientFactory, TSubstateCache>
impl<TEpochManager, TClientFactory, TAddr, TSubstateCache, TSignatureService>
TransactionManager<TEpochManager, TClientFactory, TSubstateCache, TSignatureService>
where
TAddr: NodeAddressable + 'static,
TAddr: DerivableFromPublicKey + 'static,
TEpochManager: EpochManagerReader<Addr = TAddr> + 'static,
TClientFactory: ValidatorNodeClientFactory<Addr = TAddr> + 'static,
<TClientFactory::Client as ValidatorNodeRpcClient>::Error: IsNotFoundError + 'static,
TSubstateCache: SubstateCache + 'static,
TSignatureService: VoteSignatureService + Send + Sync + Clone + 'static,
{
pub fn new(
epoch_manager: TEpochManager,
client_provider: TClientFactory,
substate_scanner: Arc<SubstateScanner<TEpochManager, TClientFactory, TSubstateCache>>,
substate_scanner: Arc<SubstateScanner<TEpochManager, TClientFactory, TSubstateCache, TSignatureService>>,
) -> Self {
Self {
epoch_manager,
Expand Down
5 changes: 5 additions & 0 deletions applications/tari_validator_node/src/bootstrap.rs
Expand Up @@ -42,6 +42,7 @@ use tari_dan_app_utilities::{
consensus_constants::ConsensusConstants,
keypair::RistrettoKeypair,
seed_peer::SeedPeer,
signature_service::TariSignatureService,
substate_file_cache::SubstateFileCache,
template_manager,
template_manager::{implementation::TemplateManager, interface::TemplateManagerHandle},
Expand Down Expand Up @@ -249,12 +250,16 @@ pub async fn spawn_services(
let substate_cache = SubstateFileCache::new(substate_cache_dir)
.map_err(|e| ExitError::new(ExitCode::ConfigError, format!("Substate cache error: {}", e)))?;

// Signature service
let signing_service = TariSignatureService::new(keypair.clone());

// Mempool
let virtual_substate_manager = VirtualSubstateManager::new(state_store.clone(), epoch_manager.clone());
let scanner = SubstateScanner::new(
epoch_manager.clone(),
validator_node_client_factory.clone(),
substate_cache,
signing_service,
);
let substate_resolver = TariSubstateResolver::new(
state_store.clone(),
Expand Down
11 changes: 3 additions & 8 deletions applications/tari_validator_node/src/consensus/mod.rs
Expand Up @@ -20,24 +20,19 @@ use tokio::{
};

use crate::{
consensus::{
leader_selection::RoundRobinLeaderStrategy,
signature_service::TariSignatureService,
spec::TariConsensusSpec,
state_manager::TariStateManager,
},
consensus::{leader_selection::RoundRobinLeaderStrategy, state_manager::TariStateManager},
event_subscription::EventSubscription,
};

mod handle;
mod leader_selection;
mod signature_service;
mod spec;
pub use spec::TariConsensusSpec;
mod state_manager;

pub use handle::*;
use sqlite_message_logger::SqliteMessageLogger;
use tari_dan_app_utilities::keypair::RistrettoKeypair;
use tari_dan_app_utilities::{keypair::RistrettoKeypair, signature_service::TariSignatureService};
use tari_dan_common_types::PeerAddress;

use crate::p2p::services::message_dispatcher::OutboundMessaging;
Expand Down