CCF
Loading...
Searching...
No Matches
snapshot_serdes.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
8#include "ds/serialized.h"
9#include "kv/kv_types.h"
11#include "node/history.h"
13
14#include <nlohmann/json.hpp>
15
16namespace ccf
17{
19 {
20 std::vector<uint8_t> raw;
22
23 // Store used to verify a snapshot (either created fresh when a node joins
24 // from a snapshot or points to the main store when recovering from a
25 // snapshot)
26 std::shared_ptr<ccf::kv::Store> store = nullptr;
27
29 const std::shared_ptr<ccf::kv::Store>& store_,
30 std::vector<uint8_t>&& raw_,
31 ccf::kv::Version seqno_) :
32 raw(std::move(raw_)),
33 seqno(seqno_),
34 store(store_)
35 {}
36 };
37
38 static void deserialise_snapshot(
39 const std::shared_ptr<ccf::kv::Store>& store,
40 const std::vector<uint8_t>& snapshot,
42 std::vector<ccf::kv::Version>* view_history = nullptr,
43 bool public_only = false,
44 std::optional<std::vector<uint8_t>> prev_service_identity = std::nullopt)
45 {
46 const auto* data = snapshot.data();
47 auto size = snapshot.size();
48
49 auto tx_hdr = serialized::peek<ccf::kv::SerialisedEntryHeader>(data, size);
50 auto store_snapshot_size =
51 sizeof(ccf::kv::SerialisedEntryHeader) + tx_hdr.size;
52
53 if (tx_hdr.size == 0)
54 {
55 throw std::logic_error("Snapshot transaction size should not be zero");
56 }
57
58 const auto* receipt_data = data + store_snapshot_size;
59 auto receipt_size = size - store_snapshot_size;
60
61 if (receipt_size == 0)
62 {
63 throw std::logic_error("No receipt included in snapshot");
64 }
65
66 LOG_INFO_FMT("Deserialising snapshot receipt (size: {}).", receipt_size);
67 constexpr size_t max_printed_size = 1024;
68 if (receipt_size > max_printed_size)
69 {
71 "Receipt size ({}) exceeds max printed size ({}), only printing "
72 "first {} bytes",
73 receipt_size,
74 max_printed_size,
75 max_printed_size);
76 }
77 auto printed_size = std::min<size_t>(receipt_size, max_printed_size);
78 LOG_INFO_FMT("{}", ds::to_hex(receipt_data, receipt_data + printed_size));
79
80 auto j = nlohmann::json::parse(receipt_data, receipt_data + receipt_size);
81 auto receipt_p = j.get<ReceiptPtr>();
82 auto receipt = std::dynamic_pointer_cast<ccf::ProofReceipt>(receipt_p);
83 if (receipt == nullptr)
84 {
85 throw std::logic_error(
86 fmt::format("Unexpected receipt type: missing expanded claims"));
87 }
88
89 auto snapshot_digest =
90 ccf::crypto::Sha256Hash({snapshot.data(), store_snapshot_size});
91 auto snapshot_digest_claim = receipt->leaf_components.claims_digest.value();
92 if (snapshot_digest != snapshot_digest_claim)
93 {
94 throw std::logic_error(fmt::format(
95 "Snapshot digest ({}) does not match receipt claim ({})",
96 snapshot_digest,
97 snapshot_digest_claim));
98 }
99
100 auto root = receipt->calculate_root();
101 auto raw_sig = receipt->signature;
102
103 auto v = ccf::crypto::make_unique_verifier(receipt->cert);
104 if (!v->verify_hash(
105 root.h.data(),
106 root.h.size(),
107 receipt->signature.data(),
108 receipt->signature.size(),
110 {
111 throw std::logic_error(
112 "Signature verification failed for snapshot receipt");
113 }
114
115 if (prev_service_identity)
116 {
117 ccf::crypto::Pem prev_pem(*prev_service_identity);
118 if (!v->verify_certificate(
119 {&prev_pem},
120 {}, /* ignore_time */
121 true))
122 {
123 throw std::logic_error(
124 "Previous service identity does not endorse the node identity that "
125 "signed the snapshot");
126 }
127 LOG_DEBUG_FMT("Previous service identity endorses snapshot signer");
128 }
129
131 "Deserialising snapshot (size: {}, public only: {})",
132 snapshot.size(),
133 public_only);
134
135 auto rc = store->deserialise_snapshot(
136 snapshot.data(), store_snapshot_size, hooks, view_history, public_only);
138 {
139 throw std::logic_error(fmt::format("Failed to apply snapshot: {}", rc));
140 }
141
143 "Snapshot successfully deserialised at seqno {}",
144 store->current_version());
145 };
146
147 static std::unique_ptr<StartupSnapshotInfo> initialise_from_snapshot(
148 const std::shared_ptr<ccf::kv::Store>& store,
149 std::vector<uint8_t>&& snapshot,
151 std::vector<ccf::kv::Version>* view_history = nullptr,
152 bool public_only = false,
153 std::optional<std::vector<uint8_t>> previous_service_identity =
154 std::nullopt)
155 {
156 deserialise_snapshot(
157 store,
158 snapshot,
159 hooks,
160 view_history,
161 public_only,
162 previous_service_identity);
163 return std::make_unique<StartupSnapshotInfo>(
164 store, std::move(snapshot), store->current_version());
165 }
166
167 static std::vector<uint8_t> build_and_serialise_receipt(
168 const std::vector<uint8_t>& sig,
169 const std::vector<uint8_t>& tree,
170 const NodeId& node_id,
171 const ccf::crypto::Pem& node_cert,
173 const ccf::crypto::Sha256Hash& write_set_digest,
174 const std::string& commit_evidence,
175 ccf::crypto::Sha256Hash&& claims_digest)
176 {
177 ccf::MerkleTreeHistory history(tree);
178 auto proof = history.get_proof(seqno);
180 // NOLINTNEXTLINE(performance-move-const-arg)
181 cd.set(std::move(claims_digest));
182 ccf::TxReceiptImpl tx_receipt(
183 sig,
184 std::nullopt, // cose
185 proof.get_root(),
186 proof.get_path(),
187 node_id,
188 node_cert,
189 write_set_digest,
190 commit_evidence,
191 cd);
192
193 auto receipt = ccf::describe_receipt_v1(tx_receipt);
194 const auto receipt_str = receipt.dump();
195 return {receipt_str.begin(), receipt_str.end()};
196 }
197}
Definition claims_digest.h:10
void set(Digest &&digest_)
Definition claims_digest.h:21
Definition history.h:415
Definition pem.h:18
Definition sha256_hash.h:16
#define LOG_INFO_FMT
Definition internal_logger.h:15
#define LOG_DEBUG_FMT
Definition internal_logger.h:14
VerifierUniquePtr make_unique_verifier(const std::vector< uint8_t > &cert)
Definition verifier.cpp:13
uint64_t Version
Definition version.h:8
@ PASS
Definition kv_types.h:303
std::vector< ConsensusHookPtr > ConsensusHookPtrs
Definition hooks.h:22
Definition app_interface.h:14
EntityId< NodeIdFormatter > NodeId
Definition entity_id.h:164
nlohmann::json describe_receipt_v1(const TxReceiptImpl &receipt)
Definition historical_queries_adapter.cpp:68
std::shared_ptr< Receipt > ReceiptPtr
Definition receipt.h:128
seqno
Definition signatures.h:54
STL namespace.
Definition snapshot_serdes.h:19
std::shared_ptr< ccf::kv::Store > store
Definition snapshot_serdes.h:26
StartupSnapshotInfo(const std::shared_ptr< ccf::kv::Store > &store_, std::vector< uint8_t > &&raw_, ccf::kv::Version seqno_)
Definition snapshot_serdes.h:28
std::vector< uint8_t > raw
Definition snapshot_serdes.h:20
ccf::kv::Version seqno
Definition snapshot_serdes.h:21
Definition tx_receipt_impl.h:14
Definition serialised_entry_format.h:21