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

fix: should only return main chain data #4182

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ impl<'a> GetBlocksProofProcess<'a> {

let snapshot = self.protocol.shared.snapshot();

let last_hash = self.message.last_hash().to_entity();
let last_block = if let Some(block) = snapshot.get_block(&last_hash) {
block
} else {
let last_block_hash = self.message.last_hash().to_entity();
if !snapshot.is_main_chain(&last_block_hash) {
return self
.protocol
.reply_tip_state::<packed::SendBlocksProof>(self.peer, self.nc);
};
}
let last_block = snapshot
.get_block(&last_block_hash)
.expect("block should be in store");

let block_hashes: Vec<_> = self
.message
Expand All @@ -59,42 +60,30 @@ impl<'a> GetBlocksProofProcess<'a> {
let mut uniq = HashSet::new();
if !block_hashes
.iter()
.chain([last_hash.clone()].iter())
.chain([last_block_hash].iter())
.all(|hash| uniq.insert(hash))
{
return StatusCode::MalformedProtocolMessage
.with_context("duplicate block hash exists");
}

let (positions, block_headers, missing_blocks) = block_hashes
let (found, missing): (Vec<_>, Vec<_>) = block_hashes
.into_iter()
.map(|block_hash| {
snapshot
.get_block_header(&block_hash)
.map(|header| header.number())
.filter(|number| *number != last_block.number())
.and_then(|number| snapshot.get_ancestor(&last_hash, number))
.filter(|header| header.hash() == block_hash)
.ok_or(block_hash)
})
.fold(
(Vec::new(), Vec::new(), Vec::new()),
|(mut positions, mut block_headers, mut missing_blocks), result| {
match result {
Ok(header) => {
positions.push(leaf_index_to_pos(header.number()));
block_headers.push(header);
}
Err(block_hash) => {
missing_blocks.push(block_hash);
}
}
(positions, block_headers, missing_blocks)
},
);
.partition(|block_hash| snapshot.is_main_chain(block_hash));

let mut positions = Vec::with_capacity(found.len());
let mut block_headers = Vec::with_capacity(found.len());

for block_hash in found {
let header = snapshot
.get_block_header(&block_hash)
.expect("header should be in store");
positions.push(leaf_index_to_pos(header.number()));
block_headers.push(header.data());
}

let proved_items = block_headers.into_iter().map(|view| view.data()).pack();
let missing_items = missing_blocks.pack();
let proved_items = block_headers.pack();
let missing_items = missing.pack();

self.protocol.reply_proof::<packed::SendBlocksProof>(
self.peer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,14 @@ impl<'a> GetLastStateProofProcess<'a> {
let snapshot = self.protocol.shared.snapshot();

let last_block_hash = self.message.last_hash().to_entity();
let last_block = if !snapshot.is_main_chain(&last_block_hash) {
if !snapshot.is_main_chain(&last_block_hash) {
return self
.protocol
.reply_tip_state::<packed::SendLastStateProof>(self.peer, self.nc);
} else if let Some(block) = snapshot.get_block(&last_block_hash) {
block
} else {
let errmsg = format!(
"the block is in the main chain but not found, its hash is {last_block_hash:#x}"
);
return StatusCode::InternalError.with_context(errmsg);
};
}
let last_block = snapshot
.get_block(&last_block_hash)
.expect("block should be in store");

let start_block_hash = self.message.start_hash().to_entity();
let start_block_number: BlockNumber = self.message.start_number().unpack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,107 +40,83 @@ impl<'a> GetTransactionsProofProcess<'a> {

let snapshot = self.protocol.shared.snapshot();

let last_hash = self.message.last_hash().to_entity();
let last_block = if let Some(block) = snapshot.get_block(&last_hash) {
block
} else {
let last_block_hash = self.message.last_hash().to_entity();
if !snapshot.is_main_chain(&last_block_hash) {
return self
.protocol
.reply_tip_state::<packed::SendTransactionsProof>(self.peer, self.nc);
};
}
let last_block = snapshot
.get_block(&last_block_hash)
.expect("block should be in store");

let (txs_in_blocks, missing_txs) = self
let (found, missing): (Vec<_>, Vec<_>) = self
.message
.tx_hashes()
.to_entity()
.into_iter()
.map(|tx_hash| {
let tx_with_info = snapshot.get_transaction_with_info(&tx_hash);
(tx_hash, tx_with_info)
})
.fold(
(HashMap::new(), Vec::new()),
|(mut found, mut missing_txs), (tx_hash, tx_with_info)| {
if let Some((tx, tx_info)) = tx_with_info {
found
.entry(tx_info.block_hash)
.or_insert_with(Vec::new)
.push((tx, tx_info.index));
} else {
missing_txs.push(tx_hash);
}
(found, missing_txs)
},
);

let (positions, filtered_blocks, missing_txs) = txs_in_blocks
.into_iter()
.map(|(block_hash, txs_and_tx_indices)| {
.partition(|tx_hash| {
snapshot
.get_block_header(&block_hash)
.map(|header| header.number())
.filter(|number| *number != last_block.number())
.and_then(|number| snapshot.get_ancestor(&last_hash, number))
.filter(|header| header.hash() == block_hash)
.and_then(|_| snapshot.get_block(&block_hash))
.map(|block| (block, txs_and_tx_indices.clone()))
.ok_or_else(|| {
txs_and_tx_indices
.into_iter()
.map(|(tx, _)| tx.hash())
.collect::<Vec<_>>()
})
})
.fold(
(Vec::new(), Vec::new(), missing_txs),
|(mut positions, mut filtered_blocks, mut missing_txs), result| {
match result {
Ok((block, txs_and_tx_indices)) => {
let merkle_proof = CBMT::build_merkle_proof(
&block
.transactions()
.iter()
.map(|tx| tx.hash())
.collect::<Vec<_>>(),
&txs_and_tx_indices
.iter()
.map(|(_, index)| *index as u32)
.collect::<Vec<_>>(),
)
.expect("build proof with verified inputs should be OK");

let txs: Vec<_> = txs_and_tx_indices
.into_iter()
.map(|(tx, _)| tx.data())
.collect();

let filtered_block = packed::FilteredBlock::new_builder()
.header(block.header().data())
.witnesses_root(block.calc_witnesses_root())
.transactions(txs.pack())
.proof(
packed::MerkleProof::new_builder()
.indices(merkle_proof.indices().to_owned().pack())
.lemmas(merkle_proof.lemmas().to_owned().pack())
.build(),
)
.build();

positions.push(leaf_index_to_pos(block.number()));
filtered_blocks.push(filtered_block);
}
Err(tx_hashes) => {
missing_txs.extend(tx_hashes);
}
}
(positions, filtered_blocks, missing_txs)
},
);
.get_transaction_info(tx_hash)
.map(|tx_info| snapshot.is_main_chain(&tx_info.block_hash))
.unwrap_or_default()
});

let mut txs_in_blocks = HashMap::new();
for tx_hash in found {
let (tx, tx_info) = snapshot
.get_transaction_with_info(&tx_hash)
.expect("tx exists");
txs_in_blocks
.entry(tx_info.block_hash)
.or_insert_with(Vec::new)
.push((tx, tx_info.index));
}

let mut positions = Vec::with_capacity(txs_in_blocks.len());
let mut filtered_blocks = Vec::with_capacity(txs_in_blocks.len());
for (block_hash, txs_and_tx_indices) in txs_in_blocks.into_iter() {
let block = snapshot
.get_block(&block_hash)
.expect("block should be in store");
let merkle_proof = CBMT::build_merkle_proof(
&block
.transactions()
.iter()
.map(|tx| tx.hash())
.collect::<Vec<_>>(),
&txs_and_tx_indices
.iter()
.map(|(_, index)| *index as u32)
.collect::<Vec<_>>(),
)
.expect("build proof with verified inputs should be OK");

let txs: Vec<_> = txs_and_tx_indices
.into_iter()
.map(|(tx, _)| tx.data())
.collect();

let filtered_block = packed::FilteredBlock::new_builder()
.header(block.header().data())
.witnesses_root(block.calc_witnesses_root())
.transactions(txs.pack())
.proof(
packed::MerkleProof::new_builder()
.indices(merkle_proof.indices().to_owned().pack())
.lemmas(merkle_proof.lemmas().to_owned().pack())
.build(),
)
.build();

positions.push(leaf_index_to_pos(block.number()));
filtered_blocks.push(filtered_block);
}

let proved_items = packed::FilteredBlockVec::new_builder()
.set(filtered_blocks)
.build();
let missing_items = missing_txs.pack();
let missing_items = missing.pack();

self.protocol.reply_proof::<packed::SendTransactionsProof>(
self.peer,
Expand Down
Loading