12 : m_prefix_range(std::move(prefix_range)) {}
15 -> std::optional<std::string> {
17 opt.create_if_missing =
true;
19 leveldb::DB* db_ptr{};
20 const auto res = leveldb::DB::Open(opt, db_dir, &db_ptr);
23 return res.ToString();
25 this->m_db.reset(db_ptr);
28 std::string bestBlockHeight;
29 const auto bestBlockRes = this->m_db->Get(this->m_read_options,
30 m_best_block_height_key,
32 if(bestBlockRes.IsNotFound()) {
33 this->m_best_block_height = 0;
34 std::array<char,
sizeof(m_best_block_height)> height_arr{};
35 std::memcpy(height_arr.data(),
37 sizeof(m_best_block_height));
38 leveldb::Slice startBestBlockHeight(
40 sizeof(this->m_best_block_height));
41 this->m_db->Put(this->m_write_options,
42 m_best_block_height_key,
43 startBestBlockHeight);
45 assert(bestBlockHeight.size()
46 ==
sizeof(this->m_best_block_height));
47 std::memcpy(&this->m_best_block_height,
48 bestBlockHeight.c_str(),
49 sizeof(this->m_best_block_height));
58 if(blk.m_height != m_best_block_height + 1) {
62 leveldb::WriteBatch batch;
65 for(
const auto& tx : blk.m_transactions) {
67 for(
const auto& out : tx.m_uhs_outputs) {
68 if(is_output_on_shard(out)) {
69 std::array<char,
sizeof(out)> out_arr{};
70 std::memcpy(out_arr.data(), out.data(), out.size());
71 leveldb::Slice OutPointKey(out_arr.data(), out.size());
72 batch.Put(OutPointKey, leveldb::Slice());
77 for(
const auto& inp : tx.m_inputs) {
78 if(is_output_on_shard(inp)) {
79 std::array<char,
sizeof(inp)> inp_arr{};
80 std::memcpy(inp_arr.data(), inp.data(), inp.size());
81 leveldb::Slice OutPointKey(inp_arr.data(), inp.size());
82 batch.Delete(OutPointKey);
88 this->m_best_block_height++;
89 std::array<char,
sizeof(m_best_block_height)> height_arr{};
90 std::memcpy(height_arr.data(),
92 sizeof(m_best_block_height));
93 leveldb::Slice newBestBlockHeight(height_arr.data(),
94 sizeof(this->m_best_block_height));
95 batch.Put(m_best_block_height_key, newBestBlockHeight);
98 this->m_db->Write(this->m_write_options, &batch);
108 std::shared_ptr<const leveldb::Snapshot> snp{};
109 uint64_t snp_height{};
111 std::shared_lock<std::shared_mutex> l(m_snp_mut);
112 snp_height = m_snp_height;
117 if(snp_height == 0) {
123 if(tx.m_inputs.empty()) {
129 auto read_options = m_read_options;
130 read_options.snapshot = snp.get();
133 std::unordered_set<uint64_t> attestations;
134 std::vector<hash_t> dne_inputs;
135 for(uint64_t i = 0; i < tx.m_inputs.size(); i++) {
136 const auto& inp = tx.m_inputs[i];
138 if(!is_output_on_shard(inp)) {
142 std::array<char,
sizeof(inp)> inp_arr{};
143 std::memcpy(inp_arr.data(), inp.data(), inp.size());
144 leveldb::Slice OutPointKey(inp_arr.data(), inp.size());
147 const auto& res = m_db->Get(read_options, OutPointKey, &op);
148 if(res.IsNotFound()) {
149 dne_inputs.push_back(inp);
151 attestations.insert(i);
155 if(!dne_inputs.empty()) {
163 msg.
m_tx = std::move(tx);
170 return m_best_block_height;
173 auto shard::is_output_on_shard(
const hash_t& uhs_hash)
const ->
bool {
177 void shard::update_snapshot() {
178 std::unique_lock<std::shared_mutex> l(m_snp_mut);
179 m_snp_height = m_best_block_height;
180 m_snp = std::shared_ptr<const leveldb::Snapshot>(
182 [&](
const leveldb::Snapshot* p) {
183 m_db->ReleaseSnapshot(p);
auto open_db(const std::string &db_dir) -> std::optional< std::string >
Creates or restores this shard's UTXO database.
auto best_block_height() const -> uint64_t
Returns the height of the most recently digested block.
auto digest_block(const cbdc::atomizer::block &blk) -> bool
Updates records to reflect changes from a new, contiguous transaction block from the atomizer.
auto digest_transaction(transaction::compact_tx tx) -> std::variant< atomizer::tx_notify_request, watchtower::tx_error >
Checks the validity of a provided transaction's inputs, and returns a transaction notification to for...
shard(config::shard_range_t prefix_range)
Constructor.
Wrapper for transaction errors.
auto hash_in_shard_range(const shard_range_t &range, const hash_t &val) -> bool
Checks if a hash is in the given range handled.
std::pair< uint8_t, uint8_t > shard_range_t
[start, end] inclusive.
std::array< unsigned char, cbdc::hash_size > hash_t
SHA256 hash container.
Shard core functionality.
Batch of compact transactions settled by the atomizer.
Transaction notification message.
std::unordered_set< uint64_t > m_attestations
Set of input indexes the shard is attesting are unspent at the given block height.
transaction::compact_tx m_tx
Compact transaction associated with the notification.
uint64_t m_block_height
Block height at which the given input attestations are valid.
A condensed, hash-only transaction representation.
Indicates a shard that tried to process a given transaction was out of sync with the atomizer,...