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