2024-05-31 00:52:12 +00:00
|
|
|
//! Cuprate Consensus
|
|
|
|
//!
|
|
|
|
//! This crate contains 3 [`tower::Service`]s that implement Monero's consensus rules:
|
|
|
|
//!
|
|
|
|
//! - [`BlockChainContextService`] Which handles keeping the current state of the blockchain.
|
|
|
|
//! - [`BlockVerifierService`] Which handles block verification.
|
|
|
|
//! - [`TxVerifierService`] Which handles transaction verification.
|
|
|
|
//!
|
|
|
|
//! This crate is generic over the database which is implemented as a [`tower::Service`]. To
|
2024-08-05 20:47:30 +00:00
|
|
|
//! implement a database you need to have a service which accepts [`BlockchainReadRequest`] and responds
|
|
|
|
//! with [`BlockchainResponse`].
|
2024-05-31 00:52:12 +00:00
|
|
|
//!
|
2024-09-21 00:32:03 +00:00
|
|
|
|
|
|
|
cfg_if::cfg_if! {
|
|
|
|
// Used in external `tests/`.
|
|
|
|
if #[cfg(test)] {
|
|
|
|
use cuprate_test_utils as _;
|
|
|
|
use curve25519_dalek as _;
|
|
|
|
use hex_literal as _;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-22 01:09:07 +00:00
|
|
|
use cuprate_consensus_rules::ConsensusError;
|
2023-12-16 23:03:02 +00:00
|
|
|
|
2023-12-27 23:50:18 +00:00
|
|
|
mod batch_verifier;
|
2023-09-28 11:21:06 +00:00
|
|
|
pub mod block;
|
2023-10-28 23:39:22 +00:00
|
|
|
#[cfg(test)]
|
2024-01-19 00:34:30 +00:00
|
|
|
mod tests;
|
2023-10-20 00:04:26 +00:00
|
|
|
pub mod transactions;
|
2023-10-22 16:27:37 +00:00
|
|
|
|
2024-06-04 17:19:35 +00:00
|
|
|
pub use block::{BlockVerifierService, VerifyBlockRequest, VerifyBlockResponse};
|
2024-10-16 23:17:58 +00:00
|
|
|
pub use cuprate_consensus_context::{
|
2023-12-02 22:57:34 +00:00
|
|
|
initialize_blockchain_context, BlockChainContext, BlockChainContextRequest,
|
2024-05-31 00:52:12 +00:00
|
|
|
BlockChainContextResponse, BlockChainContextService, ContextConfig,
|
2023-11-05 18:44:41 +00:00
|
|
|
};
|
2024-05-31 00:52:12 +00:00
|
|
|
pub use transactions::{TxVerifierService, VerifyTxRequest, VerifyTxResponse};
|
2023-10-22 16:27:37 +00:00
|
|
|
|
2024-06-04 17:19:35 +00:00
|
|
|
// re-export.
|
2024-10-08 17:26:07 +00:00
|
|
|
pub use cuprate_consensus_rules::genesis::generate_genesis_block;
|
2024-08-22 01:09:07 +00:00
|
|
|
pub use cuprate_types::{
|
|
|
|
blockchain::{BlockchainReadRequest, BlockchainResponse},
|
|
|
|
HardFork,
|
|
|
|
};
|
2024-06-04 17:19:35 +00:00
|
|
|
|
2024-05-31 00:52:12 +00:00
|
|
|
/// An Error returned from one of the consensus services.
|
2023-12-16 23:03:02 +00:00
|
|
|
#[derive(Debug, thiserror::Error)]
|
2024-09-21 00:32:03 +00:00
|
|
|
#[expect(variant_size_differences)]
|
2023-12-16 23:03:02 +00:00
|
|
|
pub enum ExtendedConsensusError {
|
2024-05-31 00:52:12 +00:00
|
|
|
/// A consensus error.
|
2023-12-16 23:03:02 +00:00
|
|
|
#[error("{0}")]
|
2024-05-31 00:52:12 +00:00
|
|
|
ConErr(#[from] ConsensusError),
|
|
|
|
/// A database error.
|
2023-12-16 23:03:02 +00:00
|
|
|
#[error("Database error: {0}")]
|
|
|
|
DBErr(#[from] tower::BoxError),
|
2024-05-31 00:52:12 +00:00
|
|
|
/// The transactions passed in with this block were not the ones needed.
|
2024-02-13 00:51:11 +00:00
|
|
|
#[error("The transactions passed in with the block are incorrect.")]
|
|
|
|
TxsIncludedWithBlockIncorrect,
|
2024-05-31 00:52:12 +00:00
|
|
|
/// One or more statements in the batch verifier was invalid.
|
|
|
|
#[error("One or more statements in the batch verifier was invalid.")]
|
|
|
|
OneOrMoreBatchVerificationStatementsInvalid,
|
2024-06-25 00:55:04 +00:00
|
|
|
/// A request to verify a batch of blocks had no blocks in the batch.
|
|
|
|
#[error("A request to verify a batch of blocks had no blocks in the batch.")]
|
|
|
|
NoBlocksToVerify,
|
2023-12-16 23:03:02 +00:00
|
|
|
}
|
|
|
|
|
2024-05-31 00:52:12 +00:00
|
|
|
/// Initialize the 2 verifier [`tower::Service`]s (block and transaction).
|
2024-09-21 00:32:03 +00:00
|
|
|
pub fn initialize_verifier<D, Ctx>(
|
2023-10-22 16:27:37 +00:00
|
|
|
database: D,
|
2023-11-05 18:44:41 +00:00
|
|
|
ctx_svc: Ctx,
|
2024-10-08 17:26:07 +00:00
|
|
|
) -> (
|
|
|
|
BlockVerifierService<Ctx, TxVerifierService<D>, D>,
|
|
|
|
TxVerifierService<D>,
|
|
|
|
)
|
2023-10-22 16:27:37 +00:00
|
|
|
where
|
|
|
|
D: Database + Clone + Send + Sync + 'static,
|
|
|
|
D::Future: Send + 'static,
|
2023-11-05 18:44:41 +00:00
|
|
|
Ctx: tower::Service<
|
|
|
|
BlockChainContextRequest,
|
2023-12-02 22:57:34 +00:00
|
|
|
Response = BlockChainContextResponse,
|
2023-11-05 18:44:41 +00:00
|
|
|
Error = tower::BoxError,
|
|
|
|
> + Clone
|
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ 'static,
|
|
|
|
Ctx::Future: Send + 'static,
|
2023-10-22 16:27:37 +00:00
|
|
|
{
|
2024-05-31 00:52:12 +00:00
|
|
|
let tx_svc = TxVerifierService::new(database.clone());
|
|
|
|
let block_svc = BlockVerifierService::new(ctx_svc, tx_svc.clone(), database);
|
2024-10-08 17:26:07 +00:00
|
|
|
(block_svc, tx_svc)
|
2023-10-22 16:27:37 +00:00
|
|
|
}
|
2023-09-03 22:50:38 +00:00
|
|
|
|
2024-06-04 17:19:35 +00:00
|
|
|
use __private::Database;
|
2023-09-03 22:50:38 +00:00
|
|
|
|
2024-06-04 17:19:35 +00:00
|
|
|
pub mod __private {
|
|
|
|
use std::future::Future;
|
2023-09-03 22:50:38 +00:00
|
|
|
|
2024-08-05 20:47:30 +00:00
|
|
|
use cuprate_types::blockchain::{BlockchainReadRequest, BlockchainResponse};
|
2023-10-22 16:27:37 +00:00
|
|
|
|
2024-06-04 17:19:35 +00:00
|
|
|
/// A type alias trait used to represent a database, so we don't have to write [`tower::Service`] bounds
|
|
|
|
/// everywhere.
|
2024-05-31 00:52:12 +00:00
|
|
|
///
|
2024-06-04 17:19:35 +00:00
|
|
|
/// Automatically implemented for:
|
|
|
|
/// ```ignore
|
|
|
|
/// tower::Service<BCReadRequest, Response = BCResponse, Error = tower::BoxError>
|
|
|
|
/// ```
|
|
|
|
pub trait Database:
|
|
|
|
tower::Service<
|
2024-08-05 20:47:30 +00:00
|
|
|
BlockchainReadRequest,
|
|
|
|
Response = BlockchainResponse,
|
2024-06-04 17:19:35 +00:00
|
|
|
Error = tower::BoxError,
|
|
|
|
Future = Self::Future2,
|
|
|
|
>
|
|
|
|
{
|
|
|
|
type Future2: Future<Output = Result<Self::Response, Self::Error>> + Send + 'static;
|
|
|
|
}
|
|
|
|
|
2024-08-05 20:47:30 +00:00
|
|
|
impl<
|
|
|
|
T: tower::Service<
|
|
|
|
BlockchainReadRequest,
|
|
|
|
Response = BlockchainResponse,
|
|
|
|
Error = tower::BoxError,
|
|
|
|
>,
|
2024-09-21 00:32:03 +00:00
|
|
|
> Database for T
|
2024-06-04 17:19:35 +00:00
|
|
|
where
|
|
|
|
T::Future: Future<Output = Result<Self::Response, Self::Error>> + Send + 'static,
|
|
|
|
{
|
|
|
|
type Future2 = T::Future;
|
|
|
|
}
|
2023-09-03 22:50:38 +00:00
|
|
|
}
|