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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0
// Copyright 2021 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/
use diem_types::{
ledger_info::LedgerInfoWithSignatures,
transaction::{TransactionListWithProof, Version},
};
use serde::{Deserialize, Serialize};
use std::fmt;
/// The response can carry different LedgerInfo types depending on whether the
/// verification is done via the local trusted validator set or a local
/// waypoint.
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum ResponseLedgerInfo {
/// A typical response carries a LedgerInfo with signatures that should be
/// verified using the local trusted validator set.
/// **DEPRECATED**: `VerifiableLedgerInfo` is only required for backward
/// compatibility. State sync avoids sending these response types and
/// instead uses `ProgressiveLedgerInfo` below. This message will be removed on the next breaking release: <https://github.com/diem/diem/issues/8013>
VerifiableLedgerInfo(LedgerInfoWithSignatures),
/// A response to `TargetType::HighestAvailable` chunk request type.
ProgressiveLedgerInfo {
// LedgerInfo that the corresponding GetChunkResponse is built relative
// to.
target_li: LedgerInfoWithSignatures,
// LedgerInfo for a version later than that of `target_li`
// If `None`, this is the same as `target_li`
highest_li: Option<LedgerInfoWithSignatures>,
},
/// During the initial catchup upon startup the chunks carry LedgerInfo
/// that is verified using the local waypoint.
LedgerInfoForWaypoint {
// LedgerInfo corresponding to the waypoint version.
waypoint_li: LedgerInfoWithSignatures,
// In case a chunk terminates an epoch, the LedgerInfo corresponding to
// the epoch boundary.
end_of_epoch_li: Option<LedgerInfoWithSignatures>,
},
}
impl ResponseLedgerInfo {
/// The version of the LedgerInfo relative to which the transactions proofs
/// are built.
pub fn version(&self) -> Version {
match self {
ResponseLedgerInfo::VerifiableLedgerInfo(li) => {
li.ledger_info().version()
}
ResponseLedgerInfo::ProgressiveLedgerInfo { target_li, .. } => {
target_li.ledger_info().version()
}
ResponseLedgerInfo::LedgerInfoForWaypoint {
waypoint_li, ..
} => waypoint_li.ledger_info().version(),
}
}
}
/// The returned chunk is bounded by the end of the known_epoch of the requester
/// (i.e., a chunk never crosses epoch boundaries).
#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
pub struct GetChunkResponse {
/// The proofs are built relative to the LedgerInfo in `response_li`.
/// The specifics of ledger info verification depend on its type.
pub response_li: ResponseLedgerInfo,
/// Chunk of transactions with proof corresponding to the ledger info
/// carried by the response.
pub txn_list_with_proof: TransactionListWithProof,
}
impl GetChunkResponse {
pub fn new(
response_li: ResponseLedgerInfo,
txn_list_with_proof: TransactionListWithProof,
) -> Self {
Self {
response_li,
txn_list_with_proof,
}
}
}
impl fmt::Debug for GetChunkResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl fmt::Display for GetChunkResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let txns_repr = match self.txn_list_with_proof.first_transaction_version
{
None => "empty".to_string(),
Some(first_version) => {
let last_version = first_version
.checked_add(self.txn_list_with_proof.len() as u64)
.and_then(|v| v.checked_sub(1)) // last_version = first_version + txns.len() - 1
.map(|v| v.to_string())
.unwrap_or_else(|| "Last version has overflown!".into());
format!("versions [{} - {}]", first_version, last_version)
}
};
let response_li_repr = match &self.response_li {
ResponseLedgerInfo::VerifiableLedgerInfo(li) => {
format!("[verifiable LI {}]", li.ledger_info())
}
ResponseLedgerInfo::ProgressiveLedgerInfo {
target_li,
highest_li,
} => format!(
"[progressive LI: target LI {}, highest LI {}]",
target_li.ledger_info(),
highest_li.as_ref().unwrap_or(target_li).ledger_info(),
),
ResponseLedgerInfo::LedgerInfoForWaypoint {
waypoint_li,
end_of_epoch_li,
} => format!(
"[waypoint LI {}, end of epoch LI {}]",
waypoint_li.ledger_info(),
end_of_epoch_li.as_ref().map_or("None".to_string(), |li| li
.ledger_info()
.to_string())
),
};
write!(
f,
"[ChunkResponse: response li: {}, txns: {}]",
response_li_repr, txns_repr,
)
}
}