Skip to content

Commit 3ad6992

Browse files
committed
Change block::link to return an std::optional if the block actually contains the field.
1 parent 465ddd3 commit 3ad6992

17 files changed

+74
-74
lines changed

nano/core_test/block.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ TEST (block_builder, state)
659659
ASSERT_EQ (block->hash ().to_string (), "2D243F8F92CDD0AD94A1D456A6B15F3BE7A6FCBD98D4C5831D06D15C818CD81F");
660660
ASSERT_FALSE (block->source_field ());
661661
ASSERT_FALSE (block->destination_field ());
662-
ASSERT_EQ (block->link ().to_string (), "E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86");
662+
ASSERT_EQ (block->link ().value ().to_string (), "E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86");
663663
}
664664

665665
TEST (block_builder, state_missing_rep)
@@ -732,7 +732,7 @@ TEST (block_builder, open)
732732
ASSERT_EQ (block->hash ().to_string (), "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948");
733733
ASSERT_EQ (block->source_field ().value ().to_string (), "E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA");
734734
ASSERT_FALSE (block->destination_field ());
735-
ASSERT_TRUE (block->link ().is_zero ());
735+
ASSERT_FALSE (block->link ());
736736
}
737737

738738
TEST (block_builder, open_equality)
@@ -771,7 +771,7 @@ TEST (block_builder, change)
771771
ASSERT_EQ (block->hash ().to_string (), "13552AC3928E93B5C6C215F61879358E248D4A5246B8B3D1EEC5A566EDCEE077");
772772
ASSERT_FALSE (block->source_field ());
773773
ASSERT_FALSE (block->destination_field ());
774-
ASSERT_TRUE (block->link ().is_zero ());
774+
ASSERT_FALSE (block->link ());
775775
}
776776

777777
TEST (block_builder, change_equality)
@@ -810,7 +810,7 @@ TEST (block_builder, send)
810810
ASSERT_EQ (block->hash ().to_string (), "4560E7B1F3735D082700CFC2852F5D1F378F7418FD24CEF1AD45AB69316F15CD");
811811
ASSERT_FALSE (block->source_field ());
812812
ASSERT_EQ (block->destination_field ().value ().to_account (), "nano_1gys8r4crpxhp94n4uho5cshaho81na6454qni5gu9n53gksoyy1wcd4udyb");
813-
ASSERT_TRUE (block->link ().is_zero ());
813+
ASSERT_FALSE (block->link ());
814814
}
815815

816816
TEST (block_builder, send_equality)
@@ -872,5 +872,5 @@ TEST (block_builder, receive)
872872
ASSERT_EQ (block->hash ().to_string (), "6C004BF911D9CF2ED75CF6EC45E795122AD5D093FF5A83EDFBA43EC4A3EDC722");
873873
ASSERT_EQ (block->source_field ().value ().to_string (), "7B2B0A29C1B235FDF9B4DEF2984BB3573BD1A52D28246396FBB3E4C5FE662135");
874874
ASSERT_FALSE (block->destination_field ());
875-
ASSERT_TRUE (block->link ().is_zero ());
875+
ASSERT_FALSE (block->link ());
876876
}

nano/core_test/wallet.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ TEST (wallet, epoch_2_validation)
10011001
ASSERT_EQ (nano::epoch::epoch_2, send->sideband ().details.epoch);
10021002
ASSERT_EQ (nano::epoch::epoch_0, send->sideband ().source_epoch); // Not used for send state blocks
10031003

