Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix active_transactions missed notifications #4505

Merged
merged 7 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions nano/lib/blocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ bool nano::block::is_change () const noexcept
}
}

bool nano::block::is_epoch () const noexcept
{
release_assert (has_sideband ());
switch (type ())
{
case nano::block_type::state:
return sideband ().details.is_epoch;
default:
return false;
}
}

nano::block_hash const & nano::block::hash () const
{
if (!cached_hash.is_zero ())
Expand Down
1 change: 1 addition & 0 deletions nano/lib/blocks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class block
bool is_send () const noexcept;
bool is_receive () const noexcept;
bool is_change () const noexcept;
bool is_epoch () const noexcept;

public: // Direct access to the block fields or nullopt if the block type does not have the specified field
// Returns account field or account from sideband
Expand Down
57 changes: 20 additions & 37 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ void nano::active_transactions::stop ()

void nano::active_transactions::block_cemented_callback (std::shared_ptr<nano::block> const & block_a)
{
auto transaction = node.store.tx_begin_read ();
auto status_type = election_status (transaction, block_a);
auto status_type = election_status (block_a);

if (!status_type)
return;

auto transaction = node.store.tx_begin_read ();
switch (*status_type)
{
case nano::election_status_type::inactive_confirmation_height:
Expand All @@ -102,13 +102,13 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptr<nano::b
handle_final_votes_confirmation (block_a, transaction, *status_type);
}

boost::optional<nano::election_status_type> nano::active_transactions::election_status (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block)
boost::optional<nano::election_status_type> nano::active_transactions::election_status (std::shared_ptr<nano::block> const & block)
{
boost::optional<nano::election_status_type> status_type;

if (!confirmation_height_processor.is_processing_added_block (block->hash ()))
{
status_type = confirm_block (transaction, block);
status_type = confirm_block (block);
}
else
{
Expand All @@ -120,13 +120,8 @@ boost::optional<nano::election_status_type> nano::active_transactions::election_

void nano::active_transactions::process_inactive_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block)
{
nano::account account;
nano::uint128_t amount{ 0 };
bool is_state_send = false;
bool is_state_epoch = false;
nano::account pending_account{};
node.process_confirmed_data (transaction, block, block->hash (), account, amount, is_state_send, is_state_epoch, pending_account);
node.observers.blocks.notify (nano::election_status{ block, 0, 0, std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values<std::chrono::milliseconds>::zero (), 0, 1, 0, nano::election_status_type::inactive_confirmation_height }, {}, account, amount, is_state_send, is_state_epoch);
nano::election_status status{ block, 0, 0, std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values<std::chrono::milliseconds>::zero (), 0, 1, 0, nano::election_status_type::inactive_confirmation_height };
notify_observers (transaction, status, {});
}

void nano::active_transactions::process_active_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::election_status_type status_type)
Expand All @@ -151,38 +146,26 @@ void nano::active_transactions::handle_confirmation (nano::store::read_transacti
nano::block_hash hash = block->hash ();
recently_cemented.put (election->get_status ());

nano::account account;
nano::uint128_t amount (0);
bool is_state_send = false;
bool is_state_epoch = false;
nano::account pending_account;

handle_block_confirmation (transaction, block, hash, account, amount, is_state_send, is_state_epoch, pending_account);

auto status = election->set_status_type (status_type);
auto votes = election->votes_with_weight ();
notify_observers (status, votes, account, amount, is_state_send, is_state_epoch, pending_account);
}

void nano::active_transactions::handle_block_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::block_hash const & hash, nano::account & account, nano::uint128_t & amount, bool & is_state_send, bool & is_state_epoch, nano::account & pending_account)
{
if (block->is_send ())
{
node.receive_confirmed (transaction, hash, block->destination ());
}
node.process_confirmed_data (transaction, block, hash, account, amount, is_state_send, is_state_epoch, pending_account);
notify_observers (transaction, status, votes);
}

void nano::active_transactions::notify_observers (nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes, nano::account const & account, nano::uint128_t amount, bool is_state_send, bool is_state_epoch, nano::account const & pending_account)
void nano::active_transactions::notify_observers (nano::store::read_transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes)
{
auto block = status.winner;
auto account = block->account ();
auto amount = node.ledger.amount (transaction, block->hash ()).value_or (0);
auto is_state_send = block->type () == block_type::state && block->is_send ();
auto is_state_epoch = block->type () == block_type::state && block->is_epoch ();
node.observers.blocks.notify (status, votes, account, amount, is_state_send, is_state_epoch);

if (amount > 0)
{
node.observers.account_balance.notify (account, false);
if (!pending_account.is_zero ())
if (block->is_send ())
{
node.observers.account_balance.notify (pending_account, true);
node.observers.account_balance.notify (block->destination (), true);
}
}
}
Expand All @@ -196,16 +179,16 @@ void nano::active_transactions::handle_final_votes_confirmation (std::shared_ptr
// Next-block activations are only done for blocks with previously active elections
if (cemented_bootstrap_count_reached && was_active)
{
activate_successors (account, block, transaction);
activate_successors (transaction, block);
}
}

void nano::active_transactions::activate_successors (const nano::account & account, std::shared_ptr<nano::block> const & block, nano::store::read_transaction const & transaction)
void nano::active_transactions::activate_successors (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block)
{
node.scheduler.priority.activate (account, transaction);
node.scheduler.priority.activate (block->account (), transaction);

// Start or vote for the next unconfirmed block in the destination account
if (block->is_send () && !block->destination ().is_zero () && block->destination () != account)
if (block->is_send () && !block->destination ().is_zero () && block->destination () != block->account ())
{
node.scheduler.priority.activate (block->destination (), transaction);
}
Expand Down Expand Up @@ -671,7 +654,7 @@ bool nano::active_transactions::publish (std::shared_ptr<nano::block> const & bl
}

// Returns the type of election status requiring callbacks calling later
boost::optional<nano::election_status_type> nano::active_transactions::confirm_block (store::transaction const & transaction_a, std::shared_ptr<nano::block> const & block_a)
boost::optional<nano::election_status_type> nano::active_transactions::confirm_block (std::shared_ptr<nano::block> const & block_a)
{
auto const hash = block_a->hash ();
std::shared_ptr<nano::election> election = nullptr;
Expand Down
9 changes: 4 additions & 5 deletions nano/node/active_transactions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class active_transactions final
bool empty () const;
std::size_t size () const;
bool publish (std::shared_ptr<nano::block> const &);
boost::optional<nano::election_status_type> confirm_block (store::transaction const &, std::shared_ptr<nano::block> const &);
boost::optional<nano::election_status_type> confirm_block (std::shared_ptr<nano::block> const &);
void block_cemented_callback (std::shared_ptr<nano::block> const &);
void block_already_cemented_callback (nano::block_hash const &);

Expand Down Expand Up @@ -195,14 +195,13 @@ class active_transactions final
* TODO: Should be moved to `vote_cache` class
*/
void add_vote_cache (nano::block_hash const & hash, std::shared_ptr<nano::vote> vote);
boost::optional<nano::election_status_type> election_status (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block);
boost::optional<nano::election_status_type> election_status (std::shared_ptr<nano::block> const & block);
void process_inactive_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block);
void process_active_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::election_status_type status);
void handle_final_votes_confirmation (std::shared_ptr<nano::block> const & block, nano::store::read_transaction const & transaction, nano::election_status_type status);
void handle_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, std::shared_ptr<nano::election> election, nano::election_status_type status);
void activate_successors (const nano::account & account, std::shared_ptr<nano::block> const & block, nano::store::read_transaction const & transaction);
void handle_block_confirmation (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::block_hash const & hash, nano::account & account, nano::uint128_t & amount, bool & is_state_send, bool & is_state_epoch, nano::account & pending_account);
void notify_observers (nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes, nano::account const & account, nano::uint128_t amount, bool is_state_send, bool is_state_epoch, nano::account const & pending_account);
void activate_successors (nano::store::read_transaction const & transaction, std::shared_ptr<nano::block> const & block);
void notify_observers (nano::store::read_transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes);

