mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-23 12:09:52 +00:00
clean up handler code
This commit is contained in:
parent
915633fe70
commit
01a3065cc8
9 changed files with 332 additions and 349 deletions
|
@ -1,6 +1,8 @@
|
||||||
//! Blockchain
|
//! Blockchain
|
||||||
//!
|
//!
|
||||||
//! Will contain the chain manager and syncer.
|
//! Will contain the chain manager and syncer.
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ pub async fn init_consensus(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the blockchain manager task and syncer.
|
/// Initializes the blockchain manager task and syncer.
|
||||||
pub fn init_blockchain_manager(
|
pub async fn init_blockchain_manager(
|
||||||
clearnet_interface: NetworkInterface<ClearNet>,
|
clearnet_interface: NetworkInterface<ClearNet>,
|
||||||
blockchain_write_handle: BlockchainWriteHandle,
|
blockchain_write_handle: BlockchainWriteHandle,
|
||||||
blockchain_read_handle: BlockchainReadHandle,
|
blockchain_read_handle: BlockchainReadHandle,
|
||||||
|
@ -118,7 +120,7 @@ pub fn init_blockchain_manager(
|
||||||
blockchain_read_handle,
|
blockchain_read_handle,
|
||||||
blockchain_context_service,
|
blockchain_context_service,
|
||||||
block_verifier_service,
|
block_verifier_service,
|
||||||
);
|
).await;
|
||||||
|
|
||||||
tokio::spawn(manager.run(batch_rx));
|
tokio::spawn(manager.run(batch_rx));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod batch_handler;
|
|
||||||
mod handler;
|
mod handler;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use crate::blockchain::types::ConsensusBlockchainReadHandle;
|
use crate::blockchain::types::ConsensusBlockchainReadHandle;
|
||||||
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
||||||
use cuprate_consensus::context::RawBlockChainContext;
|
use cuprate_consensus::context::RawBlockChainContext;
|
||||||
|
@ -11,12 +11,20 @@ use cuprate_consensus::{
|
||||||
};
|
};
|
||||||
use cuprate_p2p::block_downloader::BlockBatch;
|
use cuprate_p2p::block_downloader::BlockBatch;
|
||||||
use cuprate_types::blockchain::{BlockchainReadRequest, BlockchainResponse};
|
use cuprate_types::blockchain::{BlockchainReadRequest, BlockchainResponse};
|
||||||
use cuprate_types::Chain;
|
use cuprate_types::{Chain, TransactionVerificationData};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use tokio::sync::mpsc::Receiver;
|
use monero_serai::block::Block;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::{Notify, oneshot};
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
|
pub struct IncomingBlock {
|
||||||
|
block: Block,
|
||||||
|
prepped_txs: HashMap<[u8; 32], TransactionVerificationData>,
|
||||||
|
response_tx: oneshot::Sender<Result<(), anyhow::Error>>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BlockchainManager {
|
pub struct BlockchainManager {
|
||||||
blockchain_write_handle: BlockchainWriteHandle,
|
blockchain_write_handle: BlockchainWriteHandle,
|
||||||
blockchain_read_handle: BlockchainReadHandle,
|
blockchain_read_handle: BlockchainReadHandle,
|
||||||
|
@ -27,105 +35,58 @@ pub struct BlockchainManager {
|
||||||
TxVerifierService<ConsensusBlockchainReadHandle>,
|
TxVerifierService<ConsensusBlockchainReadHandle>,
|
||||||
ConsensusBlockchainReadHandle,
|
ConsensusBlockchainReadHandle,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
|
// TODO: stop_current_block_downloader: Notify,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockchainManager {
|
impl BlockchainManager {
|
||||||
pub const fn new(
|
pub async fn new(
|
||||||
blockchain_write_handle: BlockchainWriteHandle,
|
blockchain_write_handle: BlockchainWriteHandle,
|
||||||
blockchain_read_handle: BlockchainReadHandle,
|
blockchain_read_handle: BlockchainReadHandle,
|
||||||
blockchain_context_service: BlockChainContextService,
|
mut blockchain_context_service: BlockChainContextService,
|
||||||
block_verifier_service: BlockVerifierService<
|
block_verifier_service: BlockVerifierService<
|
||||||
BlockChainContextService,
|
BlockChainContextService,
|
||||||
TxVerifierService<ConsensusBlockchainReadHandle>,
|
TxVerifierService<ConsensusBlockchainReadHandle>,
|
||||||
ConsensusBlockchainReadHandle,
|
ConsensusBlockchainReadHandle,
|
||||||
>,
|
>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let BlockChainContextResponse::Context(blockchain_context) = blockchain_context_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(BlockChainContextRequest::GetContext)
|
||||||
|
.await
|
||||||
|
.expect("TODO") else {
|
||||||
|
panic!("Blockchain context service returned wrong response!");
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
blockchain_write_handle,
|
blockchain_write_handle,
|
||||||
blockchain_read_handle,
|
blockchain_read_handle,
|
||||||
blockchain_context_service,
|
blockchain_context_service,
|
||||||
cached_blockchain_context: todo!(),
|
cached_blockchain_context: blockchain_context.unchecked_blockchain_context().clone(),
|
||||||
block_verifier_service,
|
block_verifier_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_incoming_main_chain_batch(
|
pub async fn run(mut self, mut block_batch_rx: mpsc::Receiver<BlockBatch>, mut block_single_rx: mpsc::Receiver<IncomingBlock>) {
|
||||||
&mut self,
|
|
||||||
batch: BlockBatch,
|
|
||||||
) -> Result<(), anyhow::Error> {
|
|
||||||
let VerifyBlockResponse::MainChainBatchPrepped(prepped) = self
|
|
||||||
.block_verifier_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(VerifyBlockRequest::MainChainBatchPrepareBlocks {
|
|
||||||
blocks: batch.blocks,
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
panic!("Incorrect response!");
|
|
||||||
};
|
|
||||||
|
|
||||||
for (block, txs) in prepped {
|
|
||||||
let VerifyBlockResponse::MainChain(verified_block) = block_verifier_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(VerifyBlockRequest::MainChainPrepped { block, txs })
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
else {
|
|
||||||
panic!("Incorrect response!");
|
|
||||||
};
|
|
||||||
|
|
||||||
blockchain_context_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(BlockChainContextRequest::Update(NewBlockData {
|
|
||||||
block_hash: verified_block.block_hash,
|
|
||||||
height: verified_block.height,
|
|
||||||
timestamp: verified_block.block.header.timestamp,
|
|
||||||
weight: verified_block.weight,
|
|
||||||
long_term_weight: verified_block.long_term_weight,
|
|
||||||
generated_coins: verified_block.generated_coins,
|
|
||||||
vote: HardFork::from_vote(verified_block.block.header.hardfork_signal),
|
|
||||||
cumulative_difficulty: verified_block.cumulative_difficulty,
|
|
||||||
}))
|
|
||||||
.await
|
|
||||||
.expect("TODO");
|
|
||||||
|
|
||||||
blockchain_write_handle
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(BlockchainWriteRequest::WriteBlock(verified_block))
|
|
||||||
.await
|
|
||||||
.expect("TODO");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_incoming_block_batch(&mut self, batch: BlockBatch) {
|
|
||||||
let (first_block, _) = batch
|
|
||||||
.blocks
|
|
||||||
.first()
|
|
||||||
.expect("Block batch should not be empty");
|
|
||||||
|
|
||||||
if first_block.header.previous == self.cached_blockchain_context.top_hash {
|
|
||||||
todo!("Main chain")
|
|
||||||
} else {
|
|
||||||
todo!("Alt chain")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(mut self, mut batch_rx: Receiver<BlockBatch>) {
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
Some(batch) = batch_rx.recv() => {
|
Some(batch) = block_batch_rx.recv() => {
|
||||||
self.handle_incoming_block_batch(
|
self.handle_incoming_block_batch(
|
||||||
batch,
|
batch,
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
|
Some(incoming_block) = block_single_rx.recv() => {
|
||||||
|
let IncomingBlock {
|
||||||
|
block,
|
||||||
|
prepped_txs,
|
||||||
|
response_tx
|
||||||
|
} = incoming_block;
|
||||||
|
|
||||||
|
let res = self.handle_incoming_block(block, prepped_txs).await;
|
||||||
|
let _ = response_tx.send(res);
|
||||||
|
}
|
||||||
else => {
|
else => {
|
||||||
todo!("TODO: exit the BC manager")
|
todo!("TODO: exit the BC manager")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
//! Block batch handling functions.
|
|
||||||
|
|
||||||
use crate::blockchain::types::ConsensusBlockchainReadHandle;
|
|
||||||
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
|
||||||
use cuprate_consensus::context::NewBlockData;
|
|
||||||
use cuprate_consensus::transactions::new_tx_verification_data;
|
|
||||||
use cuprate_consensus::{
|
|
||||||
BlockChainContextRequest, BlockChainContextResponse, BlockChainContextService,
|
|
||||||
BlockVerifierService, BlockchainReadRequest, BlockchainResponse, ExtendedConsensusError,
|
|
||||||
VerifyBlockRequest, VerifyBlockResponse, VerifyTxRequest, VerifyTxResponse,
|
|
||||||
};
|
|
||||||
use cuprate_p2p::block_downloader::BlockBatch;
|
|
||||||
use cuprate_types::blockchain::BlockchainWriteRequest;
|
|
||||||
use cuprate_types::{Chain, HardFork};
|
|
||||||
use rayon::prelude::*;
|
|
||||||
use tower::{Service, ServiceExt};
|
|
||||||
use tracing::{debug, error, info};
|
|
||||||
|
|
||||||
async fn handle_incoming_block_batch_main_chain<C, TxV>(
|
|
||||||
batch: BlockBatch,
|
|
||||||
block_verifier_service: &mut BlockVerifierService<C, TxV, ConsensusBlockchainReadHandle>,
|
|
||||||
blockchain_context_service: &mut C,
|
|
||||||
blockchain_write_handle: &mut BlockchainWriteHandle,
|
|
||||||
) -> Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
C: Service<
|
|
||||||
BlockChainContextRequest,
|
|
||||||
Response = BlockChainContextResponse,
|
|
||||||
Error = tower::BoxError,
|
|
||||||
> + Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
C::Future: Send + 'static,
|
|
||||||
|
|
||||||
TxV: Service<VerifyTxRequest, Response = VerifyTxResponse, Error = ExtendedConsensusError>
|
|
||||||
+ Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
TxV::Future: Send + 'static,
|
|
||||||
{
|
|
||||||
info!(
|
|
||||||
"Handling batch to main chain height: {}",
|
|
||||||
batch.blocks.first().unwrap().0.number().unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
let VerifyBlockResponse::MainChainBatchPrepped(prepped) = block_verifier_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(VerifyBlockRequest::MainChainBatchPrepareBlocks {
|
|
||||||
blocks: batch.blocks,
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
panic!("Incorrect response!");
|
|
||||||
};
|
|
||||||
|
|
||||||
for (block, txs) in prepped {
|
|
||||||
let VerifyBlockResponse::MainChain(verified_block) = block_verifier_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(VerifyBlockRequest::MainChainPrepped { block, txs })
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
panic!("Incorrect response!");
|
|
||||||
};
|
|
||||||
|
|
||||||
blockchain_context_service
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(BlockChainContextRequest::Update(NewBlockData {
|
|
||||||
block_hash: verified_block.block_hash,
|
|
||||||
height: verified_block.height,
|
|
||||||
timestamp: verified_block.block.header.timestamp,
|
|
||||||
weight: verified_block.weight,
|
|
||||||
long_term_weight: verified_block.long_term_weight,
|
|
||||||
generated_coins: verified_block.generated_coins,
|
|
||||||
vote: HardFork::from_vote(verified_block.block.header.hardfork_signal),
|
|
||||||
cumulative_difficulty: verified_block.cumulative_difficulty,
|
|
||||||
}))
|
|
||||||
.await
|
|
||||||
.expect("TODO");
|
|
||||||
|
|
||||||
blockchain_write_handle
|
|
||||||
.ready()
|
|
||||||
.await
|
|
||||||
.expect("TODO")
|
|
||||||
.call(BlockchainWriteRequest::WriteBlock(verified_block))
|
|
||||||
.await
|
|
||||||
.expect("TODO");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_incoming_block_batch_alt_chain<C, TxV>(
|
|
||||||
batch: BlockBatch,
|
|
||||||
block_verifier_service: &mut BlockVerifierService<C, TxV, ConsensusBlockchainReadHandle>,
|
|
||||||
blockchain_context_service: &mut C,
|
|
||||||
blockchain_write_handle: &mut BlockchainWriteHandle,
|
|
||||||
) -> Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
C: Service<
|
|
||||||
BlockChainContextRequest,
|
|
||||||
Response = BlockChainContextResponse,
|
|
||||||
Error = tower::BoxError,
|
|
||||||
> + Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
C::Future: Send + 'static,
|
|
||||||
|
|
||||||
TxV: Service<VerifyTxRequest, Response = VerifyTxResponse, Error = ExtendedConsensusError>
|
|
||||||
+ Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
TxV::Future: Send + 'static,
|
|
||||||
{
|
|
||||||
for (block, txs) in batch.blocks {
|
|
||||||
alt_block_info.cumulative_difficulty
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::blockchain::types::ConsensusBlockchainReadHandle;
|
use crate::blockchain::types::ConsensusBlockchainReadHandle;
|
||||||
|
use crate::signals::REORG_LOCK;
|
||||||
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
|
||||||
|
use cuprate_consensus::block::PreparedBlock;
|
||||||
|
use cuprate_consensus::context::NewBlockData;
|
||||||
use cuprate_consensus::transactions::new_tx_verification_data;
|
use cuprate_consensus::transactions::new_tx_verification_data;
|
||||||
use cuprate_consensus::{
|
use cuprate_consensus::{
|
||||||
BlockChainContextRequest, BlockChainContextResponse, BlockVerifierService,
|
BlockChainContextRequest, BlockChainContextResponse, BlockVerifierService,
|
||||||
|
@ -10,45 +13,128 @@ use cuprate_p2p::block_downloader::BlockBatch;
|
||||||
use cuprate_types::blockchain::{
|
use cuprate_types::blockchain::{
|
||||||
BlockchainReadRequest, BlockchainResponse, BlockchainWriteRequest,
|
BlockchainReadRequest, BlockchainResponse, BlockchainWriteRequest,
|
||||||
};
|
};
|
||||||
use cuprate_types::AltBlockInformation;
|
use cuprate_types::{
|
||||||
|
AltBlockInformation, HardFork, TransactionVerificationData, VerifiedBlockInformation,
|
||||||
|
};
|
||||||
|
use futures::{TryFutureExt, TryStreamExt};
|
||||||
use monero_serai::block::Block;
|
use monero_serai::block::Block;
|
||||||
use monero_serai::transaction::Transaction;
|
use monero_serai::transaction::Transaction;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
async fn handle_incoming_alt_block<C, TxV>(
|
impl super::BlockchainManager {
|
||||||
|
pub async fn handle_incoming_block(
|
||||||
|
&mut self,
|
||||||
block: Block,
|
block: Block,
|
||||||
txs: Vec<Transaction>,
|
prepared_txs: HashMap<[u8; 32], TransactionVerificationData>,
|
||||||
current_cumulative_difficulty: u128,
|
) -> Result<(), anyhow::Error> {
|
||||||
block_verifier_service: &mut BlockVerifierService<C, TxV, ConsensusBlockchainReadHandle>,
|
if block.header.previous != self.cached_blockchain_context.top_hash {
|
||||||
blockchain_context_service: &mut C,
|
self.handle_incoming_alt_block(block, prepared_txs).await?;
|
||||||
blockchain_write_handle: &mut BlockchainWriteHandle,
|
|
||||||
) -> Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
C: Service<
|
|
||||||
BlockChainContextRequest,
|
|
||||||
Response = BlockChainContextResponse,
|
|
||||||
Error = tower::BoxError,
|
|
||||||
> + Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
C::Future: Send + 'static,
|
|
||||||
|
|
||||||
TxV: Service<VerifyTxRequest, Response = VerifyTxResponse, Error = ExtendedConsensusError>
|
return Ok(());
|
||||||
+ Clone
|
}
|
||||||
+ Send
|
|
||||||
+ 'static,
|
let VerifyBlockResponse::MainChain(verified_block) = self
|
||||||
TxV::Future: Send + 'static,
|
.block_verifier_service
|
||||||
{
|
.ready()
|
||||||
let prepared_txs = txs
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(VerifyBlockRequest::MainChain {
|
||||||
|
block,
|
||||||
|
prepared_txs,
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
panic!("Incorrect response!");
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_valid_block_to_main_chain(verified_block).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_incoming_block_batch(&mut self, batch: BlockBatch) {
|
||||||
|
let (first_block, _) = batch
|
||||||
|
.blocks
|
||||||
|
.first()
|
||||||
|
.expect("Block batch should not be empty");
|
||||||
|
|
||||||
|
if first_block.header.previous == self.cached_blockchain_context.top_hash {
|
||||||
|
self.handle_incoming_block_batch_main_chain(batch).await.expect("TODO");
|
||||||
|
} else {
|
||||||
|
self.handle_incoming_block_batch_alt_chain(batch).await.expect("TODO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_incoming_block_batch_main_chain(
|
||||||
|
&mut self,
|
||||||
|
batch: BlockBatch,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
info!(
|
||||||
|
"Handling batch to main chain height: {}",
|
||||||
|
batch.blocks.first().unwrap().0.number().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let VerifyBlockResponse::MainChainBatchPrepped(prepped) = self
|
||||||
|
.block_verifier_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(VerifyBlockRequest::MainChainBatchPrepareBlocks {
|
||||||
|
blocks: batch.blocks,
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
panic!("Incorrect response!");
|
||||||
|
};
|
||||||
|
|
||||||
|
for (block, txs) in prepped {
|
||||||
|
let VerifyBlockResponse::MainChain(verified_block) = self
|
||||||
|
.block_verifier_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(VerifyBlockRequest::MainChainPrepped { block, txs })
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
panic!("Incorrect response!");
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_valid_block_to_main_chain(verified_block).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_incoming_block_batch_alt_chain(
|
||||||
|
&mut self,
|
||||||
|
batch: BlockBatch,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
for (block, txs) in batch.blocks {
|
||||||
|
let txs = txs
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|tx| {
|
.map(|tx| {
|
||||||
let tx = new_tx_verification_data(tx)?;
|
let tx = new_tx_verification_data(tx)?;
|
||||||
(tx.tx_hash, tx)
|
Ok((tx.tx_hash, tx))
|
||||||
})
|
})
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, anyhow::Error>>()?;
|
||||||
|
|
||||||
let VerifyBlockResponse::AltChain(alt_block_info) = block_verifier_service
|
self.handle_incoming_alt_block(block, txs).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_incoming_alt_block(
|
||||||
|
&mut self,
|
||||||
|
block: Block,
|
||||||
|
prepared_txs: HashMap<[u8; 32], TransactionVerificationData>,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let VerifyBlockResponse::AltChain(alt_block_info) = self
|
||||||
|
.block_verifier_service
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.expect("TODO")
|
.expect("TODO")
|
||||||
|
@ -61,44 +147,35 @@ where
|
||||||
panic!("Incorrect response!");
|
panic!("Incorrect response!");
|
||||||
};
|
};
|
||||||
|
|
||||||
if alt_block_info.cumulative_difficulty > current_cumulative_difficulty {
|
// TODO: check in consensus crate if alt block already exists.
|
||||||
todo!("do re-org");
|
|
||||||
|
if alt_block_info.cumulative_difficulty
|
||||||
|
> self.cached_blockchain_context.cumulative_difficulty
|
||||||
|
{
|
||||||
|
self.try_do_reorg(alt_block_info).await?;
|
||||||
|
// TODO: ban the peer if the reorg failed.
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
blockchain_write_handle
|
self.blockchain_write_handle
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.expect("TODO")
|
.expect("TODO")
|
||||||
.call(BlockchainWriteRequest::WriteAltBlock(alt_block_info))?;
|
.call(BlockchainWriteRequest::WriteAltBlock(alt_block_info))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_do_reorg<C, TxV>(
|
async fn try_do_reorg(
|
||||||
|
&mut self,
|
||||||
top_alt_block: AltBlockInformation,
|
top_alt_block: AltBlockInformation,
|
||||||
chain_height: usize,
|
) -> Result<(), anyhow::Error> {
|
||||||
block_verifier_service: &mut BlockVerifierService<C, TxV, ConsensusBlockchainReadHandle>,
|
let _guard = REORG_LOCK.write().await;
|
||||||
blockchain_context_service: &mut C,
|
|
||||||
blockchain_write_handle: &mut BlockchainWriteHandle,
|
|
||||||
blockchain_read_handle: &mut BlockchainReadHandle,
|
|
||||||
) -> Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
C: Service<
|
|
||||||
BlockChainContextRequest,
|
|
||||||
Response = BlockChainContextResponse,
|
|
||||||
Error = tower::BoxError,
|
|
||||||
> + Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
C::Future: Send + 'static,
|
|
||||||
|
|
||||||
TxV: Service<VerifyTxRequest, Response = VerifyTxResponse, Error = ExtendedConsensusError>
|
let BlockchainResponse::AltBlocksInChain(mut alt_blocks) = self
|
||||||
+ Clone
|
.blockchain_read_handle
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
TxV::Future: Send + 'static,
|
|
||||||
{
|
|
||||||
let BlockchainResponse::AltBlocksInChain(mut alt_blocks) = blockchain_read_handle
|
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.expect("TODO")
|
.expect("TODO")
|
||||||
|
@ -113,51 +190,115 @@ where
|
||||||
alt_blocks.push(top_alt_block);
|
alt_blocks.push(top_alt_block);
|
||||||
|
|
||||||
let split_height = alt_blocks[0].height;
|
let split_height = alt_blocks[0].height;
|
||||||
|
let current_main_chain_height = self.cached_blockchain_context.chain_height;
|
||||||
|
|
||||||
let BlockchainResponse::PopBlocks(old_main_chain_id) = blockchain_write_handle
|
let BlockchainResponse::PopBlocks(old_main_chain_id) = self
|
||||||
|
.blockchain_write_handle
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.expect("TODO")
|
.expect("TODO")
|
||||||
.call(BlockchainWriteRequest::PopBlocks(
|
.call(BlockchainWriteRequest::PopBlocks(
|
||||||
chain_height - split_height + 1,
|
current_main_chain_height - split_height + 1,
|
||||||
))
|
))
|
||||||
.await?
|
.await
|
||||||
|
.expect("TODO")
|
||||||
else {
|
else {
|
||||||
panic!("Incorrect response!");
|
panic!("Incorrect response!");
|
||||||
};
|
};
|
||||||
|
|
||||||
todo!()
|
self.blockchain_context_service
|
||||||
}
|
|
||||||
|
|
||||||
async fn verify_add_alt_blocks_to_main_chain<C, TxV>(
|
|
||||||
alt_blocks: Vec<AltBlockInformation>,
|
|
||||||
block_verifier_service: &mut BlockVerifierService<C, TxV, ConsensusBlockchainReadHandle>,
|
|
||||||
blockchain_context_service: &mut C,
|
|
||||||
blockchain_write_handle: &mut BlockchainWriteHandle,
|
|
||||||
) -> Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
C: Service<
|
|
||||||
BlockChainContextRequest,
|
|
||||||
Response = BlockChainContextResponse,
|
|
||||||
Error = tower::BoxError,
|
|
||||||
> + Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
C::Future: Send + 'static,
|
|
||||||
|
|
||||||
TxV: Service<VerifyTxRequest, Response = VerifyTxResponse, Error = ExtendedConsensusError>
|
|
||||||
+ Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
TxV::Future: Send + 'static,
|
|
||||||
{
|
|
||||||
let VerifyBlockResponse::AltChain(alt_block_info) = block_verifier_service
|
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.expect("TODO")
|
.expect("TODO")
|
||||||
.call(VerifyBlockRequest::MainChainPrepped { block, txs })
|
.call(BlockChainContextRequest::PopBlocks {
|
||||||
|
numb_blocks: current_main_chain_height - split_height + 1,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.expect("TODO");
|
||||||
|
|
||||||
|
let reorg_res = self.verify_add_alt_blocks_to_main_chain(alt_blocks).await;
|
||||||
|
|
||||||
|
match reorg_res {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(e) => {
|
||||||
|
todo!("Reverse reorg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn verify_add_alt_blocks_to_main_chain(
|
||||||
|
&mut self,
|
||||||
|
alt_blocks: Vec<AltBlockInformation>,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
for mut alt_block in alt_blocks {
|
||||||
|
let prepped_txs = alt_block
|
||||||
|
.txs
|
||||||
|
.drain(..)
|
||||||
|
.map(|tx| Ok(Arc::new(tx.try_into()?)))
|
||||||
|
.collect::<Result<_, anyhow::Error>>()?;
|
||||||
|
|
||||||
|
let prepped_block = PreparedBlock::new_alt_block(alt_block)?;
|
||||||
|
|
||||||
|
let VerifyBlockResponse::MainChain(verified_block) = self
|
||||||
|
.block_verifier_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(VerifyBlockRequest::MainChainPrepped {
|
||||||
|
block: prepped_block,
|
||||||
|
txs: prepped_txs,
|
||||||
|
})
|
||||||
.await?
|
.await?
|
||||||
else {
|
else {
|
||||||
panic!("Incorrect response!");
|
panic!("Incorrect response!");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.add_valid_block_to_main_chain(verified_block).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_valid_block_to_main_chain(
|
||||||
|
&mut self,
|
||||||
|
verified_block: VerifiedBlockInformation,
|
||||||
|
) {
|
||||||
|
self.blockchain_context_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(BlockChainContextRequest::Update(NewBlockData {
|
||||||
|
block_hash: verified_block.block_hash,
|
||||||
|
height: verified_block.height,
|
||||||
|
timestamp: verified_block.block.header.timestamp,
|
||||||
|
weight: verified_block.weight,
|
||||||
|
long_term_weight: verified_block.long_term_weight,
|
||||||
|
generated_coins: verified_block.generated_coins,
|
||||||
|
vote: HardFork::from_vote(verified_block.block.header.hardfork_signal),
|
||||||
|
cumulative_difficulty: verified_block.cumulative_difficulty,
|
||||||
|
}))
|
||||||
|
.await
|
||||||
|
.expect("TODO");
|
||||||
|
|
||||||
|
self.blockchain_write_handle
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(BlockchainWriteRequest::WriteBlock(verified_block))
|
||||||
|
.await
|
||||||
|
.expect("TODO");
|
||||||
|
|
||||||
|
let BlockChainContextResponse::Context(blockchain_context) = self
|
||||||
|
.blockchain_context_service
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.expect("TODO")
|
||||||
|
.call(BlockChainContextRequest::GetContext)
|
||||||
|
.await
|
||||||
|
.expect("TODO") else {
|
||||||
|
panic!("Incorrect response!");
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cached_blockchain_context = blockchain_context.unchecked_blockchain_context().clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod blockchain;
|
||||||
mod config;
|
mod config;
|
||||||
mod p2p;
|
mod p2p;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
|
mod signals;
|
||||||
mod txpool;
|
mod txpool;
|
||||||
|
|
||||||
use blockchain::check_add_genesis;
|
use blockchain::check_add_genesis;
|
||||||
|
@ -58,7 +59,7 @@ fn main() {
|
||||||
context_svc,
|
context_svc,
|
||||||
block_verifier,
|
block_verifier,
|
||||||
config.block_downloader_config(),
|
config.block_downloader_config(),
|
||||||
);
|
).await;
|
||||||
|
|
||||||
// TODO: this can be removed as long as the main thread does not exit, so when command handling
|
// TODO: this can be removed as long as the main thread does not exit, so when command handling
|
||||||
// is added
|
// is added
|
||||||
|
|
3
binaries/cuprated/src/signals.rs
Normal file
3
binaries/cuprated/src/signals.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
pub static REORG_LOCK: RwLock<()> = RwLock::const_new(());
|
|
@ -88,19 +88,15 @@ mod sealed {
|
||||||
|
|
||||||
/// An internal trait for the address book for a [`NetworkZone`] that adds the requirement of [`borsh`] traits
|
/// An internal trait for the address book for a [`NetworkZone`] that adds the requirement of [`borsh`] traits
|
||||||
/// onto the network address.
|
/// onto the network address.
|
||||||
pub trait BorshNetworkZone:
|
pub trait BorshNetworkZone: NetworkZone<Addr = Self::BorshAddr> {
|
||||||
NetworkZone<
|
type BorshAddr: NetZoneAddress + borsh::BorshDeserialize + borsh::BorshSerialize;
|
||||||
Addr: NetZoneAddress<BanID: borsh::BorshDeserialize + borsh::BorshSerialize>
|
|
||||||
+ borsh::BorshDeserialize
|
|
||||||
+ borsh::BorshSerialize,
|
|
||||||
>
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NetworkZone> BorshNetworkZone for T
|
impl<T: NetworkZone> BorshNetworkZone for T
|
||||||
where
|
where
|
||||||
T::Addr: borsh::BorshDeserialize + borsh::BorshSerialize,
|
T::Addr: borsh::BorshDeserialize + borsh::BorshSerialize,
|
||||||
<T::Addr as NetZoneAddress>::BanID: borsh::BorshDeserialize + borsh::BorshSerialize,
|
|
||||||
{
|
{
|
||||||
|
type BorshAddr = T::Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
BIN
p2p_state.bin
BIN
p2p_state.bin
Binary file not shown.
|
@ -628,7 +628,7 @@ fn next_missing_chain_entry(env: &ConcreteEnv, block_hashes: Vec<[u8; 32]>) -> R
|
||||||
let block_hashes: Vec<_> = table_block_infos
|
let block_hashes: Vec<_> = table_block_infos
|
||||||
.get_range(start_height..end_height)?
|
.get_range(start_height..end_height)?
|
||||||
.map(|block_info| Ok(block_info?.block_hash))
|
.map(|block_info| Ok(block_info?.block_hash))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, RuntimeError>>()?;
|
||||||
|
|
||||||
let first_missing_block = if block_hashes.len() > 1 {
|
let first_missing_block = if block_hashes.len() > 1 {
|
||||||
let table_block_blobs = env_inner.open_db_ro::<BlockBlobs>(&tx_ro)?;
|
let table_block_blobs = env_inner.open_db_ro::<BlockBlobs>(&tx_ro)?;
|
||||||
|
|
Loading…
Reference in a new issue