Skip to content

Commit ef09e55

Browse files
authored
Merge pull request #3284 from nanocurrency/v22rc2_cherry_pick
Cherry picking latest commits from develop.
2 parents 2a3afcb + 9a532b1 commit ef09e55

7 files changed

+137
-98
lines changed

nano/core_test/active_transactions.cpp

+36-92
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ TEST (active_transactions, inactive_votes_cache_existing_vote)
308308
// Insert vote
309309
auto vote1 (std::make_shared<nano::vote> (key.pub, key.prv, 1, std::vector<nano::block_hash> (1, send->hash ())));
310310
node.vote_processor.vote (vote1, std::make_shared<nano::transport::channel_loopback> (node));
311-
ASSERT_TIMELY (5s, election->votes ().size () == 2)
311+
ASSERT_TIMELY (5s, election->votes ().size () == 2);
312312
ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_new));
313313
auto last_vote1 (election->votes ()[key.pub]);
314314
ASSERT_EQ (send->hash (), last_vote1.hash);
@@ -388,49 +388,28 @@ TEST (active_transactions, inactive_votes_cache_election_start)
388388
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
389389
auto & node = *system.add_node (node_config);
390390
nano::block_hash latest (node.latest (nano::dev_genesis_key.pub));
391-
nano::keypair key1, key2, key3, key4, key5;
391+
nano::keypair key1, key2;
392392
nano::send_block_builder send_block_builder;
393393
nano::state_block_builder state_block_builder;
394394
auto send1 = send_block_builder.make_block ()
395395
.previous (latest)
396396
.destination (key1.pub)
397-
.balance (nano::genesis_amount - 2000 * nano::Gxrb_ratio)
397+
.balance (nano::genesis_amount - 5000 * nano::Gxrb_ratio)
398398
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
399399
.work (*system.work.generate (latest))
400400
.build_shared ();
401401
auto send2 = send_block_builder.make_block ()
402402
.previous (send1->hash ())
403403
.destination (key2.pub)
404-
.balance (nano::genesis_amount - 4000 * nano::Gxrb_ratio)
405-
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
406-
.work (*system.work.generate (send1->hash ()))
407-
.build_shared ();
408-
auto send3 = send_block_builder.make_block ()
409-
.previous (send2->hash ())
410-
.destination (key3.pub)
411-
.balance (nano::genesis_amount - 6000 * nano::Gxrb_ratio)
412-
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
413-
.work (*system.work.generate (send2->hash ()))
414-
.build_shared ();
415-
auto send4 = send_block_builder.make_block ()
416-
.previous (send3->hash ())
417-
.destination (key4.pub)
418-
.balance (nano::genesis_amount - 8000 * nano::Gxrb_ratio)
419-
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
420-
.work (*system.work.generate (send3->hash ()))
421-
.build_shared ();
422-
auto send5 = send_block_builder.make_block ()
423-
.previous (send4->hash ())
424-
.destination (key5.pub)
425404
.balance (nano::genesis_amount - 10000 * nano::Gxrb_ratio)
426405
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
427-
.work (*system.work.generate (send4->hash ()))
406+
.work (*system.work.generate (send1->hash ()))
428407
.build_shared ();
429408
auto open1 = state_block_builder.make_block ()
430409
.account (key1.pub)
431410
.previous (0)
432411
.representative (key1.pub)
433-
.balance (2000 * nano::Gxrb_ratio)
412+
.balance (5000 * nano::Gxrb_ratio)
434413
.link (send1->hash ())
435414
.sign (key1.prv, key1.pub)
436415
.work (*system.work.generate (key1.pub))
@@ -439,107 +418,69 @@ TEST (active_transactions, inactive_votes_cache_election_start)
439418
.account (key2.pub)
440419
.previous (0)
441420
.representative (key2.pub)
442-
.balance (2000 * nano::Gxrb_ratio)
421+
.balance (5000 * nano::Gxrb_ratio)
443422
.link (send2->hash ())
444423
.sign (key2.prv, key2.pub)
445424
.work (*system.work.generate (key2.pub))
446425
.build_shared ();
447-
auto open3 = state_block_builder.make_block ()
448-
.account (key3.pub)
449-
.previous (0)
450-
.representative (key3.pub)
451-
.balance (2000 * nano::Gxrb_ratio)
452-
.link (send3->hash ())
453-
.sign (key3.prv, key3.pub)
454-
.work (*system.work.generate (key3.pub))
455-
.build_shared ();
456-
auto open4 = state_block_builder.make_block ()
457-
.account (key4.pub)
458-
.previous (0)
459-
.representative (key4.pub)
460-
.balance (2000 * nano::Gxrb_ratio)
461-
.link (send4->hash ())
462-
.sign (key4.prv, key4.pub)
463-
.work (*system.work.generate (key4.pub))
464-
.build_shared ();
465-
auto open5 = state_block_builder.make_block ()
466-
.account (key5.pub)
467-
.previous (0)
468-
.representative (key5.pub)
469-
.balance (2000 * nano::Gxrb_ratio)
470-
.link (send5->hash ())
471-
.sign (key5.prv, key5.pub)
472-
.work (*system.work.generate (key5.pub))
473-
.build_shared ();
474426
node.block_processor.add (send1);
475427
node.block_processor.add (send2);
476-
node.block_processor.add (send3);
477-
node.block_processor.add (send4);
478-
node.block_processor.add (send5);
479428
node.block_processor.add (open1);
480429
node.block_processor.add (open2);
481-
node.block_processor.add (open3);
482-
node.block_processor.add (open4);
483-
node.block_processor.add (open5);
484430
node.block_processor.flush ();
485-
ASSERT_TIMELY (5s, 11 == node.ledger.cache.block_count);
431+
ASSERT_TIMELY (5s, 5 == node.ledger.cache.block_count);
486432
ASSERT_TRUE (node.active.empty ());
487433
ASSERT_EQ (1, node.ledger.cache.cemented_count);
488434
// These blocks will be processed later
489-
auto send6 = send_block_builder.make_block ()
490-
.previous (send5->hash ())
435+
auto send3 = send_block_builder.make_block ()
436+
.previous (send2->hash ())
491437
.destination (nano::keypair ().pub)
492-
.balance (send5->balance ().number () - 1)
438+
.balance (send2->balance ().number () - 1)
493439
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
494-
.work (*system.work.generate (send5->hash ()))
440+
.work (*system.work.generate (send2->hash ()))
495441
.build_shared ();
496-
auto send7 = send_block_builder.make_block ()
497-
.previous (send6->hash ())
442+
auto send4 = send_block_builder.make_block ()
443+
.previous (send3->hash ())
498444
.destination (nano::keypair ().pub)
499-
.balance (send6->balance ().number () - 1)
445+
.balance (send3->balance ().number () - 1)
500446
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
501-
.work (*system.work.generate (send6->hash ()))
447+
.work (*system.work.generate (send3->hash ()))
502448
.build_shared ();
503449
// Inactive votes
504-
std::vector<nano::block_hash> hashes{ open1->hash (), open2->hash (), open3->hash (), open4->hash (), open5->hash (), send7->hash () };
450+
std::vector<nano::block_hash> hashes{ open1->hash (), open2->hash (), send4->hash () };
505451
auto vote1 (std::make_shared<nano::vote> (key1.pub, key1.prv, 0, hashes));
506452
node.vote_processor.vote (vote1, std::make_shared<nano::transport::channel_loopback> (node));
507-
auto vote2 (std::make_shared<nano::vote> (key2.pub, key2.prv, 0, hashes));
508-
node.vote_processor.vote (vote2, std::make_shared<nano::transport::channel_loopback> (node));
509-
auto vote3 (std::make_shared<nano::vote> (key3.pub, key3.prv, 0, hashes));
510-
node.vote_processor.vote (vote3, std::make_shared<nano::transport::channel_loopback> (node));
511-
auto vote4 (std::make_shared<nano::vote> (key4.pub, key4.prv, 0, hashes));
512-
node.vote_processor.vote (vote4, std::make_shared<nano::transport::channel_loopback> (node));
513-
ASSERT_TIMELY (5s, node.active.inactive_votes_cache_size () == 6);
453+
ASSERT_TIMELY (5s, node.active.inactive_votes_cache_size () == 3);
514454
ASSERT_TRUE (node.active.empty ());
515455
ASSERT_EQ (1, node.ledger.cache.cemented_count);
516-
// 5 votes are required to start election
517-
auto vote5 (std::make_shared<nano::vote> (key5.pub, key5.prv, 0, hashes));
518-
node.vote_processor.vote (vote5, std::make_shared<nano::transport::channel_loopback> (node));
519-
ASSERT_TIMELY (5s, 5 == node.active.size ());
456+
// 2 votes are required to start election (dev network)
457+
auto vote2 (std::make_shared<nano::vote> (key2.pub, key2.prv, 0, hashes));
458+
node.vote_processor.vote (vote2, std::make_shared<nano::transport::channel_loopback> (node));
459+
// Only open1 & open2 blocks elections should start (send4 is missing previous block in ledger)
460+
ASSERT_TIMELY (5s, 2 == node.active.size ());
520461
// Confirm elections with weight quorum
521462
auto vote0 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, std::numeric_limits<uint64_t>::max (), hashes)); // Final vote for confirmation
522463
node.vote_processor.vote (vote0, std::make_shared<nano::transport::channel_loopback> (node));
523464
ASSERT_TIMELY (5s, node.active.empty ());
524-
ASSERT_TIMELY (5s, 11 == node.ledger.cache.cemented_count);
465+
ASSERT_TIMELY (5s, 5 == node.ledger.cache.cemented_count);
525466
// A late block arrival also checks the inactive votes cache
526467
ASSERT_TRUE (node.active.empty ());
527-
auto send7_cache (node.active.find_inactive_votes_cache (send7->hash ()));
528-
ASSERT_EQ (6, send7_cache.voters.size ());
529-
ASSERT_TRUE (send7_cache.status.bootstrap_started);
530-
ASSERT_TRUE (send7_cache.status.confirmed);
531-
ASSERT_TRUE (send7_cache.status.election_started); // already marked even though the block does not exist
532-
node.process_active (send6);
468+
auto send4_cache (node.active.find_inactive_votes_cache (send4->hash ()));
469+
ASSERT_EQ (3, send4_cache.voters.size ());
470+
ASSERT_TRUE (send4_cache.status.bootstrap_started);
471+
ASSERT_TRUE (send4_cache.status.confirmed);
472+
ASSERT_TRUE (send4_cache.status.election_started); // already marked even though the block does not exist
473+
node.process_active (send3);
533474
node.block_processor.flush ();
534475
// An election is started for send6 but does not confirm
535476
ASSERT_TIMELY (5s, 1 == node.active.size ());
536477
node.vote_processor.flush ();
537-
ASSERT_FALSE (node.block_confirmed_or_being_confirmed (node.store.tx_begin_read (), send6->hash ()));
478+
ASSERT_FALSE (node.block_confirmed_or_being_confirmed (node.store.tx_begin_read (), send3->hash ()));
538479
// send7 cannot be voted on but an election should be started from inactive votes
539-
ASSERT_FALSE (node.ledger.dependents_confirmed (node.store.tx_begin_read (), *send7));
540-
node.process_active (send7);
480+
ASSERT_FALSE (node.ledger.dependents_confirmed (node.store.tx_begin_read (), *send4));
481+
node.process_active (send4);
541482
node.block_processor.flush ();
542-
ASSERT_TIMELY (5s, 13 == node.ledger.cache.cemented_count);
483+
ASSERT_TIMELY (5s, 7 == node.ledger.cache.cemented_count);
543484
}
544485

