use crate::{
block_data_manager::BlockExecutionResult,
message::{GetMaybeRequestId, Message, MessageProtocolVersionBound, MsgId},
sync::{
message::{msgid, Context, Handleable, SnapshotManifestRequest},
state::storage::RangedManifest,
Error, SYNC_PROTO_V1, SYNC_PROTO_V3,
},
};
use cfx_types::H256;
use network::service::ProtocolVersion;
use primitives::{MerkleHash, StateRoot};
use rlp::Encodable;
use rlp_derive::{RlpDecodable, RlpEncodable};
#[derive(RlpDecodable, RlpEncodable, Default)]
pub struct SnapshotManifestResponse {
pub request_id: u64,
pub manifest: RangedManifest,
pub state_root_vec: Vec<StateRoot>,
pub receipt_blame_vec: Vec<H256>,
pub bloom_blame_vec: Vec<H256>,
pub block_receipts: Vec<BlockExecutionResult>,
pub snapshot_merkle_root: MerkleHash,
}
build_msg_impl! {
SnapshotManifestResponse, msgid::GET_SNAPSHOT_MANIFEST_RESPONSE,
"SnapshotManifestResponse", SYNC_PROTO_V1, SYNC_PROTO_V3
}
impl Handleable for SnapshotManifestResponse {
fn handle(self, ctx: &Context) -> Result<(), Error> {
let message = ctx.match_request(self.request_id)?;
let request = message.downcast_ref::<SnapshotManifestRequest>(
ctx.io,
&ctx.manager.request_manager,
)?;
if let Err(e) = self.validate(ctx, request) {
ctx.manager
.request_manager
.resend_request_to_another_peer(ctx.io, &message);
return Err(e);
}
ctx.manager
.state_sync
.handle_snapshot_manifest_response(ctx, self, &request)?;
Ok(())
}
}
impl SnapshotManifestResponse {
fn validate(
&self, _: &Context, request: &SnapshotManifestRequest,
) -> Result<(), Error> {
if request.is_initial_request() && self.state_root_vec.is_empty() {
debug!("Responded snapshot manifest has empty blame states");
bail!(Error::InvalidSnapshotManifest(
"state blame vector not found".into()
));
}
if self.state_root_vec.len() != self.receipt_blame_vec.len()
|| self.state_root_vec.len() != self.bloom_blame_vec.len()
{
debug!("Responded snapshot manifest has mismatch blame states/receipts/blooms");
bail!(Error::InvalidSnapshotManifest(
"blame vector length mismatch".into()
));
}
Ok(())
}
}