private: // Dependencies
nano::node & node;
Expand Down
48 changes: 7 additions & 41 deletions nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,13 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons
std::exit (1);
}
}
confirmation_height_processor.add_cemented_observer ([this] (auto const & block) {
if (block->is_send ())
{
auto transaction = store.tx_begin_read ();
receive_confirmed (transaction, block->hash (), block->destination ());
}
});
}
node_initialized_latch.count_down ();
}
Expand Down Expand Up @@ -1212,47 +1219,6 @@ void nano::node::receive_confirmed (store::transaction const & block_transaction
}
}

void nano::node::process_confirmed_data (store::transaction const & transaction_a, std::shared_ptr<nano::block> const & block_a, nano::block_hash const & hash_a, nano::account & account_a, nano::uint128_t & amount_a, bool & is_state_send_a, bool & is_state_epoch_a, nano::account & pending_account_a)
{
// Faster account calculation
account_a = block_a->account ();
// Faster amount calculation
auto previous (block_a->previous ());
auto previous_balance = ledger.balance (transaction_a, previous);
auto block_balance = block_a->balance ();
if (hash_a != ledger.constants.genesis->account ())
{
if (previous_balance)
{
amount_a = block_balance > previous_balance.value () ? block_balance.number () - previous_balance.value () : previous_balance.value () - block_balance.number ();
}
else
{
amount_a = 0;
}
}
else
{
amount_a = nano::dev::constants.genesis_amount;
}
if (auto state = dynamic_cast<nano::state_block *> (block_a.get ()))
{
if (state->hashables.balance < previous_balance)
{
is_state_send_a = true;
}
if (amount_a == 0 && network_params.ledger.epochs.is_epoch_link (state->link_field ().value ()))
{
is_state_epoch_a = true;
}
pending_account_a = state->hashables.link.as_account ();
}
if (auto send = dynamic_cast<nano::send_block *> (block_a.get ()))
{
pending_account_a = send->hashables.destination;
}
}

void nano::node::process_confirmed (nano::election_status const & status_a, uint64_t iteration_a)
{
auto hash (status_a.winner->hash ());
Expand Down
1 change: 0 additions & 1 deletion nano/node/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class node final : public std::enable_shared_from_this<nano::node>
std::shared_ptr<nano::node> shared ();
int store_version ();
void receive_confirmed (store::transaction const & block_transaction_a, nano::block_hash const & hash_a, nano::account const & destination_a);
void process_confirmed_data (store::transaction const &, std::shared_ptr<nano::block> const &, nano::block_hash const &, nano::account &, nano::uint128_t &, bool &, bool &, nano::account &);
void process_confirmed (nano::election_status const &, uint64_t = 0);
void process_active (std::shared_ptr<nano::block> const &);
std::optional<nano::block_status> process_local (std::shared_ptr<nano::block> const &);
Expand Down
2 changes: 1 addition & 1 deletion nano/node/node_observers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class node_observers final
{
public:
using blocks_t = nano::observer_set<nano::election_status const &, std::vector<nano::vote_with_weight_info> const &, nano::account const &, nano::uint128_t const &, bool, bool>;
blocks_t blocks;
blocks_t blocks; // Notification upon election completion or cancellation
nano::observer_set<bool> wallet;
nano::observer_set<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>, nano::vote_code> vote;
nano::observer_set<nano::block_hash const &> active_started;
Expand Down
Loading