545486
namespace nano
@@ -1046,6 +987,7 @@ TEST (active_transactions, restart_dropped)
1046987
ASSERT_EQ (0, node.active.size ());
1047988
node.process_active (send);
1048989
node.block_processor.flush ();
990+
node.scheduler.flush ();
1049991
ASSERT_EQ (1, node.active.size ());
1050992
ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::election_restart));
1051993
auto ledger_block (node.store.block_get (node.store.tx_begin_read (), send->hash ()));
@@ -1058,6 +1000,7 @@ TEST (active_transactions, restart_dropped)
10581000
// Try to restart election with the same difficulty
10591001
node.process_active (send);
10601002
node.block_processor.flush ();
1003+
node.scheduler.flush ();
10611004
ASSERT_EQ (0, node.active.size ());
10621005
ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::election_restart));
10631006
// Generate even higher difficulty work
@@ -1068,6 +1011,7 @@ TEST (active_transactions, restart_dropped)
10681011
ASSERT_EQ (0, node.active.size ());
10691012
node.process_active (send);
10701013
node.block_processor.flush ();
1014+
node.scheduler.flush ();
10711015
ASSERT_EQ (1, node.active.size ());
10721016
ASSERT_EQ (1, node.ledger.cache.cemented_count);
10731017
ASSERT_EQ (2, node.stats.count (nano::stat::type::election, nano::stat::detail::election_restart));

