1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright 2019 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/

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,
    // FIXME: this TODO must be addressed before release, or we must have a
    // FIXME: protocol version field
    //
    // We actually need state_root_blame_vec for two epochs: snapshot_epoch_id
    // and its next snapshot + 1 epoch; and the state_root of snapshot_epoch_id
    // and the state root of its next snapshot + 1 epoch to get
    // snapshot_merkle_root of snapshot_epoch_id. The
    // current implementation passes state_blame_vec for the entire range of
    // snapshot_epoch_id to its next snapshot's trusted blame block,
    // which should be improved.
    //
    // TODO: reduce the data to pass over network.
    pub state_root_vec: Vec<StateRoot>,
    pub receipt_blame_vec: Vec<H256>,
    pub bloom_blame_vec: Vec<H256>,
    pub block_receipts: Vec<BlockExecutionResult>,

    // Debug only field.
    // TODO: can be deleted later.
    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(())
    }
}