Skip to content

Commit aa274eb

Browse files
committed
add fluffy_missing_txs handler
1 parent ec77a91 commit aa274eb

File tree

7 files changed

+132
-20
lines changed

7 files changed

+132
-20
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

binaries/cuprated/src/p2p/request_handler.rs

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use bytes::Bytes;
2+
use futures::future::BoxFuture;
3+
use futures::FutureExt;
14
use std::{
25
future::{ready, Ready},
36
task::{Context, Poll},
47
};
5-
6-
use futures::future::BoxFuture;
7-
use futures::FutureExt;
88
use tower::{Service, ServiceExt};
99

1010
use cuprate_blockchain::service::BlockchainReadHandle;
@@ -15,7 +15,11 @@ use cuprate_helper::map::{combine_low_high_bits_to_u128, split_u128_into_low_hig
1515
use cuprate_p2p::constants::MAX_BLOCK_BATCH_LEN;
1616
use cuprate_p2p_core::{client::PeerInformation, NetworkZone, ProtocolRequest, ProtocolResponse};
1717
use cuprate_types::blockchain::{BlockchainReadRequest, BlockchainResponse};
18-
use cuprate_wire::protocol::{ChainRequest, ChainResponse, GetObjectsRequest, GetObjectsResponse};
18+
use cuprate_types::{BlockCompleteEntry, MissingTxsInBlock, TransactionBlobs};
19+
use cuprate_wire::protocol::{
20+
ChainRequest, ChainResponse, FluffyMissingTransactionsRequest, GetObjectsRequest,
21+
GetObjectsResponse, NewFluffyBlock,
22+
};
1923

2024
#[derive(Clone)]
2125
pub struct P2pProtocolRequestHandlerMaker {
@@ -63,12 +67,20 @@ impl<Z: NetworkZone> Service<ProtocolRequest> for P2pProtocolRequestHandler<Z> {
6367
ProtocolRequest::GetObjects(r) => {
6468
get_objects(r, self.blockchain_read_handle.clone()).boxed()
6569
}
66-
ProtocolRequest::GetChain(_) => todo!(),
67-
ProtocolRequest::FluffyMissingTxs(_) => todo!(),
68-
ProtocolRequest::GetTxPoolCompliment(_) => todo!(),
69-
ProtocolRequest::NewBlock(_) => todo!(),
70+
ProtocolRequest::GetChain(r) => {
71+
get_chain(r, self.blockchain_read_handle.clone()).boxed()
72+
}
73+
ProtocolRequest::FluffyMissingTxs(r) => {
74+
fluffy_missing_txs(r, self.blockchain_read_handle.clone()).boxed()
75+
}
76+
ProtocolRequest::NewBlock(_) => ready(Err(anyhow::anyhow!(
77+
"Peer sent a full block when we support fluffy blocks"
78+
)))
79+
.boxed(),
7080
ProtocolRequest::NewFluffyBlock(_) => todo!(),
71-
ProtocolRequest::NewTransactions(_) => todo!(),
81+
ProtocolRequest::GetTxPoolCompliment(_) | ProtocolRequest::NewTransactions(_) => {
82+
ready(Ok(ProtocolResponse::NA)).boxed()
83+
} // TODO: tx-pool
7284
}
7385
}
7486
}
@@ -138,6 +150,10 @@ async fn get_chain(
138150
panic!("blockchain returned wrong response!");
139151
};
140152

153+
if start_height == 0 {
154+
anyhow::bail!("The peers chain has a different genesis block than ours.");
155+
}
156+
141157
let (cumulative_difficulty_low64, cumulative_difficulty_top64) =
142158
split_u128_into_low_high_bits(cumulative_difficulty);
143159

