Skip to content
New issue

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

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

Already on GitHub? # to your account

Improve block field functions by accessing sideband information internally #4465

Merged
merged 17 commits into from
Mar 9, 2024

Conversation

clemahieu
Copy link
Contributor

This change moves the responsibility of determining if a field is in the block or in the block's sideband on to the block class.

Previously call sites would need to either inspect the block type or check for a sentinel value to determine where the block field information was stored. This complicates call sites, duplicates code, and could be error prone.

Direct block field access e.g. account/link/destination/balance are suffixed with _field and return an std::optional depending if the block type contains the requested field.

The replacement field functions check block type and determine if the value should be retrieved from the field or the block sideband.

The conversion for each field is done with two commits in order to ensure all call sites are inspected and updated to the new semantics.

  • The first commit changes the return type of of the block field which allowed easy locating / updating of all the call sites through compiler type checking.
  • The second commit renames the direct field access function and adds a helper function to pull the field value or the sideband value depending on block type.

@@ -166,7 +166,7 @@ void nano::bootstrap_ascending::service::inspect (store::transaction const & tx,
break;
case nano::block_status::gap_source:
{
const auto account = block.previous ().is_zero () ? block.account ().value () : ledger.account (tx, block.previous ()).value ();
const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.account (tx, block.previous ()).value ();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line looks a bit suspicious, it seems to rely on the fact that if both source and previous block is missing, then ledger processing code will return block_status::gap_previous. Otherwise it would crash. No need to do anything, just something that might bite later down the road, with subsequent refactorings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea it relies on the fact that if previous.is_zero (), then it must be an open or state block and therefore the account field is present. Since the block failed to be inserted it won't have sideband at this point.

pwojcikdev
pwojcikdev previously approved these changes Mar 7, 2024
…y contains the field.

Fixes up call sites that checked against the old sentinel value 0.
Convert many call sites to using ledger::account(block&) when possible.
@clemahieu clemahieu force-pushed the block_fields branch 2 times, most recently from 7fdf312 to ec4706a Compare March 8, 2024 00:22
@clemahieu clemahieu marked this pull request as ready for review March 8, 2024 14:28
nano/lib/blocks.hpp Outdated Show resolved Hide resolved
@@ -3679,7 +3679,7 @@ void nano::json_handler::republish ()
while (block_d != nullptr && hash != source)
{
hashes.push_back (previous);
source = node.ledger.block_source (transaction, *block_d);
source = block_d->source_field ().value_or (block_d->is_send () ? 0 : block_d->link_field ().value_or (0).as_block_hash ());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A short node.ledger.block_source ( .. ) call changed into this relatively long conditional statement, is this intentional?

pwojcikdev
pwojcikdev previously approved these changes Mar 9, 2024
@@ -3641,7 +3641,7 @@ void nano::json_handler::republish ()
block = node.ledger.block (transaction, hash);
if (sources != 0) // Republish source chain
{
nano::block_hash source (node.ledger.block_source (transaction, *block));
nano::block_hash source = block->source_field ().value_or (block->link_field ().value_or (0).as_block_hash ());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another line that got more complicated after the refactor than before.

…ccesses the account field is renamed to block::account_field.
…ccesses the account field is renamed to block::balance_field.
…estination is created which accesses the the destination field for send blocks.
…ce is moved to block::source which accesses the source field for open/receive/state blocks that are receives.
A specialised variant of is_send for state blocks that do not have sideband was added to dependent_block_visitor so the value can be calculated even if the block does not yet have sideband.
…nge block or a state block with a zero link field.
… number to an account number are replaced with calls to block::destination (). Usages that converted this number to a block_hash are replaced with calls to block::source, and usages that check this number for being an epoch directly access the link field.
…nal depending if the block has the field.

Add block::previous with backwards compatibility and a todo to fix up usages to not check for sentinel values.
@clemahieu clemahieu merged commit 7561a79 into nanocurrency:develop Mar 9, 2024
24 of 27 checks passed
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants