CCF
Loading...
Searching...
No Matches
history.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#include "ccf/ds/logger.h"
7#include "ccf/pal/locking.h"
11#include "crypto/openssl/hash.h"
13#include "ds/thread_messaging.h"
14#include "endian.h"
15#include "kv/kv_types.h"
16#include "kv/store.h"
19
20#include <array>
21#include <deque>
22#include <string.h>
23
24#define HAVE_OPENSSL
25// merklecpp traces are off by default, even when CCF tracing is enabled
26// #include "merklecpp_trace.h"
27#include <merklecpp/merklecpp.h>
28
29FMT_BEGIN_NAMESPACE
30template <>
31struct formatter<ccf::kv::TxHistory::RequestID>
32{
33 template <typename ParseContext>
34 constexpr auto parse(ParseContext& ctx)
35 {
36 return ctx.begin();
37 }
38
39 template <typename FormatContext>
40 auto format(const ccf::kv::TxHistory::RequestID& p, FormatContext& ctx) const
41 {
42 return format_to(
43 ctx.out(), "<RID {0}, {1}>", std::get<0>(p), std::get<1>(p));
44 }
45};
46FMT_END_NAMESPACE
47
48namespace ccf
49{
57
58#ifdef OVERRIDE_MAX_HISTORY_LEN
59 constexpr int MAX_HISTORY_LEN = OVERRIDE_MAX_HISTORY_LEN;
60#else
61 constexpr int MAX_HISTORY_LEN = 0;
62#endif
63
64 static std::ostream& operator<<(std::ostream& os, HashOp flag)
65 {
66 switch (flag)
67 {
68 case APPEND:
69 os << "append";
70 break;
71
72 case VERIFY:
73 os << "verify";
74 break;
75
76 case ROLLBACK:
77 os << "rollback";
78 break;
79
80 case COMPACT:
81 os << "compact";
82 break;
83 }
84
85 return os;
86 }
87
88 static inline void log_hash(const ccf::crypto::Sha256Hash& h, HashOp flag)
89 {
90 LOG_TRACE_FMT("History [{}] {}", flag, h);
91 }
92
94 {
95 ccf::kv::TxID txid;
96 ccf::kv::Store& store;
97 NodeId id;
98
99 public:
101 ccf::kv::TxID txid_, ccf::kv::Store& store_, const NodeId& id_) :
102 txid(txid_),
103 store(store_),
104 id(id_)
105 {}
106
108 {
109 auto sig = store.create_reserved_tx(txid);
110 auto signatures =
111 sig.template wo<ccf::Signatures>(ccf::Tables::SIGNATURES);
112 auto cose_signatures =
113 sig.template wo<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
114
115 auto serialised_tree = sig.template wo<ccf::SerialisedMerkleTree>(
116 ccf::Tables::SERIALISED_MERKLE_TREE);
117 PrimarySignature sig_value(id, txid.version);
118 signatures->put(sig_value);
119 cose_signatures->put(ccf::CoseSignature{});
120 serialised_tree->put({});
121 return sig.commit_reserved();
122 }
123 };
124
126 {
127 ccf::kv::Store& store;
128 NodeId id;
129
130 protected:
134
135 public:
137 ccf::kv::Store& store_, const NodeId& id_, ccf::crypto::KeyPair&) :
138 store(store_),
139 id(id_)
140 {}
141
142 void append(const std::vector<uint8_t>&) override
143 {
144 version++;
145 }
146
148 const ccf::crypto::Sha256Hash& digest,
149 std::optional<ccf::kv::Term> term_of_next_version_ =
150 std::nullopt) override
151 {
152 version++;
153 }
154
156 {
157 return true;
158 }
159
160 void set_term(ccf::kv::Term t) override
161 {
164 }
165
167 const ccf::kv::TxID& tx_id, ccf::kv::Term commit_term_) override
168 {
169 version = tx_id.version;
171 term_of_next_version = commit_term_;
172 }
173
174 void compact(ccf::kv::Version) override {}
175
176 bool init_from_snapshot(const std::vector<uint8_t>&) override
177 {
178 return true;
179 }
180
181 std::vector<uint8_t> get_raw_leaf(uint64_t) override
182 {
183 return {};
184 }
185
186 void emit_signature() override
187 {
188 auto txid = store.next_txid();
189 LOG_DEBUG_FMT("Issuing signature at {}.{}", txid.term, txid.version);
190 store.commit(
191 txid, std::make_unique<NullTxHistoryPendingTx>(txid, store, id), true);
192 }
193
194 void try_emit_signature() override {}
195
196 void start_signature_emit_timer() override {}
197
199 std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp_,
200 const ccf::COSESignaturesConfig& cose_signatures) override
201 {
202 std::ignore = std::move(service_kp_);
203 }
204
206 {
207 throw std::logic_error("Unimplemented");
208 }
209
211 {
212 return ccf::crypto::Sha256Hash(std::to_string(version));
213 }
214
215 std::tuple<ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
217 {
218 return {
220 ccf::crypto::Sha256Hash(std::to_string(version)),
222 }
223
224 std::vector<uint8_t> get_proof(ccf::kv::Version) override
225 {
226 return {};
227 }
228
229 bool verify_proof(const std::vector<uint8_t>&) override
230 {
231 return true;
232 }
233
234 std::vector<uint8_t> serialise_tree(size_t) override
235 {
236 return {};
237 }
238
239 void set_endorsed_certificate(const ccf::crypto::Pem& cert) override {}
240 };
241
242 // Use optimised CCF openssl_sha256 function to avoid performance regression
243 // on OpenSSL 3.x
244 static constexpr size_t sha256_byte_size = 32;
245 static inline void sha256_history(
246 const merkle::HashT<sha256_byte_size>& l,
247 const merkle::HashT<sha256_byte_size>& r,
248 merkle::HashT<sha256_byte_size>& out)
249
250 {
251 uint8_t block[sha256_byte_size * 2];
252 memcpy(&block[0], l.bytes, sha256_byte_size);
253 memcpy(&block[sha256_byte_size], r.bytes, sha256_byte_size);
254
255 ccf::crypto::openssl_sha256(block, out.bytes);
256 }
257
258 using HistoryTree = merkle::TreeT<sha256_byte_size, ccf::sha256_history>;
259
260 class Proof
261 {
262 private:
263 HistoryTree::Hash root;
264 std::shared_ptr<HistoryTree::Path> path = nullptr;
265
266 public:
267 Proof() {}
268
269 Proof(const std::vector<uint8_t>& v)
270 {
271 size_t position = 0;
272 root.deserialise(v, position);
273 path = std::make_shared<HistoryTree::Path>(v, position);
274 }
275
276 const HistoryTree::Hash& get_root() const
277 {
278 return root;
279 }
280
281 std::shared_ptr<HistoryTree::Path> get_path()
282 {
283 return path;
284 }
285
286 Proof(HistoryTree* tree, uint64_t index)
287 {
288 root = tree->root();
289 path = tree->path(index);
290 }
291
292 Proof(const Proof&) = delete;
293
294 bool verify(HistoryTree* tree) const
295 {
296 if (path->max_index() > tree->max_index())
297 {
298 return false;
299 }
300 else if (tree->max_index() == path->max_index())
301 {
302 return tree->root() == root && path->verify(root);
303 }
304 else
305 {
306 auto past_root = tree->past_root(path->max_index());
307 return path->verify(*past_root);
308 }
309 }
310
311 std::vector<uint8_t> to_v() const
312 {
313 std::vector<uint8_t> v;
314 root.serialise(v);
315 path->serialise(v);
316 return v;
317 }
318 };
319
320 template <class T>
322 {
323 ccf::kv::TxID txid;
324 ccf::kv::Store& store;
325 ccf::kv::TxHistory& history;
326 NodeId id;
327 ccf::crypto::KeyPair& node_kp;
329 ccf::crypto::Pem& endorsed_cert;
330 const ccf::COSESignaturesConfig& cose_signatures_config;
331
332 public:
334 ccf::kv::TxID txid_,
335 ccf::kv::Store& store_,
336 ccf::kv::TxHistory& history_,
337 const NodeId& id_,
338 ccf::crypto::KeyPair& node_kp_,
339 ccf::crypto::KeyPair_OpenSSL& service_kp_,
340 ccf::crypto::Pem& endorsed_cert_,
341 const ccf::COSESignaturesConfig& cose_signatures_config_) :
342 txid(txid_),
343 store(store_),
344 history(history_),
345 id(id_),
346 node_kp(node_kp_),
347 service_kp(service_kp_),
348 endorsed_cert(endorsed_cert_),
349 cose_signatures_config(cose_signatures_config_)
350 {}
351
353 {
354 auto sig = store.create_reserved_tx(txid);
355 auto signatures =
356 sig.template wo<ccf::Signatures>(ccf::Tables::SIGNATURES);
357 auto cose_signatures =
358 sig.template wo<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
359 auto serialised_tree = sig.template wo<ccf::SerialisedMerkleTree>(
360 ccf::Tables::SERIALISED_MERKLE_TREE);
362
363 std::vector<uint8_t> primary_sig;
364
365 std::vector<uint8_t> root_hash{
366 root.h.data(), root.h.data() + root.h.size()};
367 primary_sig = node_kp.sign_hash(root_hash.data(), root_hash.size());
368
369 PrimarySignature sig_value(
370 id,
371 txid.version,
372 txid.term,
373 root,
374 {}, // Nonce is currently empty
375 primary_sig,
376 endorsed_cert);
377
378 constexpr int64_t vds_merkle_tree = 2;
379
380 const auto& service_key_der = service_kp.public_key_der();
381 auto kid = ccf::crypto::Sha256Hash(service_key_der).hex_str();
382 std::span<const uint8_t> kid_span{(uint8_t*)kid.data(), kid.size()};
383
384 const auto time_since_epoch =
385 std::chrono::duration_cast<std::chrono::seconds>(
386 std::chrono::system_clock::now().time_since_epoch())
387 .count();
388
389 auto ccf_headers =
390 std::static_pointer_cast<ccf::crypto::COSEParametersFactory>(
391 std::make_shared<ccf::crypto::COSEParametersMap>(
392 std::make_shared<ccf::crypto::COSEMapStringKey>(
393 ccf::crypto::COSE_PHEADER_KEY_CCF),
396 ccf::crypto::COSE_PHEADER_KEY_TXID, txid.str())}));
397
398 auto cwt_headers =
399 std::static_pointer_cast<ccf::crypto::COSEParametersFactory>(
400 std::make_shared<ccf::crypto::COSEParametersMap>(
401 std::make_shared<ccf::crypto::COSEMapIntKey>(
402 ccf::crypto::COSE_PHEADER_KEY_CWT),
405 ccf::crypto::COSE_PHEADER_KEY_IAT, time_since_epoch),
407 ccf::crypto::COSE_PHEADER_KEY_ISS,
408 cose_signatures_config.issuer),
410 ccf::crypto::COSE_PHEADER_KEY_SUB,
411 cose_signatures_config.subject),
412 }));
413
414 const auto pheaders = {
415 // Key digest
417 ccf::crypto::COSE_PHEADER_KEY_ID, kid_span),
418 // VDS
420 ccf::crypto::COSE_PHEADER_KEY_VDS, vds_merkle_tree),
421 // CWT claims
422 cwt_headers,
423 // CCF headers
424 ccf_headers};
425
426 auto cose_sign = crypto::cose_sign1(service_kp, pheaders, root_hash);
427
428 signatures->put(sig_value);
429 cose_signatures->put(cose_sign);
430 serialised_tree->put(history.serialise_tree(txid.version - 1));
431 return sig.commit_reserved();
432 }
433 };
434
436 {
437 HistoryTree* tree;
438
439 public:
441
442 MerkleTreeHistory(const std::vector<uint8_t>& serialised)
443 {
444 tree = new HistoryTree(serialised);
445 }
446
448 {
449 tree = new HistoryTree(merkle::Hash(first_hash.h));
450 }
451
453 {
454 delete (tree);
455 tree = nullptr;
456 }
457
458 void deserialise(const std::vector<uint8_t>& serialised)
459 {
460 delete (tree);
461 tree = new HistoryTree(serialised);
462 }
463
465 {
466 tree->insert(merkle::Hash(hash.h));
467 }
468
470 {
471 const merkle::Hash& root = tree->root();
473 std::copy(root.bytes, root.bytes + root.size(), result.h.begin());
474 return result;
475 }
476
478 {
479 delete (tree);
481 tree = new HistoryTree(merkle::Hash(root.h));
482 }
483
484 void flush(uint64_t index)
485 {
486 LOG_TRACE_FMT("mt_flush_to index={}", index);
487 tree->flush_to(index);
488 }
489
490 void retract(uint64_t index)
491 {
492 LOG_TRACE_FMT("mt_retract_to index={}", index);
493 tree->retract_to(index);
494 }
495
496 Proof get_proof(uint64_t index)
497 {
498 if (index < begin_index())
499 {
500 throw std::logic_error(fmt::format(
501 "Cannot produce proof for {}: index is older than first index {}, "
502 "and has been flushed from memory",
503 index,
504 begin_index()));
505 }
506 if (index > end_index())
507 {
508 throw std::logic_error(fmt::format(
509 "Cannot produce proof for {}: index is later than last index {}",
510 index,
511 end_index()));
512 }
513 return Proof(tree, index);
514 }
515
516 bool verify(const Proof& r)
517 {
518 return r.verify(tree);
519 }
520
521 std::vector<uint8_t> serialise()
522 {
523 LOG_TRACE_FMT("mt_serialize_size {}", tree->serialised_size());
524 std::vector<uint8_t> output;
525 tree->serialise(output);
526 return output;
527 }
528
529 std::vector<uint8_t> serialise(size_t from, size_t to)
530 {
532 "mt_serialize_size ({},{}) {}",
533 from,
534 to,
535 tree->serialised_size(from, to));
536 std::vector<uint8_t> output;
537 tree->serialise(from, to, output);
538 return output;
539 }
540
541 uint64_t begin_index()
542 {
543 return tree->min_index();
544 }
545
546 uint64_t end_index()
547 {
548 return tree->max_index();
549 }
550
551 bool in_range(uint64_t index)
552 {
553 return index >= begin_index() && index <= end_index();
554 }
555
557 {
558 const merkle::Hash& leaf = tree->leaf(index);
560 std::copy(leaf.bytes, leaf.bytes + leaf.size(), result.h.begin());
561 return result;
562 }
563 };
564
565 template <class T>
567 {
568 ccf::kv::Store& store;
569 NodeId id;
570 T replicated_state_tree;
571
572 ccf::crypto::KeyPair& node_kp;
574 std::vector<uint8_t> cose_cert_cached{};
575
576 std::optional<::threading::TaskQueue::TimerEntry>
577 emit_signature_timer_entry = std::nullopt;
578 size_t sig_tx_interval;
579 size_t sig_ms_interval;
580
581 ccf::pal::Mutex state_lock;
582 ccf::kv::Term term_of_last_version = 0;
583 ccf::kv::Term term_of_next_version;
584
585 std::optional<ccf::crypto::Pem> endorsed_cert = std::nullopt;
586
587 struct ServiceSigningIdentity
588 {
589 const std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp;
590 const ccf::COSESignaturesConfig cose_signatures_config;
591 };
592
593 std::optional<ServiceSigningIdentity> signing_identity = std::nullopt;
594
595 public:
597 ccf::kv::Store& store_,
598 const NodeId& id_,
599 ccf::crypto::KeyPair& node_kp_,
600 size_t sig_tx_interval_ = 0,
601 size_t sig_ms_interval_ = 0,
602 bool signature_timer = false) :
603 store(store_),
604 id(id_),
605 node_kp(node_kp_),
606 sig_tx_interval(sig_tx_interval_),
607 sig_ms_interval(sig_ms_interval_)
608 {
609 if (signature_timer)
610 {
612 }
613 }
614
616 std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp_,
617 const ccf::COSESignaturesConfig& cose_signatures_config_) override
618 {
619 if (signing_identity.has_value())
620 {
621 throw std::logic_error(
622 "Called set_service_signing_identity() multiple times");
623 }
624
625 signing_identity.emplace(
626 ServiceSigningIdentity{service_kp_, cose_signatures_config_});
627
629 "Setting service signing identity to iss: {} sub: {}",
630 cose_signatures_config_.issuer,
631 cose_signatures_config_.subject);
632 }
633
635 {
636 if (!signing_identity.has_value())
637 {
638 throw std::logic_error(
639 "Called get_cose_signatures_config() before "
640 "set_service_signing_identity()");
641 }
642
643 return signing_identity->cose_signatures_config;
644 }
645
647 {
648 struct EmitSigMsg
649 {
650 EmitSigMsg(HashedTxHistory<T>* self_) : self(self_) {}
651 HashedTxHistory<T>* self;
652 };
653
654 auto emit_sig_msg = std::make_unique<::threading::Tmsg<EmitSigMsg>>(
655 [](std::unique_ptr<::threading::Tmsg<EmitSigMsg>> msg) {
656 auto self = msg->data.self;
657
658 std::unique_lock<ccf::pal::Mutex> mguard(
659 self->signature_lock, std::defer_lock);
660
661 bool should_emit_signature = false;
662
663 if (mguard.try_lock())
664 {
665 auto consensus = self->store.get_consensus();
666 if (consensus != nullptr)
667 {
668 auto sig_disp = consensus->get_signature_disposition();
669 switch (sig_disp)
670 {
672 {
673 break;
674 }
676 {
677 if (self->store.committable_gap() > 0)
678 {
679 should_emit_signature = true;
680 }
681 break;
682 }
684 {
685 should_emit_signature = true;
686 break;
687 }
688 }
689 }
690 }
691
692 if (should_emit_signature)
693 {
694 msg->data.self->emit_signature();
695 }
696
697 self->emit_signature_timer_entry =
699 std::move(msg), std::chrono::milliseconds(self->sig_ms_interval));
700 },
701 this);
702
703 emit_signature_timer_entry =
705 std::move(emit_sig_msg), std::chrono::milliseconds(sig_ms_interval));
706 }
707
709 {
710 if (emit_signature_timer_entry.has_value())
711 {
713 *emit_signature_timer_entry);
714 }
715 }
716
717 void set_node_id(const NodeId& id_)
718 {
719 id = id_;
720 }
721
723 const std::vector<uint8_t>& hash_at_snapshot) override
724 {
725 // The history can be initialised after a snapshot has been applied by
726 // deserialising the tree in the signatures table and then applying the
727 // hash of the transaction at which the snapshot was taken
728 auto tx = store.create_read_only_tx();
729 auto tree_h = tx.template ro<ccf::SerialisedMerkleTree>(
730 ccf::Tables::SERIALISED_MERKLE_TREE);
731 auto tree = tree_h->get();
732 if (!tree.has_value())
733 {
734 LOG_FAIL_FMT("No tree found in serialised tree map");
735 return false;
736 }
737
738 // Delay taking this lock until _after_ the read above, to avoid lock
739 // inversions
740 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
741
743 !replicated_state_tree.in_range(1),
744 "Tree is not empty before initialising from snapshot");
745
746 replicated_state_tree.deserialise(tree.value());
747
749 std::copy_n(
750 hash_at_snapshot.begin(),
752 hash.h.begin());
753 replicated_state_tree.append(hash);
754 return true;
755 }
756
758 {
759 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
760 return replicated_state_tree.get_root();
761 }
762
763 std::tuple<ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
765 {
766 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
767 return {
768 {term_of_last_version,
769 static_cast<ccf::kv::Version>(replicated_state_tree.end_index())},
770 replicated_state_tree.get_root(),
771 term_of_next_version};
772 }
773
775 {
776 auto tx = store.create_read_only_tx();
777
778 auto signatures =
779 tx.template ro<ccf::Signatures>(ccf::Tables::SIGNATURES);
780 auto sig = signatures->get();
781 if (!sig.has_value())
782 {
783 LOG_FAIL_FMT("No signature found in signatures map");
784 return false;
785 }
786
787 auto root = get_replicated_state_root();
788 log_hash(root, VERIFY);
789 if (!verify_node_signature(tx, sig->node, sig->sig, root))
790 {
791 return false;
792 }
793
794 auto cose_signatures =
795 tx.template ro<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
796 auto cose_sig = cose_signatures->get();
797
798 if (!cose_sig.has_value())
799 {
800 return true;
801 }
802
803 // Since COSE signatures have not always been emitted, it is possible in a
804 // mixed-service to see an _old_ COSE signature (by reading from the KV)
805 // that does not refer to the _current root_. When this occurs
806 // version_of_previous_write will not match the version at which we're
807 // verifying.
808 const auto cose_sig_version =
809 cose_signatures->get_version_of_previous_write();
810 if (cose_sig_version.has_value() && cose_sig_version.value() != version)
811 {
813 "Non-monotonic presence of COSE signatures - had one at {} but none "
814 "at {}",
815 cose_sig_version.value(),
816 version);
817 return true;
818 }
819
820 auto service = tx.template ro<ccf::Service>(Tables::SERVICE);
821 auto service_info = service->get();
822
823 if (!service_info.has_value())
824 {
825 LOG_FAIL_FMT("No service key found to verify the signature");
826 return false;
827 }
828
829 const auto raw_cert = service_info->cert.raw();
830 std::vector<uint8_t> root_hash{
831 root.h.data(), root.h.data() + root.h.size()};
832
833 return cose_verifier_cached(raw_cert)->verify_detached(
834 cose_sig.value(), root_hash);
835 }
836
837 std::vector<uint8_t> serialise_tree(size_t to) override
838 {
839 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
840 if (to <= replicated_state_tree.end_index())
841 {
842 return replicated_state_tree.serialise(
843 replicated_state_tree.begin_index(), to);
844 }
845 else
846 {
847 return {};
848 }
849 }
850
851 void set_term(ccf::kv::Term t) override
852 {
853 // This should only be called once, when the store first knows about its
854 // term
855 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
856 term_of_last_version = t;
857 term_of_next_version = t;
858 }
859
861 const ccf::kv::TxID& tx_id, ccf::kv::Term term_of_next_version_) override
862 {
863 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
864 LOG_TRACE_FMT("Rollback to {}.{}", tx_id.term, tx_id.version);
865 term_of_last_version = tx_id.term;
866 term_of_next_version = term_of_next_version_;
867 replicated_state_tree.retract(tx_id.version);
868 log_hash(replicated_state_tree.get_root(), ROLLBACK);
869 }
870
871 void compact(ccf::kv::Version v) override
872 {
873 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
874 // Receipts can only be retrieved to the flushed index. Keep a range of
875 // history so that a range of receipts are available.
876 if (v > MAX_HISTORY_LEN)
877 {
878 replicated_state_tree.flush(v - MAX_HISTORY_LEN);
879 }
880 log_hash(replicated_state_tree.get_root(), COMPACT);
881 }
882
884
885 void try_emit_signature() override
886 {
887 std::unique_lock<ccf::pal::Mutex> mguard(signature_lock, std::defer_lock);
888 if (store.committable_gap() < sig_tx_interval || !mguard.try_lock())
889 {
890 return;
891 }
892
893 if (store.committable_gap() >= sig_tx_interval)
894 {
895 mguard.unlock();
897 }
898 }
899
900 void emit_signature() override
901 {
902 // Signatures are only emitted when there is a consensus
903 auto consensus = store.get_consensus();
904 if (!consensus)
905 {
906 return;
907 }
908
909 if (!endorsed_cert.has_value())
910 {
911 throw std::logic_error(
912 fmt::format("No endorsed certificate set to emit signature"));
913 }
914
915 auto txid = store.next_txid();
916
917 LOG_DEBUG_FMT("Signed at {} in view: {}", txid.version, txid.term);
918
919 if (!signing_identity.has_value())
920 {
921 throw std::logic_error(
922 fmt::format("No service key has been set yet to sign"));
923 }
924
925 store.commit(
926 txid,
927 std::make_unique<MerkleTreeHistoryPendingTx<T>>(
928 txid,
929 store,
930 *this,
931 id,
932 node_kp,
933 *signing_identity->service_kp,
934 endorsed_cert.value(),
935 signing_identity->cose_signatures_config),
936 true);
937 }
938
939 std::vector<uint8_t> get_proof(ccf::kv::Version index) override
940 {
941 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
942 return replicated_state_tree.get_proof(index).to_v();
943 }
944
945 bool verify_proof(const std::vector<uint8_t>& v) override
946 {
947 Proof proof(v);
948 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
949 return replicated_state_tree.verify(proof);
950 }
951
952 std::vector<uint8_t> get_raw_leaf(uint64_t index) override
953 {
954 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
955 auto leaf = replicated_state_tree.get_leaf(index);
956 return {leaf.h.begin(), leaf.h.end()};
957 }
958
959 void append(const std::vector<uint8_t>& data) override
960 {
962 log_hash(rh, APPEND);
963 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
964 replicated_state_tree.append(rh);
965 }
966
968 const ccf::crypto::Sha256Hash& digest,
969 std::optional<ccf::kv::Term> expected_term_of_next_version =
970 std::nullopt) override
971 {
972 log_hash(digest, APPEND);
973 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
974 if (expected_term_of_next_version.has_value())
975 {
976 if (expected_term_of_next_version.value() != term_of_next_version)
977 {
978 return;
979 }
980 }
981 replicated_state_tree.append(digest);
982 }
983
985 {
986 endorsed_cert = cert;
987 }
988
989 private:
990 ccf::crypto::COSEVerifierUniquePtr& cose_verifier_cached(
991 const std::vector<uint8_t>& cert)
992 {
993 if (cert != cose_cert_cached)
994 {
995 cose_cert_cached = cert;
996 cose_verifier =
998 }
999 return cose_verifier;
1000 }
1001 };
1002
1004}
#define CCF_ASSERT_FMT(expr,...)
Definition ccf_assert.h:10
Definition history.h:567
void set_term(ccf::kv::Term t) override
Definition history.h:851
bool verify_proof(const std::vector< uint8_t > &v) override
Definition history.h:945
void set_endorsed_certificate(const ccf::crypto::Pem &cert) override
Definition history.h:984
void set_service_signing_identity(std::shared_ptr< ccf::crypto::KeyPair_OpenSSL > service_kp_, const ccf::COSESignaturesConfig &cose_signatures_config_) override
Definition history.h:615
void compact(ccf::kv::Version v) override
Definition history.h:871
std::vector< uint8_t > get_proof(ccf::kv::Version index) override
Definition history.h:939
ccf::pal::Mutex signature_lock
Definition history.h:883
const ccf::COSESignaturesConfig & get_cose_signatures_config() override
Definition history.h:634
std::vector< uint8_t > serialise_tree(size_t to) override
Definition history.h:837
bool verify_root_signatures(ccf::kv::Version version) override
Definition history.h:774
void append(const std::vector< uint8_t > &data) override
Definition history.h:959
~HashedTxHistory()
Definition history.h:708
std::tuple< ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term > get_replicated_state_txid_and_root() override
Definition history.h:764
void start_signature_emit_timer() override
Definition history.h:646
void set_node_id(const NodeId &id_)
Definition history.h:717
void try_emit_signature() override
Definition history.h:885
void emit_signature() override
Definition history.h:900
ccf::crypto::Sha256Hash get_replicated_state_root() override
Definition history.h:757
std::vector< uint8_t > get_raw_leaf(uint64_t index) override
Definition history.h:952
void append_entry(const ccf::crypto::Sha256Hash &digest, std::optional< ccf::kv::Term > expected_term_of_next_version=std::nullopt) override
Definition history.h:967
void rollback(const ccf::kv::TxID &tx_id, ccf::kv::Term term_of_next_version_) override
Definition history.h:860
bool init_from_snapshot(const std::vector< uint8_t > &hash_at_snapshot) override
Definition history.h:722
HashedTxHistory(ccf::kv::Store &store_, const NodeId &id_, ccf::crypto::KeyPair &node_kp_, size_t sig_tx_interval_=0, size_t sig_ms_interval_=0, bool signature_timer=false)
Definition history.h:596
Definition history.h:322
ccf::kv::PendingTxInfo call() override
Definition history.h:352
MerkleTreeHistoryPendingTx(ccf::kv::TxID txid_, ccf::kv::Store &store_, ccf::kv::TxHistory &history_, const NodeId &id_, ccf::crypto::KeyPair &node_kp_, ccf::crypto::KeyPair_OpenSSL &service_kp_, ccf::crypto::Pem &endorsed_cert_, const ccf::COSESignaturesConfig &cose_signatures_config_)
Definition history.h:333
Definition history.h:436
void deserialise(const std::vector< uint8_t > &serialised)
Definition history.h:458
void flush(uint64_t index)
Definition history.h:484
ccf::crypto::Sha256Hash get_root() const
Definition history.h:469
std::vector< uint8_t > serialise(size_t from, size_t to)
Definition history.h:529
ccf::crypto::Sha256Hash get_leaf(uint64_t index)
Definition history.h:556
MerkleTreeHistory(const std::vector< uint8_t > &serialised)
Definition history.h:442
MerkleTreeHistory(ccf::crypto::Sha256Hash first_hash={})
Definition history.h:447
bool verify(const Proof &r)
Definition history.h:516
MerkleTreeHistory(MerkleTreeHistory const &)=delete
Proof get_proof(uint64_t index)
Definition history.h:496
std::vector< uint8_t > serialise()
Definition history.h:521
uint64_t end_index()
Definition history.h:546
void operator=(const MerkleTreeHistory &rhs)
Definition history.h:477
void append(const ccf::crypto::Sha256Hash &hash)
Definition history.h:464
uint64_t begin_index()
Definition history.h:541
void retract(uint64_t index)
Definition history.h:490
~MerkleTreeHistory()
Definition history.h:452
bool in_range(uint64_t index)
Definition history.h:551
Definition history.h:94
ccf::kv::PendingTxInfo call() override
Definition history.h:107
NullTxHistoryPendingTx(ccf::kv::TxID txid_, ccf::kv::Store &store_, const NodeId &id_)
Definition history.h:100
Definition history.h:126
void set_endorsed_certificate(const ccf::crypto::Pem &cert) override
Definition history.h:239
void set_service_signing_identity(std::shared_ptr< ccf::crypto::KeyPair_OpenSSL > service_kp_, const ccf::COSESignaturesConfig &cose_signatures) override
Definition history.h:198
void try_emit_signature() override
Definition history.h:194
void compact(ccf::kv::Version) override
Definition history.h:174
bool verify_root_signatures(ccf::kv::Version v) override
Definition history.h:155
ccf::crypto::Sha256Hash get_replicated_state_root() override
Definition history.h:210
ccf::kv::Term term_of_last_version
Definition history.h:132
void start_signature_emit_timer() override
Definition history.h:196
void rollback(const ccf::kv::TxID &tx_id, ccf::kv::Term commit_term_) override
Definition history.h:166
std::tuple< ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term > get_replicated_state_txid_and_root() override
Definition history.h:216
bool init_from_snapshot(const std::vector< uint8_t > &) override
Definition history.h:176
std::vector< uint8_t > serialise_tree(size_t) override
Definition history.h:234
void emit_signature() override
Definition history.h:186
ccf::kv::Term term_of_next_version
Definition history.h:133
bool verify_proof(const std::vector< uint8_t > &) override
Definition history.h:229
void append(const std::vector< uint8_t > &) override
Definition history.h:142
std::vector< uint8_t > get_proof(ccf::kv::Version) override
Definition history.h:224
void set_term(ccf::kv::Term t) override
Definition history.h:160
void append_entry(const ccf::crypto::Sha256Hash &digest, std::optional< ccf::kv::Term > term_of_next_version_=std::nullopt) override
Definition history.h:147
ccf::kv::Version version
Definition history.h:131
NullTxHistory(ccf::kv::Store &store_, const NodeId &id_, ccf::crypto::KeyPair &)
Definition history.h:136
const ccf::COSESignaturesConfig & get_cose_signatures_config() override
Definition history.h:205
std::vector< uint8_t > get_raw_leaf(uint64_t) override
Definition history.h:181
Definition history.h:261
std::shared_ptr< HistoryTree::Path > get_path()
Definition history.h:281
const HistoryTree::Hash & get_root() const
Definition history.h:276
std::vector< uint8_t > to_v() const
Definition history.h:311
Proof(HistoryTree *tree, uint64_t index)
Definition history.h:286
Proof(const std::vector< uint8_t > &v)
Definition history.h:269
Proof(const Proof &)=delete
Proof()
Definition history.h:267
bool verify(HistoryTree *tree) const
Definition history.h:294
Definition key_pair.h:17
virtual std::vector< uint8_t > public_key_der() const override
Definition key_pair.cpp:124
Definition key_pair.h:19
virtual std::vector< uint8_t > sign_hash(const uint8_t *hash, size_t hash_size) const =0
Definition pem.h:18
Definition sha256_hash.h:16
Representation h
Definition sha256_hash.h:20
std::string hex_str() const
Definition sha256_hash.cpp:61
static constexpr size_t SIZE
Definition sha256_hash.h:18
Definition kv_types.h:509
Definition store.h:88
ReservedTx create_reserved_tx(const TxID &tx_id)
Definition store.h:1300
ReadOnlyTx create_read_only_tx() override
Definition store.h:1275
size_t committable_gap() override
Definition store.h:1129
TxID next_txid() override
Definition store.h:1121
std::shared_ptr< Consensus > get_consensus() override
Definition store.h:188
CommitResult commit(const TxID &txid, std::unique_ptr< PendingTx > pending_tx, bool globally_committable) override
Definition store.h:905
Definition kv_types.h:368
std::tuple< size_t, size_t > RequestID
Definition kv_types.h:372
virtual std::vector< uint8_t > serialise_tree(size_t to)=0
virtual ccf::crypto::Sha256Hash get_replicated_state_root()=0
static ThreadMessaging & instance()
Definition thread_messaging.h:283
bool cancel_timer_task(TaskQueue::TimerEntry timer_entry)
Definition thread_messaging.h:333
TaskQueue::TimerEntry add_task_after(std::unique_ptr< Tmsg< Payload > > msg, std::chrono::milliseconds ms)
Definition thread_messaging.h:326
#define LOG_INFO_FMT
Definition logger.h:362
#define LOG_TRACE_FMT
Definition logger.h:356
#define LOG_DEBUG_FMT
Definition logger.h:357
#define LOG_FAIL_FMT
Definition logger.h:363
void openssl_sha256(const std::span< const uint8_t > &data, uint8_t *h)
Definition hash.cpp:101
std::shared_ptr< COSEParametersFactory > cose_params_int_int(int64_t key, int64_t value)
Definition cose_sign.cpp:154
std::shared_ptr< COSEParametersFactory > cose_params_int_bytes(int64_t key, std::span< const uint8_t > value)
Definition cose_sign.cpp:204
std::shared_ptr< COSEParametersFactory > cose_params_int_string(int64_t key, const std::string &value)
Definition cose_sign.cpp:166
std::unique_ptr< COSEVerifier > COSEVerifierUniquePtr
Definition cose_verifier.h:25
std::shared_ptr< COSEParametersFactory > cose_params_string_string(const std::string &key, const std::string &value)
Definition cose_sign.cpp:191
std::vector< uint8_t > cose_sign1(const KeyPair_OpenSSL &key, const std::vector< std::shared_ptr< COSEParametersFactory > > &protected_headers, std::span< const uint8_t > payload, bool detached_payload)
Definition cose_sign.cpp:231
COSEVerifierUniquePtr make_cose_verifier_from_cert(const std::vector< uint8_t > &cert)
Definition cose_verifier.cpp:221
std::vector< std::shared_ptr< ccf::crypto::COSEParametersFactory > > COSEHeadersArray
Definition cose_sign.h:164
uint64_t Term
Definition kv_types.h:48
uint64_t Version
Definition version.h:8
std::mutex Mutex
Definition locking.h:12
Definition app_interface.h:14
merkle::TreeT< sha256_byte_size, ccf::sha256_history > HistoryTree
Definition history.h:258
constexpr int MAX_HISTORY_LEN
Definition history.h:61
std::vector< uint8_t > CoseSignature
Definition signatures.h:64
HashOp
Definition history.h:51
@ COMPACT
Definition history.h:55
@ VERIFY
Definition history.h:53
@ APPEND
Definition history.h:52
@ ROLLBACK
Definition history.h:54
Definition consensus_types.h:23
Definition cose_signatures_config.h:12
std::string issuer
Definition cose_signatures_config.h:13
std::string subject
Definition cose_signatures_config.h:14
Definition signatures.h:14
Definition kv_types.h:487
Definition kv_types.h:52
std::string str() const
Definition kv_types.h:73
Version version
Definition kv_types.h:54
Term term
Definition kv_types.h:53
auto format(const ccf::kv::TxHistory::RequestID &p, FormatContext &ctx) const
Definition history.h:40
constexpr auto parse(ParseContext &ctx)
Definition history.h:34