1004-
auto receive = wallet.receive_action (send->hash (), nano::dev::genesis_key.pub, amount, send->link ().as_account (), 1);
1004+
auto receive = wallet.receive_action (send->hash (), nano::dev::genesis_key.pub, amount, send->link ().value ().as_account (), 1);
10051005
ASSERT_NE (nullptr, receive);
10061006
if (nano::dev::network_params.work.difficulty (*receive) < node.network_params.work.base)
10071007
{
@@ -1043,7 +1043,7 @@ TEST (wallet, epoch_2_receive_propagation)
10431043
auto amount = node.config.receive_minimum.number ();
10441044
auto send1 = wallet.send_action (nano::dev::genesis_key.pub, key.pub, amount, 1);
10451045
ASSERT_NE (nullptr, send1);
1046-
ASSERT_NE (nullptr, wallet.receive_action (send1->hash (), nano::dev::genesis_key.pub, amount, send1->link ().as_account (), 1));
1046+
ASSERT_NE (nullptr, wallet.receive_action (send1->hash (), nano::dev::genesis_key.pub, amount, send1->link ().value ().as_account (), 1));
10471047

10481048
// Upgrade the genesis account to epoch 2
10491049
auto epoch2 = system.upgrade_genesis_epoch (node, nano::epoch::epoch_2);
@@ -1053,7 +1053,7 @@ TEST (wallet, epoch_2_receive_propagation)
10531053
auto send2 = wallet.send_action (nano::dev::genesis_key.pub, key.pub, amount, 1);
10541054
ASSERT_NE (nullptr, send2);
10551055

1056-
auto receive2 = wallet.receive_action (send2->hash (), key.pub, amount, send2->link ().as_account (), 1);
1056+
auto receive2 = wallet.receive_action (send2->hash (), key.pub, amount, send2->link ().value ().as_account (), 1);
10571057
ASSERT_NE (nullptr, receive2);
10581058
if (nano::dev::network_params.work.difficulty (*receive2) < node.network_params.work.base)
10591059
{
@@ -1106,7 +1106,7 @@ TEST (wallet, epoch_2_receive_unopened)
11061106

11071107
wallet.insert_adhoc (key.prv, false);
11081108

1109-
auto receive1 = wallet.receive_action (send1->hash (), key.pub, amount, send1->link ().as_account (), 1);
1109+
auto receive1 = wallet.receive_action (send1->hash (), key.pub, amount, send1->link ().value ().as_account (), 1);
11101110
ASSERT_NE (nullptr, receive1);
11111111
if (nano::dev::network_params.work.difficulty (*receive1) < node.network_params.work.base)
11121112
{
@@ -1190,7 +1190,7 @@ TEST (wallet, search_receivable)
11901190
auto receive = node.block (receive_hash);
11911191
ASSERT_NE (nullptr, receive);
11921192
ASSERT_EQ (receive->sideband ().height, 3);
1193-
ASSERT_EQ (send->hash (), receive->link ().as_block_hash ());
1193+
ASSERT_EQ (send->hash (), receive->link ().value ().as_block_hash ());
11941194
}
11951195

11961196
TEST (wallet, receive_pruned)
@@ -1228,7 +1228,7 @@ TEST (wallet, receive_pruned)
12281228

12291229
wallet2.insert_adhoc (key.prv, false);
12301230

1231-
auto open1 = wallet2.receive_action (send1->hash (), key.pub, amount, send1->link ().as_account (), 1);
1231+
auto open1 = wallet2.receive_action (send1->hash (), key.pub, amount, send1->link ().value ().as_account (), 1);
12321232
ASSERT_NE (nullptr, open1);
12331233
ASSERT_EQ (amount, node2.ledger.balance (node2.store.tx_begin_read (), open1->hash ()));
12341234
ASSERT_TIMELY_EQ (5s, node2.ledger.cache.cemented_count, 4);

nano/core_test/wallets.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,6 @@ TEST (wallets, search_receivable)
254254
auto receive = node.block (receive_hash);
255255
ASSERT_NE (nullptr, receive);
256256
ASSERT_EQ (receive->sideband ().height, 3);
257-
ASSERT_EQ (send->hash (), receive->link ().as_block_hash ());
257+
ASSERT_EQ (send->hash (), receive->link ().value ().as_block_hash ());
258258
}
259259
}

nano/lib/blocks.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,9 @@ std::optional<nano::account> nano::block::destination_field () const
177177
return std::nullopt;
178178
}
179179

180-
nano::link const & nano::block::link () const
180+
std::optional<nano::link> nano::block::link () const
181181
{
182-
static nano::link link{ 0 };
183-
return link;
182+
return std::nullopt;
184183
}
185184

186185
nano::account nano::block::account () const
@@ -226,7 +225,7 @@ nano::account nano::block::destination () const
226225
return destination_field ().value ();
227226
case nano::block_type::state:
228227
release_assert (sideband ().details.is_send);
229-
return link ().as_account ();
228+
return link ().value ().as_account ();
230229
default:
231230
release_assert (false);
232231
}
@@ -242,7 +241,7 @@ nano::block_hash nano::block::source ()
242241
return source_field ().value ();
243242
case nano::block_type::state:
244243
release_assert (sideband ().details.is_receive);
245-
return link ().as_block_hash ();
244+
return link ().value ().as_block_hash ();
246245
default:
247246
release_assert (false);
248247
}
@@ -1424,7 +1423,7 @@ nano::root const & nano::state_block::root () const
14241423
}
14251424
}
14261425

