CCF
Loading...
Searching...
No Matches
signature_cache_subsystem.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
6
7#include <map>
8#include <mutex>
9
10namespace ccf
11{
13 {
14 private:
15 static constexpr size_t DEFAULT_MAX_CACHE_SIZE = 5;
16
17 struct PendingEntry
18 {
19 std::optional<PrimarySignature> sig = std::nullopt;
20 std::optional<std::vector<uint8_t>> cose_signature = std::nullopt;
21 std::optional<std::vector<uint8_t>> serialised_tree = std::nullopt;
22
23 [[nodiscard]] bool is_complete() const
24 {
25 return (sig.has_value() || cose_signature.has_value()) &&
26 serialised_tree.has_value();
27 }
28 };
29
30 std::map<ccf::SeqNo, PendingEntry> cache;
31 size_t max_cache_size = DEFAULT_MAX_CACHE_SIZE;
32 mutable std::mutex cache_mutex;
33
34 void evict_oldest()
35 {
36 if (cache.size() > max_cache_size)
37 {
38 auto excess = cache.size() - max_cache_size;
39 auto end = std::next(cache.begin(), static_cast<ptrdiff_t>(excess));
40 cache.erase(cache.begin(), end);
41 }
42 }
43
44 PendingEntry& get_or_create_entry(ccf::kv::Version version)
45 {
46 cache.try_emplace(version);
47 evict_oldest();
48
49 // If eviction removed the entry we just inserted (version was
50 // older than everything and cache was full), re-insert it. This
51 // is an edge case that shouldn't occur in practice, would mean extremely
52 // out-of-order/large-batch hooks
53 auto it = cache.find(version);
54 if (it == cache.end())
55 {
56 it = cache.try_emplace(version).first;
57 }
58 return it->second;
59 }
60
61 public:
63
64 void set_max_cache_size(size_t n) override
65 {
66 std::lock_guard<std::mutex> guard(cache_mutex);
67 max_cache_size = std::max<size_t>(1, n);
68 evict_oldest();
69 }
70
71 [[nodiscard]] std::optional<CachedSignature> get_signature_for(
72 ccf::SeqNo seqno) const override
73 {
74 std::lock_guard<std::mutex> guard(cache_mutex);
75
76 // Find the first entry with version > seqno (the covering signature).
77 auto it = cache.upper_bound(seqno);
78 if (it == cache.end())
79 {
80 return std::nullopt;
81 }
82
83 const auto& [version, entry] = *it;
84 if (
85 !(entry.sig.has_value() || entry.cose_signature.has_value()) ||
86 !entry.serialised_tree.has_value())
87 {
88 return std::nullopt;
89 }
90
91 return CachedSignature{
92 entry.sig,
93 entry.cose_signature,
94 entry.serialised_tree.value(),
95 version};
96 }
97
99 ccf::kv::Version version, const PrimarySignature& sig)
100 {
101 std::lock_guard<std::mutex> guard(cache_mutex);
102 auto& entry = get_or_create_entry(version);
103 entry.sig = sig;
104 }
105
107 ccf::kv::Version version, const std::vector<uint8_t>& cose_sig)
108 {
109 std::lock_guard<std::mutex> guard(cache_mutex);
110 auto& entry = get_or_create_entry(version);
111 entry.cose_signature = cose_sig;
112 }
113
115 ccf::kv::Version version, const std::vector<uint8_t>& tree)
116 {
117 std::lock_guard<std::mutex> guard(cache_mutex);
118 auto& entry = get_or_create_entry(version);
119 entry.serialised_tree = tree;
120 }
121
123 {
124 tables.set_global_hook(
125 Tables::SIGNATURES,
127 [this](ccf::kv::Version version, const Signatures::Write& w) {
128 if (w.has_value())
129 {
130 on_signature_committed(version, w.value());
131 }
132 }));
133
134 tables.set_global_hook(
135 Tables::COSE_SIGNATURES,
137 [this](ccf::kv::Version version, const CoseSignatures::Write& w) {
138 if (w.has_value())
139 {
140 on_cose_signature_committed(version, w.value());
141 }
142 }));
143
144 tables.set_global_hook(
145 Tables::SERIALISED_MERKLE_TREE,
147 [this](
149 if (w.has_value())
150 {
151 on_tree_committed(version, w.value());
152 }
153 }));
154 }
155 };
156}
Definition signature_cache_interface.h:23
Definition signature_cache_subsystem.h:13
void register_hooks(ccf::kv::Store &tables)
Definition signature_cache_subsystem.h:122
void on_tree_committed(ccf::kv::Version version, const std::vector< uint8_t > &tree)
Definition signature_cache_subsystem.h:114
std::optional< CachedSignature > get_signature_for(ccf::SeqNo seqno) const override
Definition signature_cache_subsystem.h:71
void on_signature_committed(ccf::kv::Version version, const PrimarySignature &sig)
Definition signature_cache_subsystem.h:98
void on_cose_signature_committed(ccf::kv::Version version, const std::vector< uint8_t > &cose_sig)
Definition signature_cache_subsystem.h:106
void set_max_cache_size(size_t n) override
Definition signature_cache_subsystem.h:64
Definition store.h:88
void set_global_hook(const std::string &map_name, const ccf::kv::untyped::Map::CommitHook &hook)
Definition store.h:1272
static ccf::kv::untyped::CommitHook wrap_commit_hook(const CommitHook &hook)
Definition value.h:65
std::optional< V > Write
Definition value.h:38
uint64_t Version
Definition version.h:10
Definition app_interface.h:13
uint64_t SeqNo
Definition tx_id.h:36
Definition signature_cache_interface.h:15
std::optional< PrimarySignature > sig
Definition signature_cache_interface.h:16
Definition signatures.h:14