cfxcore/sync/message/
snapshot_manifest_response.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use crate::{
6    block_data_manager::BlockExecutionResult,
7    message::{GetMaybeRequestId, Message, MessageProtocolVersionBound, MsgId},
8    sync::{
9        message::{msgid, Context, Handleable, SnapshotManifestRequest},
10        state::storage::RangedManifest,
11        Error, SYNC_PROTO_V1, SYNC_PROTO_V3,
12    },
13};
14use cfx_types::H256;
15use network::service::ProtocolVersion;
16use primitives::{MerkleHash, StateRoot};
17use rlp::Encodable;
18use rlp_derive::{RlpDecodable, RlpEncodable};
19
20#[derive(RlpDecodable, RlpEncodable, Default)]
21pub struct SnapshotManifestResponse {
22    pub request_id: u64,
23    pub manifest: RangedManifest,
24    // FIXME: this TODO must be addressed before release, or we must have a
25    // FIXME: protocol version field
26    //
27    // We actually need state_root_blame_vec for two epochs: snapshot_epoch_id
28    // and its next snapshot + 1 epoch; and the state_root of snapshot_epoch_id
29    // and the state root of its next snapshot + 1 epoch to get
30    // snapshot_merkle_root of snapshot_epoch_id. The
31    // current implementation passes state_blame_vec for the entire range of
32    // snapshot_epoch_id to its next snapshot's trusted blame block,
33    // which should be improved.
34    //
35    // TODO: reduce the data to pass over network.
36    pub state_root_vec: Vec<StateRoot>,
37    pub receipt_blame_vec: Vec<H256>,
38    pub bloom_blame_vec: Vec<H256>,
39    pub block_receipts: Vec<BlockExecutionResult>,
40
41    // Debug only field.
42    // TODO: can be deleted later.
43    pub snapshot_merkle_root: MerkleHash,
44}
45
46build_msg_impl! {
47    SnapshotManifestResponse, msgid::GET_SNAPSHOT_MANIFEST_RESPONSE,
48    "SnapshotManifestResponse", SYNC_PROTO_V1, SYNC_PROTO_V3
49}
50
51impl Handleable for SnapshotManifestResponse {
52    fn handle(self, ctx: &Context) -> Result<(), Error> {
53        let message = ctx.match_request(self.request_id)?;
54
55        let request = message.downcast_ref::<SnapshotManifestRequest>(
56            ctx.io,
57            &ctx.manager.request_manager,
58        )?;
59
60        if let Err(e) = self.validate(ctx, request) {
61            ctx.manager
62                .request_manager
63                .resend_request_to_another_peer(ctx.io, &message);
64            return Err(e);
65        }
66
67        ctx.manager
68            .state_sync
69            .handle_snapshot_manifest_response(ctx, self, &request)?;
70
71        Ok(())
72    }
73}
74
75impl SnapshotManifestResponse {
76    fn validate(
77        &self, _: &Context, request: &SnapshotManifestRequest,
78    ) -> Result<(), Error> {
79        if request.is_initial_request() && self.state_root_vec.is_empty() {
80            debug!("Responded snapshot manifest has empty blame states");
81            bail!(Error::InvalidSnapshotManifest(
82                "state blame vector not found".into()
83            ));
84        }
85
86        if self.state_root_vec.len() != self.receipt_blame_vec.len()
87            || self.state_root_vec.len() != self.bloom_blame_vec.len()
88        {
89            debug!("Responded snapshot manifest has mismatch blame states/receipts/blooms");
90            bail!(Error::InvalidSnapshotManifest(
91                "blame vector length mismatch".into()
92            ));
93        }
94
95        Ok(())
96    }
97}