16 std::unique_lock lk(m_bc_mut);
21 std::shared_lock lk0(m_bc_mut, std::defer_lock);
22 std::unique_lock lk1(m_ec_mut, std::defer_lock);
24 auto repeated_tx_filter = [&](
const auto& err) ->
bool {
26 auto check_uhs = [&](
const hash_t& err_tx_id,
auto&& info) {
27 for(
const auto& uhs : info.input_uhs_ids()) {
29 auto [height, tx_id] =
spent.value();
30 if(err_tx_id == tx_id) {
36 auto [height, tx_id] =
unspent.value();
37 if(err_tx_id == tx_id) {
45 check_uhs(err.tx_id(), std::move(info));
48 check_uhs(err.tx_id(), std::move(info));
51 std::move(err.info()));
55 std::remove_if(errs.begin(), errs.end(), repeated_tx_filter),
60 auto watchtower::check_uhs_id_statuses(
const std::vector<hash_t>& uhs_ids,
65 -> std::vector<status_update_state> {
66 std::vector<status_update_state> states;
67 states.reserve(uhs_ids.size());
68 for(
const auto& uhs_id : uhs_ids) {
69 auto found_status =
false;
77 if(
auto uhs_err = m_ec.check_uhs_id(uhs_id)) {
90 if(
auto spent = m_bc.check_spent(uhs_id)) {
91 auto [height, s_tx_id] =
spent.value();
92 if(s_tx_id == tx_id) {
99 }
else if(
auto unspent = m_bc.check_unspent(uhs_id)) {
100 auto [height, us_tx_id] =
unspent.value();
101 if(us_tx_id == tx_id) {
121 -> std::unique_ptr<response> {
122 std::unordered_map<
hash_t,
123 std::vector<status_update_state>,
127 std::shared_lock lk0(m_bc_mut, std::defer_lock);
128 std::shared_lock lk1(m_ec_mut, std::defer_lock);
130 auto best_height = m_bc.best_block_height();
131 for(
const auto& [tx_id, uhs_ids] : req.uhs_ids()) {
132 auto tx_err = m_ec.check_tx_id(tx_id);
133 bool internal_err{
false};
134 if(tx_err.has_value()
135 && (std::holds_alternative<tx_error_sync>(
136 tx_err.value().info())
137 || std::holds_alternative<tx_error_stxo_range>(
138 tx_err.value().info()))) {
141 auto states = check_uhs_id_statuses(uhs_ids,
146 chks.emplace(std::make_pair(tx_id, std::move(states)));
155 -> std::unique_ptr<response> {
156 std::shared_lock lk(m_bc_mut);
157 return std::make_unique<response>(
162 : m_bc{block_cache_size},
163 m_ec{error_cache_size} {}
176 return (rhs.m_height == m_height);
180 : m_height(height) {}
191 return m_req == rhs.m_req;
205 return m_resp == rhs.m_resp;
Interface for serializing objects into and out of raw bytes representations.
Contains the watchtower's known best block height.
auto height() const -> uint64_t
Returns the states of a set of UHS IDs, following the order of the UHS IDs in the containing StatusUp...
best_block_height_response()=delete
auto operator==(const best_block_height_response &rhs) const -> bool
void push_block(cbdc::atomizer::block &&blk)
Moves a block into the block cache, evicting the oldest block if the cache has reached its maximum si...
auto check_unspent(const hash_t &uhs_id) const -> std::optional< block_cache_result >
Checks to see if the given UHS ID is spendable according to the blocks in the cache.
auto check_spent(const hash_t &uhs_id) const -> std::optional< block_cache_result >
Checks to see if the given UHS ID has been spent according to the blocks in the cache.
void push_errors(std::vector< tx_error > &&errs)
Moves an error into the error cache, evicting the oldest error if the cache has reached its maximum s...
RPC request message to the watchtower external endpoint.
auto payload() const -> const request_t &
Return the request payload.
auto operator==(const request &rhs) const -> bool
std::variant< status_update_request, best_block_height_request > request_t
RPC response message from the watchtower external endpoint.
std::variant< status_request_check_success, best_block_height_response > response_t
auto payload() const -> const response_t &
Return the response payload.
auto operator==(const response &rhs) const -> bool
Indicates a successful check request, sent with a StatusUpdateResponse.
Network request to interact with the Watchtower's status update service.
Represents the internal state of an ongoing status update request.
void add_errors(std::vector< tx_error > &&errs)
Adds an error from an internal component to the Watchtower's error cache.
auto handle_status_update_request(const status_update_request &req) -> std::unique_ptr< response >
Composes a response to a status update request based on the data available.
void add_block(cbdc::atomizer::block &&blk)
Adds a new block from the Atomizer to the Watchtower.
auto handle_best_block_height_request(const best_block_height_request &req) -> std::unique_ptr< response >
Composes a response to a status update best block height request.
@ invalid_input
The transaction processing system rejected the transaction because the requested UHS ID was already s...
@ spent
The STXO set contains the requested UHS ID.
@ unspent
The UTXO set contains the requested UHS ID.
@ internal_error
The transaction processing system failed to process the transaction containing the requested UHS ID d...
@ tx_rejected
The transaction processing system rejected the requested UHS ID's transaction due to a problem with a...
@ no_history
The Watchtower has finished scanning the block history for the UHS ID in the request and hasn't found...
auto get_variant(serializer &deser) -> std::variant< Ts... >
Deserializes a variant where the alternatives are all default constructible or all are not default co...
std::array< unsigned char, cbdc::hash_size > hash_t
SHA256 hash container.
Batch of compact transactions settled by the atomizer.
SipHash function to generate STL data structure hash keys for system IDs.
Variant handler template.
Request the watchtower's known best block height.
auto operator==(const best_block_height_request &) const -> bool
best_block_height_request()=default
Watchtower core functionality.