@@ -147,7 +163,7 @@ async fn get_chain(
147163
cumulative_difficulty_low64,
148164
cumulative_difficulty_top64,
149165
m_block_ids: ByteArrayVec::from(block_ids),
150-
first_block: Default::default(),
166+
first_block: first_block_blob.map_or(Bytes::new(), Bytes::from),
151167
// only needed when
152168
m_block_weights: if want_pruned_data {
153169
block_weights.into_iter().map(usize_to_u64).collect()
@@ -156,3 +172,43 @@ async fn get_chain(
156172
},
157173
}))
158174
}
175+
176+
/// [`ProtocolRequest::FluffyMissingTxs`]
177+
async fn fluffy_missing_txs(
178+
mut request: FluffyMissingTransactionsRequest,
179+
mut blockchain_read_handle: BlockchainReadHandle,
180+
) -> anyhow::Result<ProtocolResponse> {
181+
let tx_indexes = std::mem::take(&mut request.missing_tx_indices);
182+
let block_hash: [u8; 32] = *request.block_hash;
183+
let current_blockchain_height = request.current_blockchain_height;
184+
185+
// de-allocate the backing `Bytes`.
186+
drop(request);
187+
188+
let BlockchainResponse::MissingTxsInBlock(res) = blockchain_read_handle
189+
.ready()
190+
.await?
191+
.call(BlockchainReadRequest::MissingTxsInBlock {
192+
block_hash,
193+
tx_indexes,
194+
})
195+
.await?
196+
else {
197+
panic!("blockchain returned wrong response!");
198+
};
199+
200+
let Some(MissingTxsInBlock { block, txs }) = res else {
201+
anyhow::bail!("The peer requested txs out of range.");
202+
};
203+
204+
Ok(ProtocolResponse::NewFluffyBlock(NewFluffyBlock {
205+
b: BlockCompleteEntry {
206+
block: Bytes::from(block),
207+
txs: TransactionBlobs::Normal(txs.into_iter().map(Bytes::from).collect()),
208+
pruned: false,
209+
// only needed for pruned blocks.
210+
block_weight: 0,
211+
},
212+
current_blockchain_height,
213+
}))
214+
}

net/wire/src/p2p/protocol.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ epee_object!(
159159
current_blockchain_height: u64,
160160
);
161161

162-
/// A request for Txs we are missing from our `TxPool`
162+
/// A request for txs we are missing from an incoming block.
163163
#[derive(Debug, Clone, PartialEq, Eq)]
164164
pub struct FluffyMissingTransactionsRequest {
165165
/// The Block we are missing the Txs in

storage/blockchain/src/service/read.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ use rayon::{
1414
};
1515
use thread_local::ThreadLocal;
1616

17-
use cuprate_database::{ConcreteEnv, DatabaseIter, DatabaseRo, Env, EnvInner, RuntimeError};
18-
use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads};
19-
use cuprate_helper::map::combine_low_high_bits_to_u128;
20-
use cuprate_types::{
21-
blockchain::{BlockchainReadRequest, BlockchainResponse},
22-
Chain, ChainId, ExtendedBlockHeader, OutputOnChain,
23-
};
24-
2517
use crate::{
2618
ops::{
2719
alt_block::{
@@ -45,6 +37,13 @@ use crate::{
4537
AltBlockHeight, Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId,
4638
},
4739
};
40+
use cuprate_database::{ConcreteEnv, DatabaseIter, DatabaseRo, Env, EnvInner, RuntimeError};
41+
use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThreads};
42+
use cuprate_helper::map::combine_low_high_bits_to_u128;
43+
use cuprate_types::{
44+
blockchain::{BlockchainReadRequest, BlockchainResponse},
45+
Chain, ChainId, ExtendedBlockHeader, MissingTxsInBlock, OutputOnChain,
46+
};
4847

4948
//---------------------------------------------------------------------------------------------------- init_read_service
5049
/// Initialize the [`BlockchainReadHandle`] thread-pool backed by [`rayon`].
@@ -110,6 +109,10 @@ fn map_request(
110109
R::CompactChainHistory => compact_chain_history(env),
111110
R::NextChainEntry(block_hashes, amount) => next_chain_entry(env, &block_hashes, amount),
112111
R::FindFirstUnknown(block_ids) => find_first_unknown(env, &block_ids),
112+
R::MissingTxsInBlock {
113+
block_hash,
114+
tx_indexes,
115+
} => missing_txs_in_block(env, block_hash, tx_indexes),
113116
R::AltBlocksInChain(chain_id) => alt_blocks_in_chain(env, chain_id),
114117
}
115118

@@ -649,6 +652,36 @@ fn find_first_unknown(env: &ConcreteEnv, block_ids: &[BlockHash]) -> ResponseRes
649652
})
650653
}
651654