nano/core_test/confirmation_height.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -304,17 +304,18 @@ TEST (confirmation_height, gap_live)
304304
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
305305
auto node = system.add_node (node_config, node_flags);
306306
node_config.peering_port = nano::get_available_port ();
307+
node_config.receive_minimum = nano::genesis_amount; // Prevent auto-receive & open1/receive1/receive2 blocks conflicts
307308
system.add_node (node_config, node_flags);
308309
nano::keypair destination;
309310
system.wallet (0)->insert_adhoc (nano::dev_genesis_key.prv);
310311
system.wallet (1)->insert_adhoc (destination.prv);
311312

312313
nano::genesis genesis;
313-
auto send1 (std::make_shared<nano::state_block> (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
314+
auto send1 (std::make_shared<nano::state_block> (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount - 1, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
314315
node->work_generate_blocking (*send1);
315-
auto send2 (std::make_shared<nano::state_block> (nano::genesis_account, send1->hash (), nano::genesis_account, nano::genesis_amount - 2 * nano::Gxrb_ratio, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
316+
auto send2 (std::make_shared<nano::state_block> (nano::genesis_account, send1->hash (), nano::genesis_account, nano::genesis_amount - 2, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
316317
node->work_generate_blocking (*send2);
317-
auto send3 (std::make_shared<nano::state_block> (nano::genesis_account, send2->hash (), nano::genesis_account, nano::genesis_amount - 3 * nano::Gxrb_ratio, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
318+
auto send3 (std::make_shared<nano::state_block> (nano::genesis_account, send2->hash (), nano::genesis_account, nano::genesis_amount - 3, destination.pub, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
318319
node->work_generate_blocking (*send3);
319320

320321
auto open1 (std::make_shared<nano::open_block> (send1->hash (), destination.pub, destination.pub, destination.prv, destination.pub, 0));

nano/core_test/conflicts.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ TEST (conflicts, add_existing)
4040
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, 0, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, 0));
4141
send2->sideband_set ({});
4242
node1.scheduler.activate (nano::dev_genesis_key.pub, node1.store.tx_begin_read ());
43+
node1.scheduler.flush ();
4344
auto election1 = node1.active.election (send2->qualified_root ());
45+
ASSERT_NE (nullptr, election1);
4446
ASSERT_EQ (1, node1.active.size ());
4547
auto vote1 (std::make_shared<nano::vote> (key2.pub, key2.prv, 0, send2));
4648
node1.active.vote (vote1);
47-
ASSERT_NE (nullptr, election1);
4849
ASSERT_EQ (2, election1->votes ().size ());
4950
auto votes (election1->votes ());
5051
ASSERT_NE (votes.end (), votes.find (key2.pub));

nano/core_test/node.cpp

+93
Original file line numberDiff line numberDiff line change
@@ -4055,6 +4055,99 @@ TEST (node, rollback_vote_self)
40554055
ASSERT_EQ (fork->hash (), vote->second.hash);
40564056
}
40574057

4058+
TEST (node, rollback_gap_source)
4059+
{
4060+
nano::system system;
4061+
nano::node_config node_config (nano::get_available_port (), system.logging);
4062+
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
4063+
auto & node = *system.add_node (node_config);
4064+
nano::state_block_builder builder;
4065+
nano::keypair key;
4066+
auto send1 = builder.make_block ()
4067+
.account (nano::dev_genesis_key.pub)
4068+
.previous (nano::genesis_hash)
4069+
.representative (nano::dev_genesis_key.pub)
4070+
.link (key.pub)
4071+
.balance (nano::genesis_amount - 1)
4072+
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
4073+
.work (*system.work.generate (nano::genesis_hash))
4074+
.build_shared ();
4075+
auto fork = builder.make_block ()
4076+
.account (key.pub)
4077+
.previous (0)
4078+
.representative (key.pub)
4079+
.link (send1->hash ())
4080+
.balance (1)
4081+
.sign (key.prv, key.pub)
4082+
.work (*system.work.generate (key.pub))
4083+
.build_shared ();
4084+
auto send2 = builder.make_block ()
4085+
.from (*send1)
4086+
.previous (send1->hash ())
4087+
.balance (send1->balance ().number () - 1)
4088+
.link (key.pub)
4089+
.sign (nano::dev_genesis_key.prv, nano::dev_genesis_key.pub)
4090+
.work (*system.work.generate (send1->hash ()))
4091+
.build_shared ();
4092+
auto open = builder.make_block ()
4093+
.from (*fork)
4094+
.link (send2->hash ())
4095+
.sign (key.prv, key.pub)
4096+
.build_shared ();
4097+
ASSERT_EQ (nano::process_result::progress, node.process (*send1).code);
4098+
ASSERT_EQ (nano::process_result::progress, node.process (*fork).code);
4099+
// Node has fork & doesn't have source for correct block open (send2)
4100+
ASSERT_EQ (nullptr, node.block (send2->hash ()));
4101+
// Start election for fork
4102+
nano::blocks_confirm (node, { fork });
4103+
{
4104+
auto election = node.active.election (fork->qualified_root ());
4105+
ASSERT_NE (nullptr, election);
4106+
// Process conflicting block for election
4107+
node.process_active (open);
4108+
node.block_processor.flush ();
4109+
ASSERT_EQ (2, election->blocks ().size ());
4110+
ASSERT_EQ (1, election->votes ().size ());
4111+
// Confirm open
4112+
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, std::numeric_limits<uint64_t>::max (), std::vector<nano::block_hash> (1, open->hash ())));
4113+
node.vote_processor.vote (vote1, std::make_shared<nano::transport::channel_loopback> (node));
4114+
ASSERT_TIMELY (5s, election->votes ().size () == 2);
4115+
ASSERT_TIMELY (3s, election->confirmed ());
4116+
}
4117+
// Wait for the rollback (attempt to replace fork with open)
4118+
ASSERT_TIMELY (5s, node.stats.count (nano::stat::type::rollback, nano::stat::detail::open) == 1);
4119+
ASSERT_TIMELY (5s, node.active.empty ());
4120+
// But replacing is not possible (missing source block - send2)
4121+
node.block_processor.flush ();
4122+
ASSERT_EQ (nullptr, node.block (open->hash ()));
4123+
ASSERT_EQ (nullptr, node.block (fork->hash ()));
4124+
// Fork can be returned by some other forked node or attacker
4125+
node.process_active (fork);
4126+
node.block_processor.flush ();
4127+
ASSERT_NE (nullptr, node.block (fork->hash ()));
4128+
// With send2 block in ledger election can start again to remove fork block
4129+
ASSERT_EQ (nano::process_result::progress, node.process (*send2).code);
4130+
nano::blocks_confirm (node, { fork });
4131+
{
4132+
auto election = node.active.election (fork->qualified_root ());
4133+
ASSERT_NE (nullptr, election);
4134+
// Process conflicting block for election
4135+
node.process_active (open);
4136+
node.block_processor.flush ();
4137+
ASSERT_EQ (2, election->blocks ().size ());
4138+
// Confirm open (again)
4139+
auto vote1 (std::make_shared<nano::vote> (nano::dev_genesis_key.pub, nano::dev_genesis_key.prv, std::numeric_limits<uint64_t>::max (), std::vector<nano::block_hash> (1, open->hash ())));
4140+
node.vote_processor.vote (vote1, std::make_shared<nano::transport::channel_loopback> (node));
4141+
ASSERT_TIMELY (5s, election->votes ().size () == 2);
4142+
}
4143+
// Wait for new rollback
4144+
ASSERT_TIMELY (5s, node.stats.count (nano::stat::type::rollback, nano::stat::detail::open) == 2);
4145+
// Now fork block should be replaced with open
4146+
node.block_processor.flush ();
4147+
ASSERT_NE (nullptr, node.block (open->hash ()));
4148+
ASSERT_EQ (nullptr, node.block (fork->hash ()));
4149+
}
4150+
40584151
// Confirm a complex dependency graph starting from the first block
40594152
TEST (node, dependency_graph)
40604153
{

nano/node/election.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ void nano::election::confirm_once (nano::unique_lock<nano::mutex> & lock_a, nano
5353
status.type = type_a;
5454
auto const status_l = status;
5555
lock_a.unlock ();
56-
node.active.add_recently_confirmed (status_l.winner->qualified_root (), status_l.winner->hash ());
5756
node.process_confirmed (status_l);
5857
node.background ([node_l = node.shared (), status_l, confirmation_action_l = confirmation_action] () {
5958
if (confirmation_action_l)

nano/node/node.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,7 @@ void nano::node::process_confirmed (nano::election_status const & status_a, uint
13531353
const auto num_iters = (config.block_processor_batch_max_time / network_params.node.process_confirmed_interval) * 4;
13541354
if (auto block_l = ledger.store.block_get (ledger.store.tx_begin_read (), hash))
13551355
{
1356+
active.add_recently_confirmed (block_l->qualified_root (), hash);
13561357
confirmation_height_processor.add (block_l);
13571358
}
13581359
else if (iteration_a < num_iters)

nano/node/nodeconfig.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const
118118
work_peers_l->push_back (boost::str (boost::format ("%1%:%2%") % i->first % i->second));
119119
}
120120

121-
auto preconfigured_peers_l (toml.create_array ("preconfigured_peers", "A list of \"address\" (hostname or ip address) entries to identify preconfigured peers."));
121+
auto preconfigured_peers_l (toml.create_array ("preconfigured_peers", "A list of \"address\" (hostname or ipv6 notation ip address) entries to identify preconfigured peers."));
122122
for (auto i (preconfigured_peers.begin ()), n (preconfigured_peers.end ()); i != n; ++i)
123123
{
124124
preconfigured_peers_l->push_back (*i);

0 commit comments

Comments
 (0)