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
5#include "ccf/ds/logger.h"
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 auto receipt_data = data + store_snapshot_size;
54 auto receipt_size = size - store_snapshot_size;
55
56 if (receipt_size == 0)
57 {
58 throw std::logic_error("No receipt included in snapshot");
59 }
60
61 auto j = nlohmann::json::parse(receipt_data, receipt_data + receipt_size);
62 auto receipt_p = j.get<ReceiptPtr>();
63 auto receipt = std::dynamic_pointer_cast<ccf::ProofReceipt>(receipt_p);
64 if (receipt == nullptr)
65 {
66 throw std::logic_error(
67 fmt::format("Unexpected receipt type: missing expanded claims"));
68 }
69
70 auto snapshot_digest =
71 ccf::crypto::Sha256Hash({snapshot.data(), store_snapshot_size});
72 auto snapshot_digest_claim = receipt->leaf_components.claims_digest.value();
73 if (snapshot_digest != snapshot_digest_claim)
74 {
75 throw std::logic_error(fmt::format(
76 "Snapshot digest ({}) does not match receipt claim ({})",
77 snapshot_digest,
78 snapshot_digest_claim));
79 }
80
81 auto root = receipt->calculate_root();
82 auto raw_sig = receipt->signature;
83
84 auto v = ccf::crypto::make_unique_verifier(receipt->cert);
85 if (!v->verify_hash(
86 root.h.data(),
87 root.h.size(),
88 receipt->signature.data(),
89 receipt->signature.size(),
91 {
92 throw std::logic_error(
93 "Signature verification failed for snapshot receipt");
94 }
95
96 if (prev_service_identity)
97 {
98 ccf::crypto::Pem prev_pem(*prev_service_identity);
99 if (!v->verify_certificate(
100 {&prev_pem},
101 {}, /* ignore_time */
102 true))
103 {
104 throw std::logic_error(
105 "Previous service identity does not endorse the node identity that "
106 "signed the snapshot");
107 }
108 LOG_DEBUG_FMT("Previous service identity endorses snapshot signer");
109 }
110
112 "Deserialising snapshot (size: {}, public only: {})",
113 snapshot.size(),
114 public_only);
115
116 auto rc = store->deserialise_snapshot(
117 snapshot.data(), store_snapshot_size, hooks, view_history, public_only);
119 {
120 throw std::logic_error(fmt::format("Failed to apply snapshot: {}", rc));
121 }
122
124 "Snapshot successfully deserialised at seqno {}",
125 store->current_version());
126 };
127
128 static std::unique_ptr<StartupSnapshotInfo> initialise_from_snapshot(
129 const std::shared_ptr<ccf::kv::Store>& store,
130 std::vector<uint8_t>&& snapshot,
132 std::vector<ccf::kv::Version>* view_history = nullptr,
133 bool public_only = false,
134 std::optional<std::vector<uint8_t>> previous_service_identity =
135 std::nullopt)
136 {
137 deserialise_snapshot(
138 store,
139 snapshot,
140 hooks,
141 view_history,
142 public_only,
143 previous_service_identity);
144 return std::make_unique<StartupSnapshotInfo>(
145 store, std::move(snapshot), store->current_version());
146 }
147
148 static std::vector<uint8_t> build_and_serialise_receipt(
149 const std::vector<uint8_t>& sig,
150 const std::vector<uint8_t>& tree,
151 const NodeId& node_id,
152 const ccf::crypto::Pem& node_cert,
154 const ccf::crypto::Sha256Hash& write_set_digest,
155 const std::string& commit_evidence,
156 ccf::crypto::Sha256Hash&& claims_digest)
157 {
158 ccf::MerkleTreeHistory history(tree);
159 auto proof = history.get_proof(seqno);
161 cd.set(std::move(claims_digest));
162 ccf::TxReceiptImpl tx_receipt(
163 sig,
164 std::nullopt, // cose
165 proof.get_root(),
166 proof.get_path(),
167 node_id,
168 node_cert,
169 write_set_digest,
170 commit_evidence,
171 cd);
172
173 auto receipt = ccf::describe_receipt_v1(tx_receipt);
174 const auto receipt_str = receipt.dump();
175 return std::vector<uint8_t>(receipt_str.begin(), receipt_str.end());
176 }
177}
Definition claims_digest.h:10
void set(Digest &&digest_)
Definition claims_digest.h:21
Definition history.h:436
Definition pem.h:18
Definition sha256_hash.h:16
#define LOG_INFO_FMT
Definition logger.h:362
#define LOG_DEBUG_FMT
Definition logger.h:357
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:342
std::vector< ConsensusHookPtr > ConsensusHookPtrs
Definition hooks.h:22
Definition app_interface.h:14
EntityId< NodeIdFormatter > NodeId
Definition entity_id.h:155
nlohmann::json describe_receipt_v1(const TxReceiptImpl &receipt)
Definition historical_queries_adapter.cpp:68
std::shared_ptr< Receipt > ReceiptPtr
Definition receipt.h:131
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:13
Definition serialised_entry_format.h:21