655+
/// [`BlockchainReadRequest::MissingTxsInBlock`]
656+
fn missing_txs_in_block(
657+
env: &ConcreteEnv,
658+
block_hash: [u8; 32],
659+
missing_txs: Vec<u64>,
660+
) -> ResponseResult {
661+
// Single-threaded, no `ThreadLocal` required.
662+
let env_inner = env.env_inner();
663+
let tx_ro = env_inner.tx_ro()?;
664+
let tables = env_inner.open_tables(&tx_ro)?;
665+
666+
let block_height = tables.block_heights().get(&block_hash)?;
667+
668+
let (block, miner_tx_index, numb_txs) = get_block_blob_with_tx_indexes(&block_height, &tables)?;
669+
let first_tx_index = miner_tx_index + 1;
670+
671+
if numb_txs < missing_txs.len() {
672+
return Ok(BlockchainResponse::MissingTxsInBlock(None));
673+
}
674+
675+
let txs = missing_txs
676+
.into_iter()
677+
.map(|index_offset| Ok(tables.tx_blobs().get(&(first_tx_index + index_offset))?.0))
678+
.collect::<Result<_, RuntimeError>>()?;
679+
680+
Ok(BlockchainResponse::MissingTxsInBlock(Some(
681+
MissingTxsInBlock { block, txs },
682+
)))
683+
}
684+
652685
/// [`BlockchainReadRequest::AltBlocksInChain`]
653686
fn alt_blocks_in_chain(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult {
654687
// Prepare tx/tables in `ThreadLocal`.

types/src/blockchain.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
ops::Range,
99
};
1010

11+
use crate::types::MissingTxsInBlock;
1112
use crate::{
1213
types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation},
1314
AltBlockInformation, BlockCompleteEntry, ChainId,
@@ -113,6 +114,16 @@ pub enum BlockchainReadRequest {
113114
/// as this request performs a binary search.
114115
FindFirstUnknown(Vec<[u8; 32]>),
115116

117+
/// A request for transactions from a specific block.
118+
MissingTxsInBlock {
119+
/// The block to get transactions from.
120+
block_hash: [u8; 32],
121+
/// The indexes of the transactions from the block.
122+
/// This is not the global index of the txs, instead it is the local index as they appear in
123+
/// the block/
124+
tx_indexes: Vec<u64>,
125+
},
126+
116127
/// A request for all alt blocks in the chain with the given [`ChainId`].
117128
AltBlocksInChain(ChainId),
118129
}
@@ -252,6 +263,11 @@ pub enum BlockchainResponse {
252263
/// This will be [`None`] if all blocks were known.
253264
FindFirstUnknown(Option<(usize, usize)>),
254265

266+
/// The response for [`BlockchainReadRequest::MissingTxsInBlock`].
267+
///
268+
/// Will return [`None`] if the request contained an index out of range.
269+
MissingTxsInBlock(Option<MissingTxsInBlock>),
270+
255271
/// The response for [`BlockchainReadRequest::AltBlocksInChain`].
256272
///
257273
/// Contains all the alt blocks in the alt-chain in chronological order.

types/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use transaction_verification_data::{
2020
CachedVerificationState, TransactionVerificationData, TxVersion,
2121
};
2222
pub use types::{
23-
AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, OutputOnChain,
23+
AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, MissingTxsInBlock, OutputOnChain,
2424
VerifiedBlockInformation, VerifiedTransactionInformation,
2525
};
2626

types/src/types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ pub struct OutputOnChain {
155155
pub commitment: EdwardsPoint,
156156
}
157157

158+
#[derive(Clone, Debug, PartialEq, Eq)]
159+
pub struct MissingTxsInBlock {
160+
pub block: Vec<u8>,
161+
pub txs: Vec<Vec<u8>>,
162+
}
163+
158164
//---------------------------------------------------------------------------------------------------- Tests
159165
#[cfg(test)]
160166
mod test {

0 commit comments

Comments
 (0)