10#include "crypto/cose.h"
19#include <nlohmann/json.hpp>
26 std::vector<uint8_t>
raw;
41 const std::vector<uint8_t>& snapshot)
43 const auto* data = snapshot.data();
44 auto size = snapshot.size();
46 auto tx_hdr = serialized::peek<ccf::kv::SerialisedEntryHeader>(data, size);
47 auto store_snapshot_size =
52 throw std::logic_error(
"Snapshot transaction size should not be zero");
55 if (store_snapshot_size > size)
57 throw std::invalid_argument(fmt::format(
58 "Snapshot transaction header claims size {} which exceeds available "
64 const auto* receipt_data = data + store_snapshot_size;
65 auto receipt_size = size - store_snapshot_size;
67 if (receipt_size == 0)
69 throw std::logic_error(
"No receipt included in snapshot");
72 std::span<const uint8_t> header_and_body{data, store_snapshot_size};
73 std::span<const uint8_t> receipt{receipt_data, receipt_size};
75 return SnapshotSegments{header_and_body, receipt};
78 static void verify_cose_snapshot_receipt(
79 const SnapshotSegments& segments,
80 const std::optional<std::vector<uint8_t>>& prev_service_identity)
82 auto receipt = ccf::cose::decode_ccf_receipt(
83 {segments.receipt.begin(), segments.receipt.end()},
87 segments.header_and_body.data(), segments.header_and_body.size());
91 snapshot_digest.h.data(),
92 receipt.claims_digest.data(),
95 throw std::logic_error(fmt::format(
96 "Snapshot digest ({}) does not match receipt claim ({})",
98 ds::to_hex(receipt.claims_digest)));
101 if (prev_service_identity)
105 if (!verifier->verify_detached(segments.receipt, receipt.merkle_root))
107 throw std::logic_error(
108 "Previous service identity does not match the service identity that "
109 "signed the snapshot");
111 LOG_DEBUG_FMT(
"Previous service identity matches snapshot signer");
115 static void verify_json_snapshot_receipt(
116 const SnapshotSegments& segments,
117 const std::optional<std::vector<uint8_t>>& prev_service_identity)
120 nlohmann::json::parse(segments.receipt.begin(), segments.receipt.end());
122 auto receipt = std::dynamic_pointer_cast<ccf::ProofReceipt>(receipt_p);
123 if (receipt ==
nullptr)
125 throw std::logic_error(
126 "Unexpected receipt type: missing expanded claims");
130 segments.header_and_body.data(), segments.header_and_body.size());
131 auto snapshot_digest_claim = receipt->leaf_components.claims_digest.value();
132 if (snapshot_digest != snapshot_digest_claim)
134 throw std::logic_error(fmt::format(
135 "Snapshot digest ({}) does not match receipt claim ({})",
137 snapshot_digest_claim));
140 auto root = receipt->calculate_root();
146 receipt->signature.data(),
147 receipt->signature.size(),
150 throw std::logic_error(
151 "Signature verification failed for snapshot receipt");
154 if (prev_service_identity)
157 if (!v->verify_certificate(
158 {&prev_pem}, {},
true
161 throw std::logic_error(
162 "Previous service identity does not endorse the node identity "
163 "that signed the snapshot");
165 LOG_DEBUG_FMT(
"Previous service identity endorses snapshot signer");
169 static void verify_snapshot(
170 const SnapshotSegments& segments,
171 std::optional<std::vector<uint8_t>> prev_service_identity = std::nullopt)
174 "Deserialising snapshot receipt (size: {}).", segments.receipt.size());
175 constexpr size_t max_printed_size = 1024;
176 if (segments.receipt.size() > max_printed_size)
179 "Receipt size ({}) exceeds max printed size ({}), only printing "
181 segments.receipt.size(),
186 std::min<size_t>(segments.receipt.size(), max_printed_size);
190 segments.receipt.data(), segments.receipt.data() + printed_size));
192 if (segments.receipt.empty())
194 throw std::logic_error(
"Empty snapshot receipt");
197 auto first_byte = segments.receipt[0];
198 constexpr uint8_t ENCODED_COSE_SIGN1_TAG = 0xD2;
199 if (first_byte == ENCODED_COSE_SIGN1_TAG)
202 verify_cose_snapshot_receipt(segments, prev_service_identity);
204 else if (first_byte ==
'{')
207 verify_json_snapshot_receipt(segments, prev_service_identity);
211 throw std::logic_error(fmt::format(
212 "Invalid snapshot receipt: unrecognised format (first byte: 0x{:02X})",
217 static void deserialise_snapshot(
218 const std::shared_ptr<ccf::kv::Store>& store,
219 const SnapshotSegments& segments,
221 std::vector<ccf::kv::Version>* view_history =
nullptr,
222 bool public_only =
false)
224 const auto* data = segments.header_and_body.data();
225 const auto size = segments.header_and_body.size();
230 "Deserialising snapshot (size: {}, public only: {})",
231 size + segments.receipt.size(),
235 store->deserialise_snapshot(data, size, hooks, view_history, public_only);
238 throw std::logic_error(fmt::format(
"Failed to apply snapshot: {}", rc));
242 "Snapshot successfully deserialised at seqno {}",
243 store->current_version());
246 static void deserialise_snapshot(
247 const std::shared_ptr<ccf::kv::Store>& store,
248 const std::vector<uint8_t>& snapshot,
250 std::vector<ccf::kv::Version>* view_history =
nullptr,
251 bool public_only =
false)
253 const auto segments = separate_segments(snapshot);
254 deserialise_snapshot(store, segments, hooks, view_history, public_only);
257 static std::vector<uint8_t> build_and_serialise_receipt(
258 const std::vector<uint8_t>& cose_sig,
259 const std::vector<uint8_t>& tree,
262 const std::string& commit_evidence,
266 auto proof = history.get_proof(seqno);
269 cd.
set(std::move(claims_digest));
283 if (!cose_signature.has_value())
285 throw std::logic_error(
286 "No COSE signature available for snapshot receipt");
289 if (!merkle_proof.has_value())
291 return *cose_signature;
296 ccf::cose::header::iana::VDP,
Definition claims_digest.h:10
void set(Digest &&digest_)
Definition claims_digest.h:21
Definition sha256_hash.h:16
static constexpr size_t SIZE
Definition sha256_hash.h:18
#define LOG_INFO_FMT
Definition internal_logger.h:15
#define LOG_DEBUG_FMT
Definition internal_logger.h:14
std::vector< uint8_t > set_unprotected_header(const std::span< const uint8_t > &cose_input, const desc::Type &descriptor)
Definition cose.cpp:14
VerifierUniquePtr make_unique_verifier(const std::vector< uint8_t > &cert)
Definition verifier.cpp:13
COSEVerifierUniquePtr make_cose_verifier_from_pem_cert(const Pem &pem)
Definition cose_verifier.cpp:280
uint64_t Version
Definition version.h:10
@ PASS
Definition kv_types.h:306
std::vector< ConsensusHookPtr > ConsensusHookPtrs
Definition hooks.h:22
Definition app_interface.h:13
std::optional< std::vector< uint8_t > > describe_merkle_proof_v1(const TxReceiptImpl &receipt)
Definition historical_queries_adapter.cpp:226
std::shared_ptr< Receipt > ReceiptPtr
Definition receipt.h:128
std::optional< SerialisedCoseSignature > describe_cose_signature_v1(const TxReceiptImpl &receipt)
Definition historical_queries_adapter.cpp:268
Definition snapshot_serdes.h:35
std::span< const uint8_t > header_and_body
Definition snapshot_serdes.h:36
std::span< const uint8_t > receipt
Definition snapshot_serdes.h:37
Definition snapshot_serdes.h:24
StartupSnapshotInfo(ccf::kv::Version s, std::vector< uint8_t > &&r)
Definition snapshot_serdes.h:28
std::vector< uint8_t > raw
Definition snapshot_serdes.h:26
ccf::kv::Version seqno
Definition snapshot_serdes.h:25
Definition tx_receipt_impl.h:14