1427-
nano::link const & nano::state_block::link () const
1426+
std::optional<nano::link> nano::state_block::link () const
14281427
{
14291428
return hashables.link;
14301429
}

nano/lib/blocks.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ class block
3939
virtual nano::root const & root () const = 0;
4040
// Qualified root value based on previous() and root()
4141
virtual nano::qualified_root qualified_root () const;
42-
// Link field for state blocks, zero otherwise.
43-
virtual nano::link const & link () const;
4442
virtual nano::account const & representative () const;
4543
virtual void serialize (nano::stream &) const = 0;
4644
virtual void serialize_json (std::string &, bool = false) const = 0;
@@ -71,6 +69,8 @@ class block
7169
nano::account destination () const;
7270
// Destination account for send blocks
7371
virtual std::optional<nano::account> destination_field () const;
72+
// Link field for state blocks
73+
virtual std::optional<nano::link> link () const;
7474
// Returns the source block hash for open/receive/state blocks that are receives
7575
nano::block_hash source ();
7676
// Source block for open/receive blocks
@@ -344,7 +344,6 @@ class state_block : public nano::block
344344
void block_work_set (uint64_t) override;
345345
nano::block_hash const & previous () const override;
346346
nano::root const & root () const override;
347-
nano::link const & link () const override;
348347
nano::account const & representative () const override;
349348
void serialize (nano::stream &) const override;
350349
bool deserialize (nano::stream &);
@@ -367,6 +366,7 @@ class state_block : public nano::block
367366
public: // State block fields
368367
std::optional<nano::account> account_field () const override;
369368
std::optional<nano::amount> balance_field () const override;
369+
std::optional<nano::link> link () const override;
370370

371371
public: // Logging
372372
void operator() (nano::object_stream &) const override;

