27#include <merklecpp/merklecpp.h>
31struct formatter<
ccf::kv::TxHistory::RequestID>
33 template <
typename ParseContext>
34 constexpr auto parse(ParseContext& ctx)
39 template <
typename FormatContext>
43 ctx.out(),
"<RID {0}, {1}>", std::get<0>(p), std::get<1>(p));
58#ifdef OVERRIDE_MAX_HISTORY_LEN
64 static std::ostream& operator<<(std::ostream& os,
HashOp flag)
111 sig.template wo<ccf::Signatures>(ccf::Tables::SIGNATURES);
112 auto cose_signatures =
113 sig.template wo<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
115 auto serialised_tree = sig.template wo<ccf::SerialisedMerkleTree>(
116 ccf::Tables::SERIALISED_MERKLE_TREE);
118 signatures->put(sig_value);
120 serialised_tree->put({});
121 return sig.commit_reserved();
142 void append(
const std::vector<uint8_t>&)
override
149 std::optional<ccf::kv::Term> term_of_next_version_ =
150 std::nullopt)
override
189 LOG_DEBUG_FMT(
"Issuing signature at {}.{}", txid.term, txid.version);
191 txid, std::make_unique<NullTxHistoryPendingTx>(txid, store,
id),
true);
199 std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp_,
202 std::ignore = std::move(service_kp_);
207 throw std::logic_error(
"Unimplemented");
215 std::tuple<ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
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)
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);
258 using HistoryTree = merkle::TreeT<sha256_byte_size, ccf::sha256_history>;
263 HistoryTree::Hash root;
264 std::shared_ptr<HistoryTree::Path> path =
nullptr;
269 Proof(
const std::vector<uint8_t>& v)
272 root.deserialise(v, position);
273 path = std::make_shared<HistoryTree::Path>(v, position);
289 path = tree->path(index);
296 if (path->max_index() > tree->max_index())
300 else if (tree->max_index() == path->max_index())
302 return tree->root() == root && path->verify(root);
306 auto past_root = tree->past_root(path->max_index());
307 return path->verify(*past_root);
311 std::vector<uint8_t>
to_v()
const
313 std::vector<uint8_t> v;
347 service_kp(service_kp_),
348 endorsed_cert(endorsed_cert_),
349 cose_signatures_config(cose_signatures_config_)
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);
363 std::vector<uint8_t> primary_sig;
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());
378 constexpr int64_t vds_merkle_tree = 2;
382 std::span<const uint8_t> kid_span{(uint8_t*)kid.data(), kid.size()};
384 const auto time_since_epoch =
385 std::chrono::duration_cast<std::chrono::seconds>(
386 std::chrono::system_clock::now().time_since_epoch())
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())}));
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),
414 const auto pheaders = {
417 ccf::crypto::COSE_PHEADER_KEY_ID, kid_span),
420 ccf::crypto::COSE_PHEADER_KEY_VDS, vds_merkle_tree),
428 signatures->put(sig_value);
429 cose_signatures->put(cose_sign);
431 return sig.commit_reserved();
449 tree =
new HistoryTree(merkle::Hash(first_hash.h));
466 tree->insert(merkle::Hash(hash.
h));
471 const merkle::Hash& root = tree->root();
473 std::copy(root.bytes, root.bytes + root.size(), result.
h.begin());
487 tree->flush_to(index);
493 tree->retract_to(index);
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",
508 throw std::logic_error(fmt::format(
509 "Cannot produce proof for {}: index is later than last index {}",
513 return Proof(tree, index);
523 LOG_TRACE_FMT(
"mt_serialize_size {}", tree->serialised_size());
524 std::vector<uint8_t> output;
525 tree->serialise(output);
532 "mt_serialize_size ({},{}) {}",
535 tree->serialised_size(from, to));
536 std::vector<uint8_t> output;
537 tree->serialise(from, to, output);
543 return tree->min_index();
548 return tree->max_index();
558 const merkle::Hash& leaf = tree->leaf(index);
560 std::copy(leaf.bytes, leaf.bytes + leaf.size(), result.
h.begin());
570 T replicated_state_tree;
574 std::vector<uint8_t> cose_cert_cached{};
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;
585 std::optional<ccf::crypto::Pem> endorsed_cert = std::nullopt;
587 struct ServiceSigningIdentity
589 const std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp;
593 std::optional<ServiceSigningIdentity> signing_identity = std::nullopt;
600 size_t sig_tx_interval_ = 0,
601 size_t sig_ms_interval_ = 0,
602 bool signature_timer =
false) :
606 sig_tx_interval(sig_tx_interval_),
607 sig_ms_interval(sig_ms_interval_)
616 std::shared_ptr<ccf::crypto::KeyPair_OpenSSL> service_kp_,
619 if (signing_identity.has_value())
621 throw std::logic_error(
622 "Called set_service_signing_identity() multiple times");
625 signing_identity.emplace(
626 ServiceSigningIdentity{service_kp_, cose_signatures_config_});
629 "Setting service signing identity to iss: {} sub: {}",
630 cose_signatures_config_.
issuer,
631 cose_signatures_config_.
subject);
636 if (!signing_identity.has_value())
638 throw std::logic_error(
639 "Called get_cose_signatures_config() before "
640 "set_service_signing_identity()");
643 return signing_identity->cose_signatures_config;
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;
658 std::unique_lock<ccf::pal::Mutex> mguard(
659 self->signature_lock, std::defer_lock);
661 bool should_emit_signature =
false;
663 if (mguard.try_lock())
665 auto consensus = self->store.get_consensus();
668 auto sig_disp =
consensus->get_signature_disposition();
677 if (self->store.committable_gap() > 0)
679 should_emit_signature =
true;
685 should_emit_signature =
true;
692 if (should_emit_signature)
694 msg->data.self->emit_signature();
697 self->emit_signature_timer_entry =
699 std::move(msg), std::chrono::milliseconds(self->sig_ms_interval));
703 emit_signature_timer_entry =
705 std::move(emit_sig_msg), std::chrono::milliseconds(sig_ms_interval));
710 if (emit_signature_timer_entry.has_value())
713 *emit_signature_timer_entry);
723 const std::vector<uint8_t>& hash_at_snapshot)
override
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())
740 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
743 !replicated_state_tree.in_range(1),
744 "Tree is not empty before initialising from snapshot");
746 replicated_state_tree.deserialise(tree.value());
750 hash_at_snapshot.begin(),
753 replicated_state_tree.append(hash);
759 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
760 return replicated_state_tree.get_root();
763 std::tuple<ccf::kv::TxID, ccf::crypto::Sha256Hash, ccf::kv::Term>
766 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
768 {term_of_last_version,
770 replicated_state_tree.get_root(),
771 term_of_next_version};
779 tx.template ro<ccf::Signatures>(ccf::Tables::SIGNATURES);
780 auto sig = signatures->get();
781 if (!sig.has_value())
789 if (!verify_node_signature(tx, sig->node, sig->sig, root))
794 auto cose_signatures =
795 tx.template ro<ccf::CoseSignatures>(ccf::Tables::COSE_SIGNATURES);
796 auto cose_sig = cose_signatures->get();
798 if (!cose_sig.has_value())
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)
813 "Non-monotonic presence of COSE signatures - had one at {} but none "
815 cose_sig_version.value(),
820 auto service = tx.template ro<ccf::Service>(Tables::SERVICE);
821 auto service_info = service->get();
823 if (!service_info.has_value())
825 LOG_FAIL_FMT(
"No service key found to verify the signature");
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()};
833 return cose_verifier_cached(raw_cert)->verify_detached(
834 cose_sig.value(), root_hash);
839 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
840 if (to <= replicated_state_tree.end_index())
842 return replicated_state_tree.serialise(
843 replicated_state_tree.begin_index(), to);
855 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
856 term_of_last_version = t;
857 term_of_next_version = t;
863 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
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);
873 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
880 log_hash(replicated_state_tree.get_root(),
COMPACT);
887 std::unique_lock<ccf::pal::Mutex> mguard(
signature_lock, std::defer_lock);
909 if (!endorsed_cert.has_value())
911 throw std::logic_error(
912 fmt::format(
"No endorsed certificate set to emit signature"));
917 LOG_DEBUG_FMT(
"Signed at {} in view: {}", txid.version, txid.term);
919 if (!signing_identity.has_value())
921 throw std::logic_error(
922 fmt::format(
"No service key has been set yet to sign"));
933 *signing_identity->service_kp,
934 endorsed_cert.value(),
935 signing_identity->cose_signatures_config),
941 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
942 return replicated_state_tree.get_proof(index).to_v();
948 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
949 return replicated_state_tree.verify(proof);
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()};
959 void append(
const std::vector<uint8_t>& data)
override
963 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
964 replicated_state_tree.append(rh);
969 std::optional<ccf::kv::Term> expected_term_of_next_version =
970 std::nullopt)
override
973 std::lock_guard<ccf::pal::Mutex> guard(state_lock);
974 if (expected_term_of_next_version.has_value())
976 if (expected_term_of_next_version.value() != term_of_next_version)
981 replicated_state_tree.append(digest);
986 endorsed_cert = cert;
991 const std::vector<uint8_t>& cert)
993 if (cert != cose_cert_cached)
995 cose_cert_cached = cert;
999 return cose_verifier;
#define CCF_ASSERT_FMT(expr,...)
Definition ccf_assert.h:10
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
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
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
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
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
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
virtual std::vector< uint8_t > public_key_der() const override
Definition key_pair.cpp:124
virtual std::vector< uint8_t > sign_hash(const uint8_t *hash, size_t hash_size) const =0
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
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
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