nano/nano_node/entry.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ int main (int argc, char * const * argv)
15011501
{
15021502
if ((state_block.hashables.balance == prev_balance && !error_or_pruned) || (node->ledger.pruning && error_or_pruned && block->sideband ().details.is_epoch))
15031503
{
1504-
invalid = validate_message (node->ledger.epoch_signer (block->link ()), hash, block->block_signature ());
1504+
invalid = validate_message (node->ledger.epoch_signer (block->link ().value ()), hash, block->block_signature ());
15051505
}
15061506
}
15071507
}
@@ -1529,12 +1529,12 @@ int main (int argc, char * const * argv)
15291529
}
15301530
else
15311531
{
1532-
if (block->link ().is_zero ())
1532+
if (block->link ().value ().is_zero ())
15331533
{
15341534
// State change
15351535
block_details_error = sideband.details.is_send || sideband.details.is_receive || sideband.details.is_epoch;
15361536
}
1537-
else if (block->balance () == prev_balance.value () && node->ledger.is_epoch_link (block->link ()))
1537+
else if (block->balance () == prev_balance.value () && node->ledger.is_epoch_link (block->link ().value ()))
15381538
{
15391539
// State epoch
15401540
block_details_error = !sideband.details.is_epoch || sideband.details.is_send || sideband.details.is_receive;
@@ -1543,7 +1543,7 @@ int main (int argc, char * const * argv)
15431543
{
15441544
// State receive
15451545
block_details_error = !sideband.details.is_receive || sideband.details.is_send || sideband.details.is_epoch;
1546-
block_details_error |= !node->ledger.block_or_pruned_exists (transaction, block->link ().as_block_hash ());
1546+
block_details_error |= !node->ledger.block_or_pruned_exists (transaction, block->link ().value ().as_block_hash ());
15471547
}
15481548
}
15491549
}
@@ -1557,7 +1557,7 @@ int main (int argc, char * const * argv)
15571557
print_error_message (boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ()));
15581558
}
15591559
// Check link epoch version
1560-
if (sideband.details.is_receive && (!node->ledger.pruning || !node->store.pruned.exists (transaction, block->link ().as_block_hash ())))
1560+
if (sideband.details.is_receive && (!node->ledger.pruning || !node->store.pruned.exists (transaction, block->source ())))
15611561
{
15621562
if (sideband.source_epoch != node->ledger.version (*block))
15631563
{
@@ -1809,7 +1809,7 @@ int main (int argc, char * const * argv)
18091809
std::cout << boost::str (boost::format ("%1% blocks retrieved") % count) << std::endl;
18101810
}
18111811
node.node->block_processor.add (block);
1812-
if (block->type () == nano::block_type::state && block->previous ().is_zero () && source_node->ledger.is_epoch_link (block->link ()))
1812+
if (block->type () == nano::block_type::state && block->previous ().is_zero () && source_node->ledger.is_epoch_link (block->link ().value ()))
18131813
{
18141814
// Epoch open blocks can be rejected without processed pending blocks to account, push it later again
18151815
epoch_open_blocks.push_back (block);

nano/node/blockprocessor.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ nano::block_status nano::block_processor::process_one (store::write_transaction
356356
}
357357
case nano::block_status::gap_source:
358358
{
359-
node.unchecked.put (block->source_field ().value_or (block->link ().as_block_hash ()), block);
359+
release_assert (block->source_field () || block->link ());
360+
node.unchecked.put (block->source_field ().value_or (block->link ().value_or (0).as_block_hash ()), block);
360361
node.stats.inc (nano::stat::type::ledger, nano::stat::detail::gap_source);
361362
break;
362363
}

nano/node/bootstrap_ascending/service.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ void nano::bootstrap_ascending::service::inspect (store::transaction const & tx,
152152
case nano::block_status::gap_source:
153153
{
154154
const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.account (tx, block.previous ()).value ();
155-
const auto source = block.source_field ().value_or (block.link ().as_block_hash ());
155+
const auto source = block.source_field ().value_or (block.link ().value_or (0).as_block_hash ());
156156

157157
// Mark account as blocked because it is missing the source block
158158
accounts.block (account, source);

nano/node/confirmation_height_bounded.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ bool nano::confirmation_height_bounded::iterate (store::read_transaction const &
253253
// Once a receive is cemented, we can cement all blocks above it until the next receive, so store those details for later.
254254
++num_blocks;
255255
auto block = ledger.block (transaction_a, hash);
256-
auto source = block->source_field ().value_or (block->link ().as_block_hash ());
256+
auto source = block->source_field ().value_or (block->link ().value_or (0).as_block_hash ());
257257
if (!source.is_zero () && !ledger.is_epoch_link (source) && ledger.block_exists (transaction_a, source))
258258
{
259259
hit_receive = true;

nano/node/confirmation_height_unbounded.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ void nano::confirmation_height_unbounded::collect_unconfirmed_receive_and_source
212212

213213
if (block)
214214
{
215-
auto source = block->source_field ().value_or (block->link ().as_block_hash ());
215+
auto source = block->source_field ().value_or (block->link ().value_or (0).as_block_hash ());
216216
if (!source.is_zero () && !ledger.is_epoch_link (source) && ledger.block_exists (transaction_a, source))
217217
{
218218
if (!hit_receive && !block_callback_data_a.empty ())

nano/node/ipc/flatbuffers_util.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ std::unique_ptr<nanoapi::BlockStateT> nano::ipc::flatbuffers_builder::from (nano
1111
block->previous = block_a.previous ().to_string ();
1212
block->representative = block_a.representative ().to_account ();
1313
block->balance = block_a.balance ().to_string_dec ();
14-
block->link = block_a.link ().to_string ();
15-
block->link_as_account = block_a.link ().to_account ();
14+
block->link = block_a.link ().value ().to_string ();
15+
block->link_as_account = block_a.link ().value ().to_account ();
1616
block_a.signature.encode_hex (block->signature);
1717
block->work = nano::to_string_hex (block_a.work);
1818

1919
if (is_state_send_a)
2020
{
2121
block->subtype = nanoapi::BlockSubType::BlockSubType_send;
2222
}
23-
else if (block_a.link ().is_zero ())
23+
else if (block_a.link ().value ().is_zero ())
2424
{
2525
block->subtype = nanoapi::BlockSubType::BlockSubType_change;
2626
}

nano/node/json_handler.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,12 @@ uint64_t nano::json_handler::difficulty_ledger (nano::block const & block_a)
411411
{
412412
details.epoch = block_previous->sideband ().details.epoch;
413413
}
414-
auto link (block_a.link ());
415-
if (!link.is_zero () && !details.is_send)
414+
auto link = block_a.link ();
415+
if (link && !details.is_send)
416416
{
417-
auto block_link = node.ledger.block (transaction, link.as_block_hash ());
417+
auto block_link = node.ledger.block (transaction, link.value ().as_block_hash ());
418418
auto account = block_a.account_field ().value (); // Link is non-zero therefore it's a state block and has an account field;
419-
if (block_link != nullptr && node.store.pending.exists (transaction, nano::pending_key (account, link.as_block_hash ())))
419+
if (block_link != nullptr && node.store.pending.exists (transaction, nano::pending_key (account, link.value ().as_block_hash ())))
420420
{
421421
details.epoch = std::max (details.epoch, block_link->sideband ().details.epoch);
422422
details.is_receive = true;
@@ -1224,7 +1224,7 @@ void nano::json_handler::block_confirm ()
12241224
if (auto state = dynamic_cast<nano::state_block *> (block_l.get ()))
12251225
{
12261226
is_state_send = node.ledger.is_send (transaction, *state);
1227-
is_state_epoch = amount.value () == 0 && node.ledger.is_epoch_link (state->link ());
1227+
is_state_epoch = amount.value () == 0 && node.ledger.is_epoch_link (state->link ().value ());
12281228
}
12291229
}
12301230
node.observers.blocks.notify (status, {}, account, amount ? amount.value () : 0, is_state_send, is_state_epoch);
@@ -2522,7 +2522,7 @@ class history_visitor : public nano::block_visitor
25222522
if (raw && accounts_filter.empty ())
25232523
{
25242524
tree.put ("subtype", "epoch");
2525-
tree.put ("account", handler.node.ledger.epoch_signer (block_a.link ()).to_account ());
2525+
tree.put ("account", handler.node.ledger.epoch_signer (block_a.link ().value ()).to_account ());
25262526
}
25272527
}
25282528
else
@@ -3641,7 +3641,7 @@ void nano::json_handler::republish ()
36413641
block = node.ledger.block (transaction, hash);
36423642
if (sources != 0) // Republish source chain
36433643
{
3644-
nano::block_hash source = block->source_field ().value_or (block->link ().as_block_hash ());
3644+
nano::block_hash source = block->source_field ().value_or (block->link ().value_or (0).as_block_hash ());
36453645
auto block_a = node.ledger.block (transaction, source);
36463646
std::vector<nano::block_hash> hashes;
36473647
while (block_a != nullptr && hashes.size () < sources)
@@ -3679,7 +3679,7 @@ void nano::json_handler::republish ()
36793679
while (block_d != nullptr && hash != source)
36803680
{
36813681
hashes.push_back (previous);
3682-
source = block_d->source_field ().value_or (block_d->sideband ().details.is_send ? 0 : block_d->link ().as_block_hash ());
3682+
source = block_d->source_field ().value_or (block_d->sideband ().details.is_send ? 0 : block_d->link ().value_or (0).as_block_hash ());
36833683
previous = block_d->previous ();
36843684
block_d = node.ledger.block (transaction, previous);
36853685
}

nano/node/node.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,13 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons
260260
// Subtype field
261261
else if (block_a->type () == nano::block_type::state)
262262
{
263-
if (block_a->link ().is_zero ())
263+
if (block_a->link ().value ().is_zero ())
264264
{
265265
event.add ("subtype", "change");
266266
}
267267
else if (is_state_epoch_a)
268268
{
269-
debug_assert (amount_a == 0 && node_l->ledger.is_epoch_link (block_a->link ()));
269+
debug_assert (amount_a == 0 && node_l->ledger.is_epoch_link (block_a->link ().value ()));
270270
event.add ("subtype", "epoch");
271271
}
272272
else
@@ -1252,7 +1252,7 @@ void nano::node::process_confirmed_data (store::transaction const & transaction_
12521252
{
12531253
is_state_send_a = true;
12541254
}
1255-
if (amount_a == 0 && network_params.ledger.epochs.is_epoch_link (state->link ()))
1255+
if (amount_a == 0 && network_params.ledger.epochs.is_epoch_link (state->link ().value ()))
12561256
{
12571257
is_state_epoch_a = true;
12581258
}

nano/node/websocket.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1012,13 +1012,13 @@ nano::websocket_server::websocket_server (nano::websocket::config & config_a, na
10121012
}
10131013
else if (block_a->type () == nano::block_type::state)
10141014
{
1015-
if (block_a->link ().is_zero ())
1015+
if (block_a->link ().value ().is_zero ())
10161016
{
10171017
subtype = "change";
10181018
}
10191019
else if (is_state_epoch_a)
10201020
{
1021-
debug_assert (amount_a == 0 && ledger.is_epoch_link (block_a->link ()));
1021+
debug_assert (amount_a == 0 && ledger.is_epoch_link (block_a->link ().value ()));
10221022
subtype = "epoch";
10231023
}
10241024
else

0 commit comments

Comments
 (0)