Remove node v18 and earlier upgrade support (#2770)
* Remove node v18 and earlier upgrade support * Remove DBv13 upgrade and add tests for checking upgrade * block_account_computed no longer used
This commit is contained in:
		
					parent
					
						
							
								bc805827bc
							
						
					
				
			
			
				commit
				
					
						7c9614ecf4
					
				
			
		
					 30 changed files with 98 additions and 2576 deletions
				
			
		| 
						 | 
					@ -38,7 +38,6 @@ add_executable (core_test
 | 
				
			||||||
	timer.cpp
 | 
						timer.cpp
 | 
				
			||||||
	uint256_union.cpp
 | 
						uint256_union.cpp
 | 
				
			||||||
	utility.cpp
 | 
						utility.cpp
 | 
				
			||||||
	versioning.cpp
 | 
					 | 
				
			||||||
	vote_processor.cpp
 | 
						vote_processor.cpp
 | 
				
			||||||
	wallet.cpp
 | 
						wallet.cpp
 | 
				
			||||||
	wallets.cpp
 | 
						wallets.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,11 +27,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace
 | 
					namespace
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
void modify_account_info_to_v13 (nano::mdb_store & store, nano::transaction const & transaction_a, nano::account const & account_a, nano::block_hash const & rep_block);
 | 
					 | 
				
			||||||
void modify_account_info_to_v14 (nano::mdb_store & store, nano::transaction const & transaction_a, nano::account const & account_a, uint64_t confirmation_height, nano::block_hash const & rep_block);
 | 
					void modify_account_info_to_v14 (nano::mdb_store & store, nano::transaction const & transaction_a, nano::account const & account_a, uint64_t confirmation_height, nano::block_hash const & rep_block);
 | 
				
			||||||
void modify_genesis_account_info_to_v5 (nano::mdb_store & store, nano::transaction const & transaction_a);
 | 
					 | 
				
			||||||
void modify_confirmation_height_to_v15 (nano::mdb_store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height);
 | 
					void modify_confirmation_height_to_v15 (nano::mdb_store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height);
 | 
				
			||||||
void write_sideband_v12 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block & block_a, nano::block_hash const & successor_a, MDB_dbi db_a);
 | 
					 | 
				
			||||||
void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a);
 | 
					void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a);
 | 
				
			||||||
void write_sideband_v15 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a);
 | 
					void write_sideband_v15 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -653,6 +650,50 @@ TEST (block_store, latest_find)
 | 
				
			||||||
	ASSERT_EQ (second, find3);
 | 
						ASSERT_EQ (second, find3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST (mdb_block_store, supported_version_upgrades)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Check that upgrading from an unsupported version is not supported
 | 
				
			||||||
 | 
						auto path (nano::unique_path ());
 | 
				
			||||||
 | 
						nano::genesis genesis;
 | 
				
			||||||
 | 
						nano::logger_mt logger;
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::mdb_store store (logger, path);
 | 
				
			||||||
 | 
							nano::stat stats;
 | 
				
			||||||
 | 
							nano::ledger ledger (store, stats);
 | 
				
			||||||
 | 
							auto transaction (store.tx_begin_write ());
 | 
				
			||||||
 | 
							store.initialize (transaction, genesis, ledger.cache);
 | 
				
			||||||
 | 
							// Lower the database to the max version unsupported for upgrades
 | 
				
			||||||
 | 
							store.version_put (transaction, store.minimum_version - 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Upgrade should fail
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::mdb_store store (logger, path);
 | 
				
			||||||
 | 
							ASSERT_TRUE (store.init_error ());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto path1 (nano::unique_path ());
 | 
				
			||||||
 | 
						// Now try with the minimum version
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::mdb_store store (logger, path1);
 | 
				
			||||||
 | 
							nano::stat stats;
 | 
				
			||||||
 | 
							nano::ledger ledger (store, stats);
 | 
				
			||||||
 | 
							auto transaction (store.tx_begin_write ());
 | 
				
			||||||
 | 
							store.initialize (transaction, genesis, ledger.cache);
 | 
				
			||||||
 | 
							// Lower the database version to the minimum version supported for upgrade.
 | 
				
			||||||
 | 
							store.version_put (transaction, store.minimum_version);
 | 
				
			||||||
 | 
							store.confirmation_height_del (transaction, nano::genesis_account);
 | 
				
			||||||
 | 
							ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1));
 | 
				
			||||||
 | 
							modify_account_info_to_v14 (store, transaction, nano::genesis_account, 1, nano::genesis_hash);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Upgrade should work
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::mdb_store store (logger, path1);
 | 
				
			||||||
 | 
							ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (mdb_block_store, bad_path)
 | 
					TEST (mdb_block_store, bad_path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
| 
						 | 
					@ -849,127 +890,6 @@ TEST (block_store, sequence_increment)
 | 
				
			||||||
	ASSERT_EQ (31, vote6->sequence);
 | 
						ASSERT_EQ (31, vote6->sequence);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (mdb_block_store, upgrade_v2_v3)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::keypair key1;
 | 
					 | 
				
			||||||
	nano::keypair key2;
 | 
					 | 
				
			||||||
	nano::block_hash change_hash;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_TRUE (!store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		nano::genesis genesis;
 | 
					 | 
				
			||||||
		auto hash (genesis.hash ());
 | 
					 | 
				
			||||||
		nano::stat stats;
 | 
					 | 
				
			||||||
		nano::ledger ledger (store, stats);
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
		nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
		nano::change_block change (hash, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (hash));
 | 
					 | 
				
			||||||
		change_hash = change.hash ();
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code);
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, ledger.weight (nano::test_genesis_key.pub));
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::genesis_amount, ledger.weight (key1.pub));
 | 
					 | 
				
			||||||
		store.version_put (transaction, 2);
 | 
					 | 
				
			||||||
		ledger.cache.rep_weights.representation_put (key1.pub, 7);
 | 
					 | 
				
			||||||
		ASSERT_EQ (7, ledger.weight (key1.pub));
 | 
					 | 
				
			||||||
		ASSERT_EQ (2, store.version_get (transaction));
 | 
					 | 
				
			||||||
		ledger.cache.rep_weights.representation_put (key2.pub, 6);
 | 
					 | 
				
			||||||
		ASSERT_EQ (6, ledger.weight (key2.pub));
 | 
					 | 
				
			||||||
		nano::account_info info;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.account_get (transaction, nano::test_genesis_key.pub, info));
 | 
					 | 
				
			||||||
		auto rep_block = ledger.representative (transaction, ledger.latest (transaction, nano::test_genesis_key.pub));
 | 
					 | 
				
			||||||
		nano::account_info_v5 info_old (info.head, rep_block, info.open_block, info.balance, info.modified);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (nano::test_genesis_key.pub), nano::mdb_val (sizeof (info_old), &info_old), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (status, 0);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	nano::stat stats;
 | 
					 | 
				
			||||||
	nano::ledger ledger (store, stats);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store.init_error ());
 | 
					 | 
				
			||||||
	ASSERT_LT (2, store.version_get (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::genesis_amount, ledger.weight (key1.pub));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, ledger.weight (key2.pub));
 | 
					 | 
				
			||||||
	nano::account_info info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.account_get (transaction, nano::test_genesis_key.pub, info));
 | 
					 | 
				
			||||||
	ASSERT_EQ (change_hash, ledger.representative (transaction, ledger.latest (transaction, nano::test_genesis_key.pub)));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v3_v4)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::keypair key1;
 | 
					 | 
				
			||||||
	nano::keypair key2;
 | 
					 | 
				
			||||||
	nano::keypair key3;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 3);
 | 
					 | 
				
			||||||
		nano::pending_info_v3 info (key1.pub, 100, key2.pub);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.pending_v0, nano::mdb_val (key3.pub), nano::mdb_val (sizeof (info), &info), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, status);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	nano::stat stats;
 | 
					 | 
				
			||||||
	nano::ledger ledger (store, stats);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	ASSERT_LT (3, store.version_get (transaction));
 | 
					 | 
				
			||||||
	nano::pending_key key (key2.pub, reinterpret_cast<nano::block_hash const &> (key3.pub));
 | 
					 | 
				
			||||||
	nano::pending_info info;
 | 
					 | 
				
			||||||
	auto error (store.pending_get (transaction, key, info));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
					 | 
				
			||||||
	ASSERT_EQ (key1.pub, info.source);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::amount (100), info.amount);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::epoch::epoch_0, info.epoch);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v4_v5)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::block_hash genesis_hash (0);
 | 
					 | 
				
			||||||
	nano::block_hash hash (0);
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		nano::genesis genesis;
 | 
					 | 
				
			||||||
		nano::stat stats;
 | 
					 | 
				
			||||||
		nano::ledger ledger (store, stats);
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 4);
 | 
					 | 
				
			||||||
		nano::account_info info;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.account_get (transaction, nano::test_genesis_key.pub, info));
 | 
					 | 
				
			||||||
		nano::keypair key0;
 | 
					 | 
				
			||||||
		nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
		nano::send_block block0 (info.head, key0.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (info.head));
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block0).code);
 | 
					 | 
				
			||||||
		hash = block0.hash ();
 | 
					 | 
				
			||||||
		auto original (store.block_get (transaction, info.head));
 | 
					 | 
				
			||||||
		genesis_hash = info.head;
 | 
					 | 
				
			||||||
		store.block_successor_clear (transaction, info.head);
 | 
					 | 
				
			||||||
		ASSERT_TRUE (store.block_successor (transaction, genesis_hash).is_zero ());
 | 
					 | 
				
			||||||
		modify_genesis_account_info_to_v5 (store, transaction);
 | 
					 | 
				
			||||||
		// The pending send needs to be the correct version
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.pending_v0, nano::mdb_val (nano::pending_key (key0.pub, block0.hash ())), nano::mdb_val (nano::pending_info_v14 (nano::genesis_account, nano::Gxrb_ratio, nano::epoch::epoch_0)), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (status, MDB_SUCCESS);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (hash, store.block_successor (transaction, genesis_hash));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (block_store, block_random)
 | 
					TEST (block_store, block_random)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
| 
						 | 
					@ -987,56 +907,6 @@ TEST (block_store, block_random)
 | 
				
			||||||
	ASSERT_EQ (*block, *genesis.open);
 | 
						ASSERT_EQ (*block, *genesis.open);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (mdb_block_store, upgrade_v5_v6)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		nano::genesis genesis;
 | 
					 | 
				
			||||||
		nano::ledger_cache ledger_cache;
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger_cache);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 5);
 | 
					 | 
				
			||||||
		modify_genesis_account_info_to_v5 (store, transaction);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	nano::account_info info;
 | 
					 | 
				
			||||||
	store.account_get (transaction, nano::test_genesis_key.pub, info);
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, info.block_count);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v6_v7)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		nano::genesis genesis;
 | 
					 | 
				
			||||||
		nano::ledger_cache ledger_cache;
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger_cache);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 6);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, nano::genesis_hash);
 | 
					 | 
				
			||||||
		auto send1 (std::make_shared<nano::send_block> (0, 0, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
 | 
					 | 
				
			||||||
		store.unchecked_put (transaction, send1->hash (), send1);
 | 
					 | 
				
			||||||
		store.flush (transaction);
 | 
					 | 
				
			||||||
		ASSERT_NE (store.unchecked_end (), store.unchecked_begin (transaction));
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (store.unchecked_end (), store.unchecked_begin (transaction));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Databases need to be dropped in order to convert to dupsort compatible
 | 
					// Databases need to be dropped in order to convert to dupsort compatible
 | 
				
			||||||
TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table
 | 
					TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1082,35 +952,6 @@ TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort ta
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (mdb_block_store, upgrade_v7_v8)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked, 1));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE, &store.unchecked));
 | 
					 | 
				
			||||||
		store.version_put (transaction, 7);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	auto send1 (std::make_shared<nano::send_block> (0, 0, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
 | 
					 | 
				
			||||||
	auto send2 (std::make_shared<nano::send_block> (1, 0, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
 | 
					 | 
				
			||||||
	store.unchecked_put (transaction, send1->hash (), send1);
 | 
					 | 
				
			||||||
	store.unchecked_put (transaction, send1->hash (), send2);
 | 
					 | 
				
			||||||
	store.flush (transaction);
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto iterator1 (store.unchecked_begin (transaction));
 | 
					 | 
				
			||||||
		++iterator1;
 | 
					 | 
				
			||||||
		ASSERT_NE (store.unchecked_end (), iterator1);
 | 
					 | 
				
			||||||
		++iterator1;
 | 
					 | 
				
			||||||
		ASSERT_EQ (store.unchecked_end (), iterator1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (block_store, sequence_flush)
 | 
					TEST (block_store, sequence_flush)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
						auto path (nano::unique_path ());
 | 
				
			||||||
| 
						 | 
					@ -1148,31 +989,6 @@ TEST (block_store, sequence_flush_by_hash)
 | 
				
			||||||
	ASSERT_EQ (*seq3, *vote1);
 | 
						ASSERT_EQ (*seq3, *vote1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Upgrading tracking block sequence numbers to whole vote.
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v8_v9)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::keypair key;
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.vote, 1));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "sequence", MDB_CREATE, &store.vote));
 | 
					 | 
				
			||||||
		uint64_t sequence (10);
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, mdb_put (store.env.tx (transaction), store.vote, nano::mdb_val (key.pub), nano::mdb_val (sizeof (sequence), &sequence), 0));
 | 
					 | 
				
			||||||
		store.version_put (transaction, 8);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_LT (8, store.version_get (transaction));
 | 
					 | 
				
			||||||
	auto vote (store.vote_get (transaction, key.pub));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, vote);
 | 
					 | 
				
			||||||
	ASSERT_EQ (10, vote->sequence);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (block_store, state_block)
 | 
					TEST (block_store, state_block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
| 
						 | 
					@ -1205,216 +1021,6 @@ TEST (block_store, state_block)
 | 
				
			||||||
	ASSERT_EQ (0, count2.state);
 | 
						ASSERT_EQ (0, count2.state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (mdb_block_store, upgrade_sideband_genesis)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
		nano::ledger_cache ledger_cache;
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger_cache);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, nano::genesis_hash);
 | 
					 | 
				
			||||||
		auto genesis_block (store.block_get (transaction, genesis.hash ()));
 | 
					 | 
				
			||||||
		ASSERT_NE (nullptr, genesis_block);
 | 
					 | 
				
			||||||
		ASSERT_EQ (1, genesis_block->sideband ().height);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1));
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, *genesis_block, 0, store.open_blocks);
 | 
					 | 
				
			||||||
		nano::block_sideband_v14 sideband1;
 | 
					 | 
				
			||||||
		auto genesis_block2 (store.block_get_v14 (transaction, genesis.hash (), &sideband1));
 | 
					 | 
				
			||||||
		ASSERT_NE (nullptr, genesis_block);
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, sideband1.height);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (store.full_sideband (transaction));
 | 
					 | 
				
			||||||
	auto genesis_block (store.block_get (transaction, genesis.hash ()));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, genesis_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, genesis_block->sideband ().height);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_sideband_two_blocks)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	nano::block_hash hash2;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		nano::stat stat;
 | 
					 | 
				
			||||||
		nano::ledger ledger (store, stat);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
		nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
		nano::state_block block (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ()));
 | 
					 | 
				
			||||||
		hash2 = block.hash ();
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block).code);
 | 
					 | 
				
			||||||
		store.block_del (transaction, hash2, block.type ());
 | 
					 | 
				
			||||||
		mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1);
 | 
					 | 
				
			||||||
		mdb_dbi_open (store.env.tx (transaction), "state", MDB_CREATE, &store.state_blocks_v0);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, *genesis.open, hash2, store.open_blocks);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, block, 0, store.state_blocks_v0);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, hash2);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.pending_v0, nano::mdb_val (nano::pending_key (nano::test_genesis_key.pub, block.hash ())), nano::mdb_val (nano::pending_info_v14 (nano::genesis_account, nano::Gxrb_ratio, nano::epoch::epoch_0)), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (status, MDB_SUCCESS);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (store.full_sideband (transaction));
 | 
					 | 
				
			||||||
	auto genesis_block (store.block_get (transaction, genesis.hash ()));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, genesis_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, genesis_block->sideband ().height);
 | 
					 | 
				
			||||||
	auto block2 (store.block_get (transaction, hash2));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, block2);
 | 
					 | 
				
			||||||
	ASSERT_EQ (2, block2->sideband ().height);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_sideband_two_accounts)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	nano::block_hash hash2;
 | 
					 | 
				
			||||||
	nano::block_hash hash3;
 | 
					 | 
				
			||||||
	nano::keypair key;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		nano::stat stat;
 | 
					 | 
				
			||||||
		nano::ledger ledger (store, stat);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
		nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
		nano::state_block block1 (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ()));
 | 
					 | 
				
			||||||
		hash2 = block1.hash ();
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block1).code);
 | 
					 | 
				
			||||||
		nano::state_block block2 (key.pub, 0, nano::test_genesis_key.pub, nano::Gxrb_ratio, hash2, key.prv, key.pub, *pool.generate (key.pub));
 | 
					 | 
				
			||||||
		hash3 = block2.hash ();
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block2).code);
 | 
					 | 
				
			||||||
		store.block_del (transaction, hash2, block1.type ());
 | 
					 | 
				
			||||||
		store.block_del (transaction, hash3, block2.type ());
 | 
					 | 
				
			||||||
		mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1);
 | 
					 | 
				
			||||||
		mdb_dbi_open (store.env.tx (transaction), "state", MDB_CREATE, &store.state_blocks_v0);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, *genesis.open, hash2, store.open_blocks);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, block1, 0, store.state_blocks_v0);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, block2, 0, store.state_blocks_v0);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, hash2);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, block2.account (), hash3);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, key.pub);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (store.full_sideband (transaction));
 | 
					 | 
				
			||||||
	auto genesis_block (store.block_get (transaction, genesis.hash ()));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, genesis_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, genesis_block->sideband ().height);
 | 
					 | 
				
			||||||
	auto block2 (store.block_get (transaction, hash2));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, block2);
 | 
					 | 
				
			||||||
	ASSERT_EQ (2, block2->sideband ().height);
 | 
					 | 
				
			||||||
	auto block3 (store.block_get (transaction, hash3));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, block3);
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, block3->sideband ().height);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, insert_after_legacy)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, nano::unique_path ());
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	nano::stat stat;
 | 
					 | 
				
			||||||
	nano::ledger ledger (store, stat);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
	store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
	mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1);
 | 
					 | 
				
			||||||
	write_sideband_v12 (store, transaction, *genesis.open, 0, store.open_blocks);
 | 
					 | 
				
			||||||
	nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
	nano::state_block block (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ()));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block).code);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Account for an open block should be retrievable
 | 
					 | 
				
			||||||
TEST (mdb_block_store, legacy_account_computed)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, nano::unique_path ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!store.init_error ());
 | 
					 | 
				
			||||||
	nano::stat stats;
 | 
					 | 
				
			||||||
	nano::ledger ledger (store, stats);
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
	store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
	mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1);
 | 
					 | 
				
			||||||
	write_sideband_v12 (store, transaction, *genesis.open, 0, store.open_blocks);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::genesis_account, ledger.account (transaction, genesis.hash ()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_sideband_epoch)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	bool error (false);
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	nano::block_hash hash2;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::work_pool pool (std::numeric_limits<unsigned>::max ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (error);
 | 
					 | 
				
			||||||
		nano::stat stat;
 | 
					 | 
				
			||||||
		nano::ledger ledger (store, stat);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 11);
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger.cache);
 | 
					 | 
				
			||||||
		nano::state_block block1 (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ()));
 | 
					 | 
				
			||||||
		hash2 = block1.hash ();
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1));
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block1).code);
 | 
					 | 
				
			||||||
		ASSERT_EQ (nano::epoch::epoch_1, store.block_version (transaction, hash2));
 | 
					 | 
				
			||||||
		store.block_del (transaction, hash2, block1.type ());
 | 
					 | 
				
			||||||
		store.block_del (transaction, genesis.open->hash (), genesis.open->type ());
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, *genesis.open, hash2, store.open_blocks);
 | 
					 | 
				
			||||||
		write_sideband_v12 (store, transaction, block1, 0, store.state_blocks_v1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		nano::mdb_val value;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.state_blocks_v1, nano::mdb_val (hash2), value));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.open_blocks, nano::mdb_val (nano::genesis_hash), value));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1));
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, hash2);
 | 
					 | 
				
			||||||
		store.account_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	nano::stat stat;
 | 
					 | 
				
			||||||
	nano::ledger ledger (store, stat);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (store.full_sideband (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::epoch::epoch_1, store.block_version (transaction, hash2));
 | 
					 | 
				
			||||||
	auto block1 (store.block_get (transaction, hash2));
 | 
					 | 
				
			||||||
	ASSERT_NE (0, block1->sideband ().height);
 | 
					 | 
				
			||||||
	nano::state_block block2 (nano::test_genesis_key.pub, hash2, nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (hash2));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block2).code);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::epoch::epoch_1, store.block_version (transaction, block2.hash ()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, sideband_height)
 | 
					TEST (mdb_block_store, sideband_height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
| 
						 | 
					@ -1602,57 +1208,6 @@ TEST (block_store, online_weight)
 | 
				
			||||||
	ASSERT_EQ (store->online_weight_end (), store->online_weight_begin (transaction));
 | 
						ASSERT_EQ (store->online_weight_end (), store->online_weight_begin (transaction));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adding confirmation height to accounts
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v13_v14)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		nano::ledger_cache ledger_cache;
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger_cache);
 | 
					 | 
				
			||||||
		nano::account_info account_info;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.account_get (transaction, nano::genesis_account, account_info));
 | 
					 | 
				
			||||||
		store.version_put (transaction, 13);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, nano::genesis_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// This should fail as sizes are no longer correct for account_info_v14
 | 
					 | 
				
			||||||
		nano::mdb_val value;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (nano::genesis_account), value));
 | 
					 | 
				
			||||||
		nano::account_info_v14 info;
 | 
					 | 
				
			||||||
		ASSERT_NE (value.size (), info.db_size ());
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Now do the upgrade
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	auto error (false);
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Size of account_info should now equal that set in db
 | 
					 | 
				
			||||||
	nano::mdb_val value;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (nano::genesis_account), value));
 | 
					 | 
				
			||||||
	nano::account_info info;
 | 
					 | 
				
			||||||
	ASSERT_EQ (value.size (), info.db_size ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Confirmation height should exist and be correct
 | 
					 | 
				
			||||||
	nano::confirmation_height_info confirmation_height_info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.confirmation_height_get (transaction, nano::genesis_account, confirmation_height_info));
 | 
					 | 
				
			||||||
	ASSERT_EQ (confirmation_height_info.height, 1);
 | 
					 | 
				
			||||||
	ASSERT_EQ (confirmation_height_info.frontier, genesis.hash ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Test deleting node ID
 | 
					 | 
				
			||||||
	nano::uint256_union node_id_mdb_key (3);
 | 
					 | 
				
			||||||
	auto error_node_id (mdb_get (store.env.tx (transaction), store.meta, nano::mdb_val (node_id_mdb_key), value));
 | 
					 | 
				
			||||||
	ASSERT_EQ (error_node_id, MDB_NOTFOUND);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ASSERT_LT (13, store.version_get (transaction));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_v14_v15)
 | 
					TEST (mdb_block_store, upgrade_v14_v15)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// Extract confirmation height to a separate database
 | 
						// Extract confirmation height to a separate database
 | 
				
			||||||
| 
						 | 
					@ -1676,7 +1231,7 @@ TEST (mdb_block_store, upgrade_v14_v15)
 | 
				
			||||||
		ASSERT_FALSE (store.confirmation_height_get (transaction, nano::genesis_account, confirmation_height_info));
 | 
							ASSERT_FALSE (store.confirmation_height_get (transaction, nano::genesis_account, confirmation_height_info));
 | 
				
			||||||
		ASSERT_EQ (confirmation_height_info.height, 1);
 | 
							ASSERT_EQ (confirmation_height_info.height, 1);
 | 
				
			||||||
		ASSERT_EQ (confirmation_height_info.frontier, genesis.hash ());
 | 
							ASSERT_EQ (confirmation_height_info.frontier, genesis.hash ());
 | 
				
			||||||
		// These databases get remove after an upgrade, so readd them
 | 
							// These databases get removed after an upgrade, so readd them
 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1));
 | 
							ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1));
 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1));
 | 
							ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1));
 | 
				
			||||||
		ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "pending_v1", MDB_CREATE, &store.pending_v1));
 | 
							ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "pending_v1", MDB_CREATE, &store.pending_v1));
 | 
				
			||||||
| 
						 | 
					@ -1714,9 +1269,8 @@ TEST (mdb_block_store, upgrade_v14_v15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now do the upgrade
 | 
						// Now do the upgrade
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
	auto error (false);
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
						nano::mdb_store store (logger, path);
 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
						ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
						auto transaction (store.tx_begin_read ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Size of account_info should now equal that set in db
 | 
						// Size of account_info should now equal that set in db
 | 
				
			||||||
| 
						 | 
					@ -1783,9 +1337,8 @@ TEST (mdb_block_store, upgrade_v15_v16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now do the upgrade
 | 
						// Now do the upgrade
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
	auto error (false);
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
						nano::mdb_store store (logger, path);
 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
						ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
						auto transaction (store.tx_begin_read ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The representation table should now be deleted
 | 
						// The representation table should now be deleted
 | 
				
			||||||
| 
						 | 
					@ -1827,9 +1380,8 @@ TEST (mdb_block_store, upgrade_v16_v17)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Now do the upgrade
 | 
							// Now do the upgrade
 | 
				
			||||||
		nano::logger_mt logger;
 | 
							nano::logger_mt logger;
 | 
				
			||||||
		auto error (false);
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
							nano::mdb_store store (logger, path);
 | 
				
			||||||
		ASSERT_FALSE (error);
 | 
							ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
		auto transaction (store.tx_begin_read ());
 | 
							auto transaction (store.tx_begin_read ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nano::confirmation_height_info confirmation_height_info;
 | 
							nano::confirmation_height_info confirmation_height_info;
 | 
				
			||||||
| 
						 | 
					@ -1911,9 +1463,8 @@ TEST (mdb_block_store, upgrade_v17_v18)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now do the upgrade
 | 
						// Now do the upgrade
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
	auto error (false);
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
						nano::mdb_store store (logger, path);
 | 
				
			||||||
	ASSERT_FALSE (error);
 | 
						ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
						auto transaction (store.tx_begin_read ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Size of state block should equal that set in db (no change)
 | 
						// Size of state block should equal that set in db (no change)
 | 
				
			||||||
| 
						 | 
					@ -2064,7 +1615,7 @@ TEST (mdb_block_store, upgrade_backup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now do the upgrade and confirm that backup is saved
 | 
						// Now do the upgrade and confirm that backup is saved
 | 
				
			||||||
	nano::logger_mt logger;
 | 
						nano::logger_mt logger;
 | 
				
			||||||
	nano::mdb_store store (logger, path, nano::txn_tracking_config{}, std::chrono::seconds (5), nano::lmdb_config{}, 512, true);
 | 
						nano::mdb_store store (logger, path, nano::txn_tracking_config{}, std::chrono::seconds (5), nano::lmdb_config{}, true);
 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
						ASSERT_FALSE (store.init_error ());
 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
						auto transaction (store.tx_begin_read ());
 | 
				
			||||||
	ASSERT_LT (14, store.version_get (transaction));
 | 
						ASSERT_LT (14, store.version_get (transaction));
 | 
				
			||||||
| 
						 | 
					@ -2118,54 +1669,6 @@ TEST (block_store, confirmation_height)
 | 
				
			||||||
	ASSERT_EQ (confirmation_height_info.frontier, nano::block_hash (0));
 | 
						ASSERT_EQ (confirmation_height_info.frontier, nano::block_hash (0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Upgrade many accounts and check they all have a confirmation height of 0 (except genesis which should have 1)
 | 
					 | 
				
			||||||
TEST (mdb_block_store, upgrade_confirmation_height_many)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto error (false);
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	auto total_num_accounts = 1000; // Includes the genesis account
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (error);
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.version_put (transaction, 13);
 | 
					 | 
				
			||||||
		nano::ledger_cache ledger_cache;
 | 
					 | 
				
			||||||
		store.initialize (transaction, genesis, ledger_cache);
 | 
					 | 
				
			||||||
		modify_account_info_to_v13 (store, transaction, nano::genesis_account, nano::genesis_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Add many accounts
 | 
					 | 
				
			||||||
		for (auto i = 0; i < total_num_accounts - 1; ++i)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			nano::account account (i);
 | 
					 | 
				
			||||||
			nano::open_block open (1, nano::genesis_account, 3, nullptr);
 | 
					 | 
				
			||||||
			open.sideband_set ({});
 | 
					 | 
				
			||||||
			store.block_put (transaction, open.hash (), open);
 | 
					 | 
				
			||||||
			nano::account_info_v13 account_info_v13 (open.hash (), open.hash (), open.hash (), 3, 4, 1, nano::epoch::epoch_0);
 | 
					 | 
				
			||||||
			auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (account), nano::mdb_val (account_info_v13), 0));
 | 
					 | 
				
			||||||
			ASSERT_EQ (status, 0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		store.confirmation_height_del (transaction, nano::genesis_account);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ASSERT_EQ (store.count (transaction, store.accounts_v0), total_num_accounts);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Loop over them all and confirm they all have the correct confirmation heights
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, path);
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (store.account_count (transaction), total_num_accounts);
 | 
					 | 
				
			||||||
	ASSERT_EQ (store.confirmation_height_count (transaction), total_num_accounts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (auto i (store.confirmation_height_begin (transaction)), n (store.confirmation_height_end ()); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ASSERT_EQ (i->second.height, (i->first == nano::genesis_account) ? 1 : 0);
 | 
					 | 
				
			||||||
		ASSERT_EQ (i->second.frontier, (i->first == nano::genesis_account) ? genesis.hash () : nano::block_hash (0));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ledger versions are not forward compatible
 | 
					// Ledger versions are not forward compatible
 | 
				
			||||||
TEST (block_store, incompatible_version)
 | 
					TEST (block_store, incompatible_version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -2252,24 +1755,6 @@ TEST (block_store, rocksdb_force_test_env_variable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace
 | 
					namespace
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
void write_sideband_v12 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block & block_a, nano::block_hash const & successor_a, MDB_dbi db_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	std::vector<uint8_t> vector;
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::vectorstream stream (vector);
 | 
					 | 
				
			||||||
		block_a.serialize (stream);
 | 
					 | 
				
			||||||
		nano::write (stream, successor_a);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	MDB_val val{ vector.size (), vector.data () };
 | 
					 | 
				
			||||||
	auto hash (block_a.hash ());
 | 
					 | 
				
			||||||
	auto status (mdb_put (store_a.env.tx (transaction_a), db_a, nano::mdb_val (hash), &val, 0));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, status);
 | 
					 | 
				
			||||||
	nano::block_sideband_v14 sideband_v14;
 | 
					 | 
				
			||||||
	auto block (store_a.block_get_v14 (transaction_a, hash, &sideband_v14));
 | 
					 | 
				
			||||||
	ASSERT_NE (nullptr, block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, sideband_v14.height);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a)
 | 
					void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto block = store_a.block_get (transaction_a, block_a.hash ());
 | 
						auto block = store_a.block_get (transaction_a, block_a.hash ());
 | 
				
			||||||
| 
						 | 
					@ -2306,16 +1791,6 @@ void write_sideband_v15 (nano::mdb_store & store_a, nano::transaction & transact
 | 
				
			||||||
	ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), store_a.state_blocks, nano::mdb_val (block_a.hash ()), &val, 0));
 | 
						ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), store_a.state_blocks, nano::mdb_val (block_a.hash ()), &val, 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// These functions take the latest account_info and create a legacy one so that upgrade tests can be emulated more easily.
 | 
					 | 
				
			||||||
void modify_account_info_to_v13 (nano::mdb_store & store, nano::transaction const & transaction, nano::account const & account, nano::block_hash const & rep_block)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::account_info info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.account_get (transaction, account, info));
 | 
					 | 
				
			||||||
	nano::account_info_v13 account_info_v13 (info.head, rep_block, info.open_block, info.balance, info.modified, info.block_count, info.epoch ());
 | 
					 | 
				
			||||||
	auto status (mdb_put (store.env.tx (transaction), (info.epoch () == nano::epoch::epoch_0) ? store.accounts_v0 : store.accounts_v1, nano::mdb_val (account), nano::mdb_val (account_info_v13), 0));
 | 
					 | 
				
			||||||
	ASSERT_EQ (status, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void modify_account_info_to_v14 (nano::mdb_store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height, nano::block_hash const & rep_block)
 | 
					void modify_account_info_to_v14 (nano::mdb_store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height, nano::block_hash const & rep_block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::account_info info;
 | 
						nano::account_info info;
 | 
				
			||||||
| 
						 | 
					@ -2330,15 +1805,4 @@ void modify_confirmation_height_to_v15 (nano::mdb_store & store, nano::transacti
 | 
				
			||||||
	auto status (mdb_put (store.env.tx (transaction), store.confirmation_height, nano::mdb_val (account), nano::mdb_val (confirmation_height), 0));
 | 
						auto status (mdb_put (store.env.tx (transaction), store.confirmation_height, nano::mdb_val (account), nano::mdb_val (confirmation_height), 0));
 | 
				
			||||||
	ASSERT_EQ (status, 0);
 | 
						ASSERT_EQ (status, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void modify_genesis_account_info_to_v5 (nano::mdb_store & store, nano::transaction const & transaction)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::account_info info;
 | 
					 | 
				
			||||||
	store.account_get (transaction, nano::test_genesis_key.pub, info);
 | 
					 | 
				
			||||||
	nano::representative_visitor visitor (transaction, store);
 | 
					 | 
				
			||||||
	visitor.compute (info.head);
 | 
					 | 
				
			||||||
	nano::account_info_v5 info_old (info.head, visitor.result, info.open_block, info.balance, info.modified);
 | 
					 | 
				
			||||||
	auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (nano::test_genesis_key.pub), nano::mdb_val (sizeof (info_old), &info_old), 0));
 | 
					 | 
				
			||||||
	ASSERT_EQ (status, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,25 +86,6 @@ TEST (ipc, synchronous)
 | 
				
			||||||
	ipc.stop ();
 | 
						ipc.stop ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (ipc, config_upgrade_v0_v1)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path1 (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto path2 (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::ipc::ipc_config config1;
 | 
					 | 
				
			||||||
	nano::ipc::ipc_config config2;
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	config1.serialize_json (tree);
 | 
					 | 
				
			||||||
	nano::jsonconfig local = tree.get_required_child ("local");
 | 
					 | 
				
			||||||
	local.erase ("version");
 | 
					 | 
				
			||||||
	local.erase ("allow_unsafe");
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (config2.deserialize_json (upgraded, tree));
 | 
					 | 
				
			||||||
	nano::jsonconfig local2 = tree.get_required_child ("local");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_LE (1, local2.get<int> ("version"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (local2.get<bool> ("allow_unsafe"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (ipc, permissions_default_user)
 | 
					TEST (ipc, permissions_default_user)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// Test empty/nonexistant access config. The default user still exists with default permissions.
 | 
						// Test empty/nonexistant access config. The default user still exists with default permissions.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,64 +58,6 @@ TEST (logging, serialization)
 | 
				
			||||||
	ASSERT_EQ (logging1.min_time_between_log_output, logging2.min_time_between_log_output);
 | 
						ASSERT_EQ (logging1.min_time_between_log_output, logging2.min_time_between_log_output);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (logging, upgrade_v1_v2)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path1 (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto path2 (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::logging logging1;
 | 
					 | 
				
			||||||
	logging1.init (path1);
 | 
					 | 
				
			||||||
	nano::logging logging2;
 | 
					 | 
				
			||||||
	logging2.init (path2);
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	logging1.serialize_json (tree);
 | 
					 | 
				
			||||||
	tree.erase ("version");
 | 
					 | 
				
			||||||
	tree.erase ("vote");
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (logging2.deserialize_json (upgraded, tree));
 | 
					 | 
				
			||||||
	ASSERT_LE (2, tree.get<int> ("version"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get<bool> ("vote"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (logging, upgrade_v6_v7)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path1 (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto path2 (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::logging logging1;
 | 
					 | 
				
			||||||
	logging1.init (path1);
 | 
					 | 
				
			||||||
	nano::logging logging2;
 | 
					 | 
				
			||||||
	logging2.init (path2);
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	logging1.serialize_json (tree);
 | 
					 | 
				
			||||||
	tree.erase ("version");
 | 
					 | 
				
			||||||
	tree.erase ("min_time_between_output");
 | 
					 | 
				
			||||||
	tree.erase ("network_timeout_logging_value");
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (logging2.deserialize_json (upgraded, tree));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_LE (7, tree.get<int> ("version"));
 | 
					 | 
				
			||||||
	ASSERT_EQ (5, tree.get<uintmax_t> ("min_time_between_output"));
 | 
					 | 
				
			||||||
	ASSERT_EQ (false, tree.get<bool> ("network_timeout_logging_value"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (logging, upgrade_v7_v8)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path1 (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto path2 (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::logging logging1;
 | 
					 | 
				
			||||||
	logging1.init (path1);
 | 
					 | 
				
			||||||
	nano::logging logging2;
 | 
					 | 
				
			||||||
	logging2.init (path2);
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	logging1.serialize_json (tree);
 | 
					 | 
				
			||||||
	tree.erase ("version");
 | 
					 | 
				
			||||||
	tree.erase ("single_line_record");
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (logging2.deserialize_json (upgraded, tree));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_LE (8, tree.get<int> ("version"));
 | 
					 | 
				
			||||||
	ASSERT_EQ (false, tree.get<bool> ("single_line_record"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (logger, changing_time_interval)
 | 
					TEST (logger, changing_time_interval)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto path1 (nano::unique_path ());
 | 
						auto path1 (nano::unique_path ());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -562,197 +562,6 @@ TEST (node_config, serialization)
 | 
				
			||||||
	ASSERT_EQ (config2.deprecated_lmdb_max_dbs, config1.deprecated_lmdb_max_dbs);
 | 
						ASSERT_EQ (config2.deprecated_lmdb_max_dbs, config1.deprecated_lmdb_max_dbs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (node_config, v1_v2_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::logging logging1;
 | 
					 | 
				
			||||||
	logging1.init (path);
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	tree.put ("peering_port", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("packet_delay_microseconds", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("bootstrap_fraction_numerator", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("creation_rebroadcast", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("rebroadcast_delay", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("receive_minimum", nano::amount (0).to_string_dec ());
 | 
					 | 
				
			||||||
	nano::jsonconfig logging_l;
 | 
					 | 
				
			||||||
	logging1.serialize_json (logging_l);
 | 
					 | 
				
			||||||
	tree.put_child ("logging", logging_l);
 | 
					 | 
				
			||||||
	nano::jsonconfig preconfigured_peers_l;
 | 
					 | 
				
			||||||
	tree.put_child ("preconfigured_peers", preconfigured_peers_l);
 | 
					 | 
				
			||||||
	nano::jsonconfig preconfigured_representatives_l;
 | 
					 | 
				
			||||||
	tree.put_child ("preconfigured_representatives", preconfigured_representatives_l);
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	nano::node_config config1;
 | 
					 | 
				
			||||||
	config1.logging.init (path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("work_peers"));
 | 
					 | 
				
			||||||
	config1.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("work_peers"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node_config, v2_v3_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	add_required_children_node_config_tree (tree);
 | 
					 | 
				
			||||||
	tree.put ("peering_port", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("packet_delay_microseconds", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("bootstrap_fraction_numerator", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("creation_rebroadcast", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("rebroadcast_delay", std::to_string (0));
 | 
					 | 
				
			||||||
	tree.put ("receive_minimum", nano::amount (0).to_string_dec ());
 | 
					 | 
				
			||||||
	tree.put ("version", "2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::jsonconfig preconfigured_representatives_l;
 | 
					 | 
				
			||||||
	preconfigured_representatives_l.push ("TR6ZJ4pdp6HC76xMRpVDny5x2s8AEbrhFue3NKVxYYdmKuTEib");
 | 
					 | 
				
			||||||
	tree.replace_child ("preconfigured_representatives", preconfigured_representatives_l);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool upgraded (false);
 | 
					 | 
				
			||||||
	nano::node_config config1;
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	config1.logging.init (path);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional<std::string> ("inactive_supply"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional<std::string> ("password_fanout"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional<std::string> ("io_threads"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional<std::string> ("work_threads"));
 | 
					 | 
				
			||||||
	config1.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
	//ASSERT_EQ (nano::uint128_union (0).to_string_dec (), tree.get<std::string> ("inactive_supply"));
 | 
					 | 
				
			||||||
	ASSERT_EQ ("1024", tree.get<std::string> ("password_fanout"));
 | 
					 | 
				
			||||||
	ASSERT_NE (0, std::stoul (tree.get<std::string> ("password_fanout")));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	auto version (tree.get<std::string> ("version"));
 | 
					 | 
				
			||||||
	ASSERT_GT (std::stoull (version), 2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node_config, v15_v16_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto test_upgrade = [](auto old_preconfigured_peers_url, auto new_preconfigured_peers_url) {
 | 
					 | 
				
			||||||
		auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
		nano::jsonconfig tree;
 | 
					 | 
				
			||||||
		add_required_children_node_config_tree (tree);
 | 
					 | 
				
			||||||
		tree.put ("version", "15");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const char * dummy_peer = "127.5.2.1";
 | 
					 | 
				
			||||||
		nano::jsonconfig preconfigured_peers_json;
 | 
					 | 
				
			||||||
		preconfigured_peers_json.push (old_preconfigured_peers_url);
 | 
					 | 
				
			||||||
		preconfigured_peers_json.push (dummy_peer);
 | 
					 | 
				
			||||||
		tree.replace_child ("preconfigured_peers", preconfigured_peers_json);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto upgraded (false);
 | 
					 | 
				
			||||||
		nano::node_config config;
 | 
					 | 
				
			||||||
		config.logging.init (path);
 | 
					 | 
				
			||||||
		// These config options should not be present at version 15
 | 
					 | 
				
			||||||
		ASSERT_FALSE (tree.get_optional_child ("allow_local_peers"));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (tree.get_optional_child ("signature_checker_threads"));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (tree.get_optional_child ("vote_minimum"));
 | 
					 | 
				
			||||||
		config.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
		// The config options should be added after the upgrade
 | 
					 | 
				
			||||||
		ASSERT_TRUE (!!tree.get_optional_child ("allow_local_peers"));
 | 
					 | 
				
			||||||
		ASSERT_TRUE (!!tree.get_optional_child ("signature_checker_threads"));
 | 
					 | 
				
			||||||
		ASSERT_TRUE (!!tree.get_optional_child ("vote_minimum"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
		auto version (tree.get<std::string> ("version"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto read_preconfigured_peers_json (tree.get_required_child ("preconfigured_peers"));
 | 
					 | 
				
			||||||
		std::vector<std::string> preconfigured_peers;
 | 
					 | 
				
			||||||
		read_preconfigured_peers_json.array_entries<std::string> ([&preconfigured_peers](const auto & entry) {
 | 
					 | 
				
			||||||
			preconfigured_peers.push_back (entry);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Check that the new peer is updated while the other peer is untouched
 | 
					 | 
				
			||||||
		ASSERT_EQ (preconfigured_peers.size (), 2);
 | 
					 | 
				
			||||||
		ASSERT_EQ (preconfigured_peers.front (), new_preconfigured_peers_url);
 | 
					 | 
				
			||||||
		ASSERT_EQ (preconfigured_peers.back (), dummy_peer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Check version is updated
 | 
					 | 
				
			||||||
		ASSERT_GT (std::stoull (version), 15);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check that upgrades work with both
 | 
					 | 
				
			||||||
	test_upgrade ("rai.raiblocks.net", "peering.nano.org");
 | 
					 | 
				
			||||||
	test_upgrade ("rai-beta.raiblocks.net", "peering-beta.nano.org");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node_config, v16_values)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	add_required_children_node_config_tree (tree);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto upgraded (false);
 | 
					 | 
				
			||||||
	nano::node_config config;
 | 
					 | 
				
			||||||
	config.logging.init (path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check config is correct
 | 
					 | 
				
			||||||
	tree.put ("allow_local_peers", false);
 | 
					 | 
				
			||||||
	tree.put ("signature_checker_threads", 1);
 | 
					 | 
				
			||||||
	tree.put ("vote_minimum", nano::Gxrb_ratio.convert_to<std::string> ());
 | 
					 | 
				
			||||||
	config.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (config.allow_local_peers);
 | 
					 | 
				
			||||||
	ASSERT_EQ (config.signature_checker_threads, 1);
 | 
					 | 
				
			||||||
	ASSERT_EQ (config.vote_minimum.number (), nano::Gxrb_ratio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check config is correct with other values
 | 
					 | 
				
			||||||
	tree.put ("allow_local_peers", true);
 | 
					 | 
				
			||||||
	tree.put ("signature_checker_threads", 4);
 | 
					 | 
				
			||||||
	tree.put ("vote_minimum", (std::numeric_limits<nano::uint128_t>::max () - 100).convert_to<std::string> ());
 | 
					 | 
				
			||||||
	upgraded = false;
 | 
					 | 
				
			||||||
	config.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (upgraded);
 | 
					 | 
				
			||||||
	ASSERT_TRUE (config.allow_local_peers);
 | 
					 | 
				
			||||||
	ASSERT_EQ (config.signature_checker_threads, 4);
 | 
					 | 
				
			||||||
	ASSERT_EQ (config.vote_minimum.number (), std::numeric_limits<nano::uint128_t>::max () - 100);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node_config, v16_v17_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::jsonconfig tree;
 | 
					 | 
				
			||||||
	add_required_children_node_config_tree (tree);
 | 
					 | 
				
			||||||
	tree.put ("version", "16");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto upgraded (false);
 | 
					 | 
				
			||||||
	nano::node_config config;
 | 
					 | 
				
			||||||
	config.logging.init (path);
 | 
					 | 
				
			||||||
	// These config options should not be present
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("tcp_io_timeout"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("pow_sleep_interval"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("external_address"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("external_port"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("tcp_incoming_connections_max"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("vote_generator_delay"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("vote_generator_threshold"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("diagnostics"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("use_memory_pools"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("confirmation_history_size"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("active_elections_size"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("bandwidth_limit"));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (tree.get_optional_child ("conf_height_processor_batch_min_time"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	config.deserialize_json (upgraded, tree);
 | 
					 | 
				
			||||||
	// The config options should be added after the upgrade
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("tcp_io_timeout"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("pow_sleep_interval"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("external_address"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("external_port"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("tcp_incoming_connections_max"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("vote_generator_delay"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("vote_generator_threshold"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("diagnostics"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("use_memory_pools"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("confirmation_history_size"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("active_elections_size"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("bandwidth_limit"));
 | 
					 | 
				
			||||||
	ASSERT_TRUE (!!tree.get_optional_child ("conf_height_processor_batch_min_time"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ASSERT_TRUE (upgraded);
 | 
					 | 
				
			||||||
	auto version (tree.get<std::string> ("version"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check version is updated
 | 
					 | 
				
			||||||
	ASSERT_GT (std::stoull (version), 16);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (node_config, v17_values)
 | 
					TEST (node_config, v17_values)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::jsonconfig tree;
 | 
						nano::jsonconfig tree;
 | 
				
			||||||
| 
						 | 
					@ -954,6 +763,23 @@ TEST (node_config, random_rep)
 | 
				
			||||||
	ASSERT_NE (config1.preconfigured_representatives.end (), std::find (config1.preconfigured_representatives.begin (), config1.preconfigured_representatives.end (), rep));
 | 
						ASSERT_NE (config1.preconfigured_representatives.end (), std::find (config1.preconfigured_representatives.begin (), config1.preconfigured_representatives.end (), rep));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST (node_config, unsupported_version_upgrade)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto path (nano::unique_path ());
 | 
				
			||||||
 | 
						nano::logging logging1;
 | 
				
			||||||
 | 
						logging1.init (path);
 | 
				
			||||||
 | 
						nano::node_config node_config (100, logging1);
 | 
				
			||||||
 | 
						nano::jsonconfig config;
 | 
				
			||||||
 | 
						node_config.serialize_json (config);
 | 
				
			||||||
 | 
						config.put ("version", "16"); // Version 16 and earlier is no longer supported for direct upgrade
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nano::node_config node_config1;
 | 
				
			||||||
 | 
						bool upgraded{ false };
 | 
				
			||||||
 | 
						auto err = node_config1.deserialize_json (upgraded, config);
 | 
				
			||||||
 | 
						ASSERT_FALSE (upgraded);
 | 
				
			||||||
 | 
						ASSERT_TRUE (err);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class json_initial_value_test final
 | 
					class json_initial_value_test final
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,115 +0,0 @@
 | 
				
			||||||
#include <nano/lib/logger_mt.hpp>
 | 
					 | 
				
			||||||
#include <nano/node/lmdb/lmdb.hpp>
 | 
					 | 
				
			||||||
#include <nano/secure/blockstore.hpp>
 | 
					 | 
				
			||||||
#include <nano/secure/utility.hpp>
 | 
					 | 
				
			||||||
#include <nano/secure/versioning.hpp>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gtest/gtest.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (versioning, account_info_v1)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto file (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::account account (1);
 | 
					 | 
				
			||||||
	nano::open_block open (1, 2, 3, nullptr);
 | 
					 | 
				
			||||||
	open.sideband_set ({});
 | 
					 | 
				
			||||||
	nano::account_info_v1 v1 (open.hash (), open.hash (), 3, 4);
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.block_put (transaction, open.hash (), open);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (account), nano::mdb_val (sizeof (v1), &v1), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, status);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	nano::account_info v_latest;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.account_get (transaction, account, v_latest));
 | 
					 | 
				
			||||||
	ASSERT_EQ (open.hash (), v_latest.open_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v1.balance, v_latest.balance);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v1.head, v_latest.head);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v1.modified, v_latest.modified);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v1.rep_block, open.hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, v_latest.block_count);
 | 
					 | 
				
			||||||
	nano::confirmation_height_info confirmation_height_info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.confirmation_height_get (transaction, account, confirmation_height_info));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, confirmation_height_info.height);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::epoch::epoch_0, v_latest.epoch ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (versioning, account_info_v5)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto file (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::account account (1);
 | 
					 | 
				
			||||||
	nano::open_block open (1, 2, 3, nullptr);
 | 
					 | 
				
			||||||
	open.sideband_set ({});
 | 
					 | 
				
			||||||
	nano::account_info_v5 v5 (open.hash (), open.hash (), open.hash (), 3, 4);
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.block_put (transaction, open.hash (), open);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (account), nano::mdb_val (sizeof (v5), &v5), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, status);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 5);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	nano::account_info v_latest;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.account_get (transaction, account, v_latest));
 | 
					 | 
				
			||||||
	ASSERT_EQ (v5.open_block, v_latest.open_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v5.balance, v_latest.balance);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v5.head, v_latest.head);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v5.modified, v_latest.modified);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v5.rep_block, open.hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, v_latest.block_count);
 | 
					 | 
				
			||||||
	nano::confirmation_height_info confirmation_height_info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.confirmation_height_get (transaction, account, confirmation_height_info));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, confirmation_height_info.height);
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::epoch::epoch_0, v_latest.epoch ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (versioning, account_info_v13)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto file (nano::unique_path ());
 | 
					 | 
				
			||||||
	nano::account account (1);
 | 
					 | 
				
			||||||
	nano::open_block open (1, 2, 3, nullptr);
 | 
					 | 
				
			||||||
	open.sideband_set ({});
 | 
					 | 
				
			||||||
	nano::account_info_v13 v13 (open.hash (), open.hash (), open.hash (), 3, 4, 10, nano::epoch::epoch_0);
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::logger_mt logger;
 | 
					 | 
				
			||||||
		nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
		ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
		auto transaction (store.tx_begin_write ());
 | 
					 | 
				
			||||||
		store.block_put (transaction, open.hash (), open);
 | 
					 | 
				
			||||||
		auto status (mdb_put (store.env.tx (transaction), store.accounts_v0, nano::mdb_val (account), nano::mdb_val (v13), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (0, status);
 | 
					 | 
				
			||||||
		store.version_put (transaction, 13);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::logger_mt logger;
 | 
					 | 
				
			||||||
	nano::mdb_store store (logger, file);
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.init_error ());
 | 
					 | 
				
			||||||
	auto transaction (store.tx_begin_read ());
 | 
					 | 
				
			||||||
	nano::account_info v_latest;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.account_get (transaction, account, v_latest));
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.open_block, v_latest.open_block);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.balance, v_latest.balance);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.head, v_latest.head);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.modified, v_latest.modified);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.rep_block, open.hash ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.block_count, v_latest.block_count);
 | 
					 | 
				
			||||||
	nano::confirmation_height_info confirmation_height_info;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (store.confirmation_height_get (transaction, account, confirmation_height_info));
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, confirmation_height_info.height);
 | 
					 | 
				
			||||||
	ASSERT_EQ (v13.epoch, v_latest.epoch ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -726,46 +726,6 @@ TEST (wallet, insert_locked)
 | 
				
			||||||
	ASSERT_TRUE (wallet->insert_adhoc (nano::keypair ().prv).is_zero ());
 | 
						ASSERT_TRUE (wallet->insert_adhoc (nano::keypair ().prv).is_zero ());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (wallet, version_1_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::system system (1);
 | 
					 | 
				
			||||||
	auto wallet (system.wallet (0));
 | 
					 | 
				
			||||||
	wallet->enter_initial_password ();
 | 
					 | 
				
			||||||
	nano::keypair key;
 | 
					 | 
				
			||||||
	auto transaction (wallet->wallets.tx_begin_write ());
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	wallet->store.rekey (transaction, "1");
 | 
					 | 
				
			||||||
	wallet->enter_password (transaction, "");
 | 
					 | 
				
			||||||
	ASSERT_FALSE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	nano::raw_key password_l;
 | 
					 | 
				
			||||||
	nano::wallet_value value (wallet->store.entry_get_raw (transaction, nano::wallet_store::wallet_key_special));
 | 
					 | 
				
			||||||
	nano::raw_key kdf;
 | 
					 | 
				
			||||||
	kdf.data.clear ();
 | 
					 | 
				
			||||||
	password_l.decrypt (value.key, kdf, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	nano::uint256_union ciphertext;
 | 
					 | 
				
			||||||
	ciphertext.encrypt (key.prv, password_l, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	wallet->store.entry_put_raw (transaction, key.pub, nano::wallet_value (ciphertext, 0));
 | 
					 | 
				
			||||||
	wallet->store.version_put (transaction, 1);
 | 
					 | 
				
			||||||
	wallet->enter_password (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::wallet_store::version_current, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	nano::raw_key prv;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (wallet->store.fetch (transaction, key.pub, prv));
 | 
					 | 
				
			||||||
	ASSERT_EQ (key.prv, prv);
 | 
					 | 
				
			||||||
	value = wallet->store.entry_get_raw (transaction, nano::wallet_store::wallet_key_special);
 | 
					 | 
				
			||||||
	wallet->store.derive_key (kdf, transaction, "");
 | 
					 | 
				
			||||||
	password_l.decrypt (value.key, kdf, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	ciphertext.encrypt (key.prv, password_l, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	wallet->store.entry_put_raw (transaction, key.pub, nano::wallet_value (ciphertext, 0));
 | 
					 | 
				
			||||||
	wallet->store.version_put (transaction, 1);
 | 
					 | 
				
			||||||
	wallet->enter_password (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::wallet_store::version_current, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	nano::raw_key prv2;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (wallet->store.fetch (transaction, key.pub, prv2));
 | 
					 | 
				
			||||||
	ASSERT_EQ (key.prv, prv2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (wallet, deterministic_keys)
 | 
					TEST (wallet, deterministic_keys)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool init;
 | 
						bool init;
 | 
				
			||||||
| 
						 | 
					@ -854,117 +814,6 @@ TEST (wallet, insert_deterministic_locked)
 | 
				
			||||||
	ASSERT_TRUE (wallet->deterministic_insert (transaction).is_zero ());
 | 
						ASSERT_TRUE (wallet->deterministic_insert (transaction).is_zero ());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (wallet, version_2_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::system system (1);
 | 
					 | 
				
			||||||
	auto wallet (system.wallet (0));
 | 
					 | 
				
			||||||
	auto transaction (wallet->wallets.tx_begin_write ());
 | 
					 | 
				
			||||||
	wallet->store.rekey (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.attempt_password (transaction, ""));
 | 
					 | 
				
			||||||
	wallet->store.erase (transaction, nano::wallet_store::deterministic_index_special);
 | 
					 | 
				
			||||||
	wallet->store.erase (transaction, nano::wallet_store::seed_special);
 | 
					 | 
				
			||||||
	wallet->store.version_put (transaction, 2);
 | 
					 | 
				
			||||||
	ASSERT_EQ (2, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (wallet->store.find (transaction, nano::wallet_store::deterministic_index_special), wallet->store.end ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (wallet->store.find (transaction, nano::wallet_store::seed_special), wallet->store.end ());
 | 
					 | 
				
			||||||
	wallet->store.attempt_password (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::wallet_store::version_current, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	ASSERT_NE (wallet->store.find (transaction, nano::wallet_store::deterministic_index_special), wallet->store.end ());
 | 
					 | 
				
			||||||
	ASSERT_NE (wallet->store.find (transaction, nano::wallet_store::seed_special), wallet->store.end ());
 | 
					 | 
				
			||||||
	ASSERT_FALSE (wallet->deterministic_insert (transaction).is_zero ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (wallet, version_3_upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::system system (1);
 | 
					 | 
				
			||||||
	auto wallet (system.wallet (0));
 | 
					 | 
				
			||||||
	auto transaction (wallet->wallets.tx_begin_write ());
 | 
					 | 
				
			||||||
	wallet->store.rekey (transaction, "1");
 | 
					 | 
				
			||||||
	wallet->enter_password (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::wallet_store::version_current, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	nano::keypair key;
 | 
					 | 
				
			||||||
	nano::raw_key seed;
 | 
					 | 
				
			||||||
	nano::uint256_union seed_ciphertext;
 | 
					 | 
				
			||||||
	nano::random_pool::generate_block (seed.data.bytes.data (), seed.data.bytes.size ());
 | 
					 | 
				
			||||||
	nano::raw_key password_l;
 | 
					 | 
				
			||||||
	nano::wallet_value value (wallet->store.entry_get_raw (transaction, nano::wallet_store::wallet_key_special));
 | 
					 | 
				
			||||||
	nano::raw_key kdf;
 | 
					 | 
				
			||||||
	wallet->store.derive_key (kdf, transaction, "1");
 | 
					 | 
				
			||||||
	password_l.decrypt (value.key, kdf, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	nano::uint256_union ciphertext;
 | 
					 | 
				
			||||||
	ciphertext.encrypt (key.prv, password_l, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	wallet->store.entry_put_raw (transaction, key.pub, nano::wallet_value (ciphertext, 0));
 | 
					 | 
				
			||||||
	seed_ciphertext.encrypt (seed, password_l, wallet->store.salt (transaction).owords[0]);
 | 
					 | 
				
			||||||
	wallet->store.entry_put_raw (transaction, nano::wallet_store::seed_special, nano::wallet_value (seed_ciphertext, 0));
 | 
					 | 
				
			||||||
	wallet->store.version_put (transaction, 3);
 | 
					 | 
				
			||||||
	wallet->enter_password (transaction, "1");
 | 
					 | 
				
			||||||
	ASSERT_TRUE (wallet->store.valid_password (transaction));
 | 
					 | 
				
			||||||
	ASSERT_EQ (nano::wallet_store::version_current, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	nano::raw_key prv;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (wallet->store.fetch (transaction, key.pub, prv));
 | 
					 | 
				
			||||||
	ASSERT_EQ (key.prv, prv);
 | 
					 | 
				
			||||||
	nano::raw_key seed_compare;
 | 
					 | 
				
			||||||
	wallet->store.seed (seed_compare, transaction);
 | 
					 | 
				
			||||||
	ASSERT_EQ (seed, seed_compare);
 | 
					 | 
				
			||||||
	ASSERT_NE (seed_ciphertext, wallet->store.entry_get_raw (transaction, nano::wallet_store::seed_special).key);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (wallet, upgrade_backup)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::system system (1);
 | 
					 | 
				
			||||||
	auto dir (nano::unique_path ());
 | 
					 | 
				
			||||||
	namespace fs = boost::filesystem;
 | 
					 | 
				
			||||||
	fs::create_directory (dir);
 | 
					 | 
				
			||||||
	/** Returns 'dir' if backup file cannot be found */
 | 
					 | 
				
			||||||
	auto get_backup_path = [&dir]() {
 | 
					 | 
				
			||||||
		for (fs::directory_iterator itr (dir); itr != fs::directory_iterator (); ++itr)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (itr->path ().filename ().string ().find ("wallets_backup_") != std::string::npos)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				return itr->path ();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return dir;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto wallet_id = nano::random_wallet_id ();
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto node1 (std::make_shared<nano::node> (system.io_ctx, nano::get_available_port (), dir, system.alarm, system.logging, system.work));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (node1->init_error ());
 | 
					 | 
				
			||||||
		auto wallet (node1->wallets.create (wallet_id));
 | 
					 | 
				
			||||||
		ASSERT_NE (nullptr, wallet);
 | 
					 | 
				
			||||||
		auto transaction (node1->wallets.tx_begin_write ());
 | 
					 | 
				
			||||||
		wallet->store.version_put (transaction, 3);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ASSERT_EQ (get_backup_path ().string (), dir.string ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check with config backup_before_upgrade = false
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto node1 (std::make_shared<nano::node> (system.io_ctx, nano::get_available_port (), dir, system.alarm, system.logging, system.work));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (node1->init_error ());
 | 
					 | 
				
			||||||
		auto wallet (node1->wallets.open (wallet_id));
 | 
					 | 
				
			||||||
		ASSERT_NE (nullptr, wallet);
 | 
					 | 
				
			||||||
		auto transaction (node1->wallets.tx_begin_write ());
 | 
					 | 
				
			||||||
		ASSERT_LT (3u, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
		wallet->store.version_put (transaction, 3);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ASSERT_EQ (get_backup_path ().string (), dir.string ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Now do the upgrade and confirm that backup is saved
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::node_config node_config (nano::get_available_port (), system.logging);
 | 
					 | 
				
			||||||
		node_config.backup_before_upgrade = true;
 | 
					 | 
				
			||||||
		auto node1 (std::make_shared<nano::node> (system.io_ctx, dir, system.alarm, node_config, system.work));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (node1->init_error ());
 | 
					 | 
				
			||||||
		auto wallet (node1->wallets.open (wallet_id));
 | 
					 | 
				
			||||||
		ASSERT_NE (nullptr, wallet);
 | 
					 | 
				
			||||||
		auto transaction (node1->wallets.tx_begin_read ());
 | 
					 | 
				
			||||||
		ASSERT_LT (3u, wallet->store.version (transaction));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ASSERT_NE (get_backup_path ().string (), dir.string ());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (wallet, no_work)
 | 
					TEST (wallet, no_work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::system system (1);
 | 
						nano::system system (1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,58 +74,6 @@ TEST (wallets, remove)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (wallets, upgrade)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Don't test this in rocksdb mode
 | 
					 | 
				
			||||||
	auto use_rocksdb_str = std::getenv ("TEST_USE_ROCKSDB");
 | 
					 | 
				
			||||||
	if (use_rocksdb_str && boost::lexical_cast<int> (use_rocksdb_str) == 1)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::system system;
 | 
					 | 
				
			||||||
	nano::node_config node_config (nano::get_available_port (), system.logging);
 | 
					 | 
				
			||||||
	node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
 | 
					 | 
				
			||||||
	system.add_node (node_config);
 | 
					 | 
				
			||||||
	auto path (nano::unique_path ());
 | 
					 | 
				
			||||||
	auto id = nano::random_wallet_id ();
 | 
					 | 
				
			||||||
	nano::node_config node_config1 (nano::get_available_port (), system.logging);
 | 
					 | 
				
			||||||
	node_config1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto node1 (std::make_shared<nano::node> (system.io_ctx, path, system.alarm, node_config1, system.work));
 | 
					 | 
				
			||||||
		ASSERT_FALSE (node1->init_error ());
 | 
					 | 
				
			||||||
		bool error (false);
 | 
					 | 
				
			||||||
		nano::wallets wallets (error, *node1);
 | 
					 | 
				
			||||||
		wallets.create (id);
 | 
					 | 
				
			||||||
		auto transaction_source (node1->wallets.env.tx_begin_write ());
 | 
					 | 
				
			||||||
		auto tx_source = static_cast<MDB_txn *> (transaction_source.get_handle ());
 | 
					 | 
				
			||||||
		auto & mdb_store (dynamic_cast<nano::mdb_store &> (node1->store));
 | 
					 | 
				
			||||||
		auto transaction_destination (mdb_store.tx_begin_write ());
 | 
					 | 
				
			||||||
		auto tx_destination = static_cast<MDB_txn *> (transaction_destination.get_handle ());
 | 
					 | 
				
			||||||
		wallets.move_table (id.to_string (), tx_source, tx_destination);
 | 
					 | 
				
			||||||
		node1->store.version_put (transaction_destination, 11);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		nano::account_info info;
 | 
					 | 
				
			||||||
		ASSERT_FALSE (mdb_store.account_get (transaction_destination, nano::genesis_account, info));
 | 
					 | 
				
			||||||
		auto rep_block = node1->rep_block (nano::genesis_account);
 | 
					 | 
				
			||||||
		nano::account_info_v13 account_info_v13 (info.head, rep_block, info.open_block, info.balance, info.modified, info.block_count, info.epoch ());
 | 
					 | 
				
			||||||
		auto status (mdb_put (mdb_store.env.tx (transaction_destination), info.epoch () == nano::epoch::epoch_0 ? mdb_store.accounts_v0 : mdb_store.accounts_v1, nano::mdb_val (nano::test_genesis_key.pub), nano::mdb_val (account_info_v13), 0));
 | 
					 | 
				
			||||||
		ASSERT_EQ (status, 0);
 | 
					 | 
				
			||||||
		mdb_store.confirmation_height_del (transaction_destination, nano::genesis_account);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	auto node1 (std::make_shared<nano::node> (system.io_ctx, path, system.alarm, node_config1, system.work));
 | 
					 | 
				
			||||||
	ASSERT_EQ (1, node1->wallets.items.size ());
 | 
					 | 
				
			||||||
	ASSERT_EQ (id, node1->wallets.items.begin ()->first);
 | 
					 | 
				
			||||||
	auto transaction_new (node1->wallets.env.tx_begin_write ());
 | 
					 | 
				
			||||||
	auto tx_new = static_cast<MDB_txn *> (transaction_new.get_handle ());
 | 
					 | 
				
			||||||
	auto transaction_old (node1->store.tx_begin_write ());
 | 
					 | 
				
			||||||
	auto tx_old = static_cast<MDB_txn *> (transaction_old.get_handle ());
 | 
					 | 
				
			||||||
	MDB_dbi old_handle;
 | 
					 | 
				
			||||||
	ASSERT_EQ (MDB_NOTFOUND, mdb_dbi_open (tx_old, id.to_string ().c_str (), 0, &old_handle));
 | 
					 | 
				
			||||||
	MDB_dbi new_handle;
 | 
					 | 
				
			||||||
	ASSERT_EQ (0, mdb_dbi_open (tx_new, id.to_string ().c_str (), 0, &new_handle));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Keeps breaking whenever we add new DBs
 | 
					// Keeps breaking whenever we add new DBs
 | 
				
			||||||
TEST (wallets, DISABLED_wallet_create_max)
 | 
					TEST (wallets, DISABLED_wallet_create_max)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,25 +89,6 @@ nano::error nano::rpc_config::deserialize_json (bool & upgraded_a, nano::jsoncon
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!json.empty ())
 | 
						if (!json.empty ())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto version_l (json.get_optional<unsigned> ("version"));
 | 
					 | 
				
			||||||
		if (!version_l)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			version_l = 1;
 | 
					 | 
				
			||||||
			json.put ("version", *version_l);
 | 
					 | 
				
			||||||
			json.put ("max_request_size", max_request_size);
 | 
					 | 
				
			||||||
			json.erase ("frontier_request_limit");
 | 
					 | 
				
			||||||
			json.erase ("chain_request_limit");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			nano::jsonconfig rpc_process_l;
 | 
					 | 
				
			||||||
			rpc_process_l.put ("version", *version_l);
 | 
					 | 
				
			||||||
			rpc_process_l.put ("io_threads", rpc_process.io_threads);
 | 
					 | 
				
			||||||
			rpc_process_l.put ("ipc_address", rpc_process.ipc_address);
 | 
					 | 
				
			||||||
			rpc_process_l.put ("ipc_port", rpc_process.ipc_port);
 | 
					 | 
				
			||||||
			rpc_process_l.put ("num_ipc_connections", rpc_process.num_ipc_connections);
 | 
					 | 
				
			||||||
			json.put_child ("process", rpc_process_l);
 | 
					 | 
				
			||||||
			upgraded_a = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto rpc_secure_l (json.get_optional_child ("secure"));
 | 
							auto rpc_secure_l (json.get_optional_child ("secure"));
 | 
				
			||||||
		if (rpc_secure_l)
 | 
							if (rpc_secure_l)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -125,15 +106,6 @@ nano::error nano::rpc_config::deserialize_json (bool & upgraded_a, nano::jsoncon
 | 
				
			||||||
		auto rpc_process_l (json.get_optional_child ("process"));
 | 
							auto rpc_process_l (json.get_optional_child ("process"));
 | 
				
			||||||
		if (rpc_process_l)
 | 
							if (rpc_process_l)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto version_l (rpc_process_l->get_optional<unsigned> ("version"));
 | 
					 | 
				
			||||||
			if (!version_l)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				version_l = 1;
 | 
					 | 
				
			||||||
				rpc_process_l->put ("version", *version_l);
 | 
					 | 
				
			||||||
				rpc_process_l->put ("ipc_address", rpc_process.ipc_address);
 | 
					 | 
				
			||||||
				upgraded_a = true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			rpc_process_l->get_optional<unsigned> ("io_threads", rpc_process.io_threads);
 | 
								rpc_process_l->get_optional<unsigned> ("io_threads", rpc_process.io_threads);
 | 
				
			||||||
			rpc_process_l->get_optional<uint16_t> ("ipc_port", rpc_process.ipc_port);
 | 
								rpc_process_l->get_optional<uint16_t> ("ipc_port", rpc_process.ipc_port);
 | 
				
			||||||
			boost::asio::ip::address_v6 ipc_address_l;
 | 
								boost::asio::ip::address_v6 ipc_address_l;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,6 @@ void nano::add_node_flag_options (boost::program_options::options_description &
 | 
				
			||||||
		("disable_block_processor_unchecked_deletion", "Disable deletion of unchecked blocks after processing")
 | 
							("disable_block_processor_unchecked_deletion", "Disable deletion of unchecked blocks after processing")
 | 
				
			||||||
		("allow_bootstrap_peers_duplicates", "Allow multiple connections to same peer in bootstrap attempts")
 | 
							("allow_bootstrap_peers_duplicates", "Allow multiple connections to same peer in bootstrap attempts")
 | 
				
			||||||
		("fast_bootstrap", "Increase bootstrap speed for high end nodes with higher limits")
 | 
							("fast_bootstrap", "Increase bootstrap speed for high end nodes with higher limits")
 | 
				
			||||||
		("batch_size", boost::program_options::value<std::size_t>(), "(Deprecated) Increase sideband batch size, default 512. This change only affects nodes upgrading from v17 (or earlier) of the node.")
 | 
					 | 
				
			||||||
		("block_processor_batch_size", boost::program_options::value<std::size_t>(), "Increase block processor transaction batch write size, default 0 (limited by config block_processor_batch_max_time), 256k for fast_bootstrap")
 | 
							("block_processor_batch_size", boost::program_options::value<std::size_t>(), "Increase block processor transaction batch write size, default 0 (limited by config block_processor_batch_max_time), 256k for fast_bootstrap")
 | 
				
			||||||
		("block_processor_full_size", boost::program_options::value<std::size_t>(), "Increase block processor allowed blocks queue size before dropping live network packets and holding bootstrap download, default 65536, 1 million for fast_bootstrap")
 | 
							("block_processor_full_size", boost::program_options::value<std::size_t>(), "Increase block processor allowed blocks queue size before dropping live network packets and holding bootstrap download, default 65536, 1 million for fast_bootstrap")
 | 
				
			||||||
		("block_processor_verification_size", boost::program_options::value<std::size_t>(), "Increase batch signature verification size in block processor, default 0 (limited by config signature_checker_threads), unlimited for fast_bootstrap")
 | 
							("block_processor_verification_size", boost::program_options::value<std::size_t>(), "Increase batch signature verification size in block processor, default 0 (limited by config signature_checker_threads), unlimited for fast_bootstrap")
 | 
				
			||||||
| 
						 | 
					@ -111,11 +110,6 @@ void nano::add_node_flag_options (boost::program_options::options_description &
 | 
				
			||||||
std::error_code nano::update_flags (nano::node_flags & flags_a, boost::program_options::variables_map const & vm)
 | 
					std::error_code nano::update_flags (nano::node_flags & flags_a, boost::program_options::variables_map const & vm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::error_code ec;
 | 
						std::error_code ec;
 | 
				
			||||||
	auto batch_size_it = vm.find ("batch_size");
 | 
					 | 
				
			||||||
	if (batch_size_it != vm.end ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		flags_a.sideband_batch_size = batch_size_it->second.as<size_t> ();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	flags_a.disable_backup = (vm.count ("disable_backup") > 0);
 | 
						flags_a.disable_backup = (vm.count ("disable_backup") > 0);
 | 
				
			||||||
	flags_a.disable_lazy_bootstrap = (vm.count ("disable_lazy_bootstrap") > 0);
 | 
						flags_a.disable_lazy_bootstrap = (vm.count ("disable_lazy_bootstrap") > 0);
 | 
				
			||||||
	flags_a.disable_legacy_bootstrap = (vm.count ("disable_legacy_bootstrap") > 0);
 | 
						flags_a.disable_legacy_bootstrap = (vm.count ("disable_legacy_bootstrap") > 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,8 +97,6 @@ nano::error nano::daemon_config::deserialize_json (bool & upgraded_a, nano::json
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!json.empty ())
 | 
							if (!json.empty ())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			int version_l;
 | 
					 | 
				
			||||||
			json.get_optional<int> ("version", version_l);
 | 
					 | 
				
			||||||
			json.get_optional<bool> ("rpc_enable", rpc_enable);
 | 
								json.get_optional<bool> ("rpc_enable", rpc_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto rpc_l (json.get_required_child ("rpc"));
 | 
								auto rpc_l (json.get_required_child ("rpc"));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,15 +108,6 @@ nano::error nano::ipc::ipc_config::deserialize_json (bool & upgraded_a, nano::js
 | 
				
			||||||
	auto domain_l (json.get_optional_child ("local"));
 | 
						auto domain_l (json.get_optional_child ("local"));
 | 
				
			||||||
	if (domain_l)
 | 
						if (domain_l)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto version_l (domain_l->get_optional<unsigned> ("version"));
 | 
					 | 
				
			||||||
		if (!version_l)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			version_l = 1;
 | 
					 | 
				
			||||||
			domain_l->put ("version", *version_l);
 | 
					 | 
				
			||||||
			domain_l->put ("allow_unsafe", transport_domain.allow_unsafe);
 | 
					 | 
				
			||||||
			upgraded_a = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		domain_l->get_optional<long> ("io_threads", transport_domain.io_threads, -1);
 | 
							domain_l->get_optional<long> ("io_threads", transport_domain.io_threads, -1);
 | 
				
			||||||
		domain_l->get_optional<bool> ("allow_unsafe", transport_domain.allow_unsafe);
 | 
							domain_l->get_optional<bool> ("allow_unsafe", transport_domain.allow_unsafe);
 | 
				
			||||||
		domain_l->get<bool> ("enable", transport_domain.enabled);
 | 
							domain_l->get<bool> ("enable", transport_domain.enabled);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ void mdb_val::convert_buffer_to_value ()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::mdb_store::mdb_store (nano::logger_mt & logger_a, boost::filesystem::path const & path_a, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, size_t const batch_size_a, bool backup_before_upgrade_a) :
 | 
					nano::mdb_store::mdb_store (nano::logger_mt & logger_a, boost::filesystem::path const & path_a, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade_a) :
 | 
				
			||||||
logger (logger_a),
 | 
					logger (logger_a),
 | 
				
			||||||
env (error, path_a, nano::mdb_env::options::make ().set_config (lmdb_config_a).set_use_no_mem_init (true)),
 | 
					env (error, path_a, nano::mdb_env::options::make ().set_config (lmdb_config_a).set_use_no_mem_init (true)),
 | 
				
			||||||
mdb_txn_tracker (logger_a, txn_tracking_config_a, block_processor_batch_max_time_a),
 | 
					mdb_txn_tracker (logger_a, txn_tracking_config_a, block_processor_batch_max_time_a),
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ txn_tracking_enabled (txn_tracking_config_a.enable)
 | 
				
			||||||
				open_databases (error, transaction, MDB_CREATE);
 | 
									open_databases (error, transaction, MDB_CREATE);
 | 
				
			||||||
				if (!error)
 | 
									if (!error)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					error |= do_upgrades (transaction, needs_vacuuming, batch_size_a);
 | 
										error |= do_upgrades (transaction, needs_vacuuming);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,11 +186,6 @@ void nano::mdb_store::open_databases (bool & error_a, nano::transaction const &
 | 
				
			||||||
	error_a |= mdb_dbi_open (env.tx (transaction_a), "meta", flags, &meta) != 0;
 | 
						error_a |= mdb_dbi_open (env.tx (transaction_a), "meta", flags, &meta) != 0;
 | 
				
			||||||
	error_a |= mdb_dbi_open (env.tx (transaction_a), "peers", flags, &peers) != 0;
 | 
						error_a |= mdb_dbi_open (env.tx (transaction_a), "peers", flags, &peers) != 0;
 | 
				
			||||||
	error_a |= mdb_dbi_open (env.tx (transaction_a), "confirmation_height", flags, &confirmation_height) != 0;
 | 
						error_a |= mdb_dbi_open (env.tx (transaction_a), "confirmation_height", flags, &confirmation_height) != 0;
 | 
				
			||||||
	if (!full_sideband (transaction_a))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// The blocks_info database is no longer used, but need opening so that it can be deleted during an upgrade
 | 
					 | 
				
			||||||
		error_a |= mdb_dbi_open (env.tx (transaction_a), "blocks_info", flags, &blocks_info) != 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts", flags, &accounts_v0) != 0;
 | 
						error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts", flags, &accounts_v0) != 0;
 | 
				
			||||||
	accounts = accounts_v0;
 | 
						accounts = accounts_v0;
 | 
				
			||||||
	error_a |= mdb_dbi_open (env.tx (transaction_a), "pending", flags, &pending_v0) != 0;
 | 
						error_a |= mdb_dbi_open (env.tx (transaction_a), "pending", flags, &pending_v0) != 0;
 | 
				
			||||||
| 
						 | 
					@ -218,37 +213,28 @@ void nano::mdb_store::open_databases (bool & error_a, nano::transaction const &
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool nano::mdb_store::do_upgrades (nano::write_transaction & transaction_a, bool & needs_vacuuming, size_t batch_size_a)
 | 
					bool nano::mdb_store::do_upgrades (nano::write_transaction & transaction_a, bool & needs_vacuuming)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto error (false);
 | 
						auto error (false);
 | 
				
			||||||
	auto version_l = version_get (transaction_a);
 | 
						auto version_l = version_get (transaction_a);
 | 
				
			||||||
	switch (version_l)
 | 
						switch (version_l)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
			upgrade_v1_to_v2 (transaction_a);
 | 
					 | 
				
			||||||
		case 2:
 | 
							case 2:
 | 
				
			||||||
			upgrade_v2_to_v3 (transaction_a);
 | 
					 | 
				
			||||||
		case 3:
 | 
							case 3:
 | 
				
			||||||
			upgrade_v3_to_v4 (transaction_a);
 | 
					 | 
				
			||||||
		case 4:
 | 
							case 4:
 | 
				
			||||||
			upgrade_v4_to_v5 (transaction_a);
 | 
					 | 
				
			||||||
		case 5:
 | 
							case 5:
 | 
				
			||||||
			upgrade_v5_to_v6 (transaction_a);
 | 
					 | 
				
			||||||
		case 6:
 | 
							case 6:
 | 
				
			||||||
			upgrade_v6_to_v7 (transaction_a);
 | 
					 | 
				
			||||||
		case 7:
 | 
							case 7:
 | 
				
			||||||
			upgrade_v7_to_v8 (transaction_a);
 | 
					 | 
				
			||||||
		case 8:
 | 
							case 8:
 | 
				
			||||||
			upgrade_v8_to_v9 (transaction_a);
 | 
					 | 
				
			||||||
		case 9:
 | 
							case 9:
 | 
				
			||||||
		case 10:
 | 
							case 10:
 | 
				
			||||||
			upgrade_v10_to_v11 (transaction_a);
 | 
					 | 
				
			||||||
		case 11:
 | 
							case 11:
 | 
				
			||||||
			upgrade_v11_to_v12 (transaction_a);
 | 
					 | 
				
			||||||
		case 12:
 | 
							case 12:
 | 
				
			||||||
			upgrade_v12_to_v13 (transaction_a, batch_size_a);
 | 
					 | 
				
			||||||
		case 13:
 | 
							case 13:
 | 
				
			||||||
			upgrade_v13_to_v14 (transaction_a);
 | 
								logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is lower than the minimum (%2%) which is supported for upgrades. Either upgrade to a v19, v20 or v21 node first or delete the ledger.") % version_l % minimum_version));
 | 
				
			||||||
 | 
								error = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 14:
 | 
							case 14:
 | 
				
			||||||
			upgrade_v14_to_v15 (transaction_a);
 | 
								upgrade_v14_to_v15 (transaction_a);
 | 
				
			||||||
			needs_vacuuming = true;
 | 
								needs_vacuuming = true;
 | 
				
			||||||
| 
						 | 
					@ -270,312 +256,6 @@ bool nano::mdb_store::do_upgrades (nano::write_transaction & transaction_a, bool
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::mdb_store::upgrade_v1_to_v2 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 2);
 | 
					 | 
				
			||||||
	nano::account account (1);
 | 
					 | 
				
			||||||
	while (!account.is_zero ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::mdb_iterator<nano::account, nano::account_info_v1> i (transaction_a, accounts_v0, nano::mdb_val (account));
 | 
					 | 
				
			||||||
		std::cerr << std::hex;
 | 
					 | 
				
			||||||
		if (i != nano::mdb_iterator<nano::account, nano::account_info_v1>{})
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			account = nano::account (i->first);
 | 
					 | 
				
			||||||
			nano::account_info_v1 v1 (i->second);
 | 
					 | 
				
			||||||
			nano::account_info_v5 v2;
 | 
					 | 
				
			||||||
			v2.balance = v1.balance;
 | 
					 | 
				
			||||||
			v2.head = v1.head;
 | 
					 | 
				
			||||||
			v2.modified = v1.modified;
 | 
					 | 
				
			||||||
			v2.rep_block = v1.rep_block;
 | 
					 | 
				
			||||||
			auto block (block_get (transaction_a, v1.head));
 | 
					 | 
				
			||||||
			while (!block->previous ().is_zero ())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				block = block_get (transaction_a, block->previous ());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			v2.open_block = block->hash ();
 | 
					 | 
				
			||||||
			auto status (mdb_put (env.tx (transaction_a), accounts_v0, nano::mdb_val (account), nano::mdb_val (sizeof (v2), &v2), 0));
 | 
					 | 
				
			||||||
			release_assert (status == 0);
 | 
					 | 
				
			||||||
			account = account.number () + 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			account.clear ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v2_to_v3 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 3);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), representation, 0);
 | 
					 | 
				
			||||||
	for (auto i (std::make_unique<nano::mdb_iterator<nano::account, nano::account_info_v5>> (transaction_a, accounts_v0)), n (std::make_unique<nano::mdb_iterator<nano::account, nano::account_info_v5>> ()); *i != *n; ++(*i))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account account_l ((*i)->first);
 | 
					 | 
				
			||||||
		nano::account_info_v5 info ((*i)->second);
 | 
					 | 
				
			||||||
		representative_visitor visitor (transaction_a, *this);
 | 
					 | 
				
			||||||
		visitor.compute (info.head);
 | 
					 | 
				
			||||||
		debug_assert (!visitor.result.is_zero ());
 | 
					 | 
				
			||||||
		info.rep_block = visitor.result;
 | 
					 | 
				
			||||||
		auto impl (boost::polymorphic_downcast<nano::mdb_iterator<nano::account, nano::account_info_v5> *> (i.get ()));
 | 
					 | 
				
			||||||
		mdb_cursor_put (impl->cursor, nano::mdb_val (account_l), nano::mdb_val (sizeof (info), &info), MDB_CURRENT);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v3_to_v4 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 4);
 | 
					 | 
				
			||||||
	std::queue<std::pair<nano::pending_key, nano::pending_info_v14>> items;
 | 
					 | 
				
			||||||
	for (auto i (nano::store_iterator<nano::block_hash, nano::pending_info_v3> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::pending_info_v3>> (transaction_a, pending_v0))), n (nano::store_iterator<nano::block_hash, nano::pending_info_v3> (nullptr)); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::block_hash const & hash (i->first);
 | 
					 | 
				
			||||||
		nano::pending_info_v3 const & info (i->second);
 | 
					 | 
				
			||||||
		items.emplace (nano::pending_key (info.destination, hash), nano::pending_info_v14 (info.source, info.amount, nano::epoch::epoch_0));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), pending_v0, 0);
 | 
					 | 
				
			||||||
	while (!items.empty ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto status (mdb_put (env.tx (transaction_a), pending, nano::mdb_val (items.front ().first), nano::mdb_val (items.front ().second), 0));
 | 
					 | 
				
			||||||
		debug_assert (success (status));
 | 
					 | 
				
			||||||
		items.pop ();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v4_to_v5 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 5);
 | 
					 | 
				
			||||||
	for (auto i (nano::store_iterator<nano::account, nano::account_info_v5> (std::make_unique<nano::mdb_iterator<nano::account, nano::account_info_v5>> (transaction_a, accounts_v0))), n (nano::store_iterator<nano::account, nano::account_info_v5> (nullptr)); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account_info_v5 const & info (i->second);
 | 
					 | 
				
			||||||
		nano::block_hash successor (0);
 | 
					 | 
				
			||||||
		auto block (block_get (transaction_a, info.head));
 | 
					 | 
				
			||||||
		while (block != nullptr)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto hash (block->hash ());
 | 
					 | 
				
			||||||
			if (block_successor (transaction_a, hash).is_zero () && !successor.is_zero ())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				std::vector<uint8_t> vector;
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					nano::vectorstream stream (vector);
 | 
					 | 
				
			||||||
					block->serialize (stream);
 | 
					 | 
				
			||||||
					nano::write (stream, successor.bytes);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				block_raw_put (transaction_a, vector, block->type (), hash);
 | 
					 | 
				
			||||||
				if (!block->previous ().is_zero ())
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					nano::block_type type;
 | 
					 | 
				
			||||||
					auto value (block_raw_get (transaction_a, block->previous (), type));
 | 
					 | 
				
			||||||
					debug_assert (value.size () != 0);
 | 
					 | 
				
			||||||
					std::vector<uint8_t> data (static_cast<uint8_t *> (value.data ()), static_cast<uint8_t *> (value.data ()) + value.size ());
 | 
					 | 
				
			||||||
					std::copy (hash.bytes.begin (), hash.bytes.end (), data.end () - nano::block_sideband::size (type));
 | 
					 | 
				
			||||||
					block_raw_put (transaction_a, data, type, block->previous ());
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			successor = hash;
 | 
					 | 
				
			||||||
			block = block_get (transaction_a, block->previous ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v5_to_v6 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 6);
 | 
					 | 
				
			||||||
	std::deque<std::pair<nano::account, nano::account_info_v13>> headers;
 | 
					 | 
				
			||||||
	for (auto i (nano::store_iterator<nano::account, nano::account_info_v5> (std::make_unique<nano::mdb_iterator<nano::account, nano::account_info_v5>> (transaction_a, accounts_v0))), n (nano::store_iterator<nano::account, nano::account_info_v5> (nullptr)); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account const & account (i->first);
 | 
					 | 
				
			||||||
		nano::account_info_v5 info_old (i->second);
 | 
					 | 
				
			||||||
		uint64_t block_count (0);
 | 
					 | 
				
			||||||
		auto hash (info_old.head);
 | 
					 | 
				
			||||||
		while (!hash.is_zero ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			++block_count;
 | 
					 | 
				
			||||||
			auto block (block_get (transaction_a, hash));
 | 
					 | 
				
			||||||
			debug_assert (block != nullptr);
 | 
					 | 
				
			||||||
			hash = block->previous ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		headers.emplace_back (account, nano::account_info_v13{ info_old.head, info_old.rep_block, info_old.open_block, info_old.balance, info_old.modified, block_count, nano::epoch::epoch_0 });
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for (auto i (headers.begin ()), n (headers.end ()); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto status (mdb_put (env.tx (transaction_a), accounts_v0, nano::mdb_val (i->first), nano::mdb_val (i->second), 0));
 | 
					 | 
				
			||||||
		release_assert (status == 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v6_to_v7 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 7);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), unchecked, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v7_to_v8 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 8);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), unchecked, 1);
 | 
					 | 
				
			||||||
	mdb_dbi_open (env.tx (transaction_a), "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v8_to_v9 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 9);
 | 
					 | 
				
			||||||
	MDB_dbi sequence;
 | 
					 | 
				
			||||||
	mdb_dbi_open (env.tx (transaction_a), "sequence", MDB_CREATE | MDB_DUPSORT, &sequence);
 | 
					 | 
				
			||||||
	nano::genesis genesis;
 | 
					 | 
				
			||||||
	std::shared_ptr<nano::block> block (std::move (genesis.open));
 | 
					 | 
				
			||||||
	nano::keypair junk;
 | 
					 | 
				
			||||||
	for (nano::mdb_iterator<nano::account, uint64_t> i (transaction_a, sequence), n (nano::mdb_iterator<nano::account, uint64_t>{}); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::bufferstream stream (reinterpret_cast<uint8_t const *> (i->second.data ()), i->second.size ());
 | 
					 | 
				
			||||||
		uint64_t sequence;
 | 
					 | 
				
			||||||
		auto error (nano::try_read (stream, sequence));
 | 
					 | 
				
			||||||
		(void)error;
 | 
					 | 
				
			||||||
		// Create a dummy vote with the same sequence number for easy upgrading.  This won't have a valid signature.
 | 
					 | 
				
			||||||
		nano::vote dummy (nano::account (i->first), junk.prv, sequence, block);
 | 
					 | 
				
			||||||
		std::vector<uint8_t> vector;
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			nano::vectorstream stream (vector);
 | 
					 | 
				
			||||||
			dummy.serialize (stream);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		auto status1 (mdb_put (env.tx (transaction_a), vote, nano::mdb_val (i->first), nano::mdb_val (vector.size (), vector.data ()), 0));
 | 
					 | 
				
			||||||
		release_assert (status1 == 0);
 | 
					 | 
				
			||||||
		debug_assert (!error);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), sequence, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v10_to_v11 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 11);
 | 
					 | 
				
			||||||
	MDB_dbi unsynced;
 | 
					 | 
				
			||||||
	mdb_dbi_open (env.tx (transaction_a), "unsynced", MDB_CREATE | MDB_DUPSORT, &unsynced);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), unsynced, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v11_to_v12 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	version_put (transaction_a, 12);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), unchecked, 1);
 | 
					 | 
				
			||||||
	mdb_dbi_open (env.tx (transaction_a), "unchecked", MDB_CREATE, &unchecked);
 | 
					 | 
				
			||||||
	MDB_dbi checksum;
 | 
					 | 
				
			||||||
	mdb_dbi_open (env.tx (transaction_a), "checksum", MDB_CREATE, &checksum);
 | 
					 | 
				
			||||||
	mdb_drop (env.tx (transaction_a), checksum, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v12_to_v13 (nano::write_transaction & transaction_a, size_t const batch_size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	size_t cost (0);
 | 
					 | 
				
			||||||
	nano::account account (0);
 | 
					 | 
				
			||||||
	auto const & not_an_account (network_params.random.not_an_account);
 | 
					 | 
				
			||||||
	while (account != not_an_account)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account first (0);
 | 
					 | 
				
			||||||
		nano::account_info_v13 second;
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			nano::mdb_merge_iterator<nano::account, nano::account_info_v13> current (transaction_a, accounts_v0, accounts_v1, nano::mdb_val (account));
 | 
					 | 
				
			||||||
			nano::mdb_merge_iterator<nano::account, nano::account_info_v13> end{};
 | 
					 | 
				
			||||||
			if (current != end)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				first = nano::account (current->first);
 | 
					 | 
				
			||||||
				second = nano::account_info_v13 (current->second);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (!first.is_zero ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto hash (second.open_block);
 | 
					 | 
				
			||||||
			uint64_t height (1);
 | 
					 | 
				
			||||||
			nano::block_sideband_v14 sideband;
 | 
					 | 
				
			||||||
			while (!hash.is_zero ())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (cost >= batch_size)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					logger.always_log (boost::str (boost::format ("Upgrading sideband information for account %1%... height %2%") % first.to_account ().substr (0, 24) % std::to_string (height)));
 | 
					 | 
				
			||||||
					transaction_a.commit ();
 | 
					 | 
				
			||||||
					std::this_thread::yield ();
 | 
					 | 
				
			||||||
					transaction_a.renew ();
 | 
					 | 
				
			||||||
					cost = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				bool is_state_block_v1 = false;
 | 
					 | 
				
			||||||
				auto block = block_get_v14 (transaction_a, hash, &sideband, &is_state_block_v1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				debug_assert (block != nullptr);
 | 
					 | 
				
			||||||
				if (sideband.height == 0)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					sideband.height = height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					std::vector<uint8_t> vector;
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						nano::vectorstream stream (vector);
 | 
					 | 
				
			||||||
						block->serialize (stream);
 | 
					 | 
				
			||||||
						sideband.serialize (stream);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					nano::mdb_val value{ vector.size (), (void *)vector.data () };
 | 
					 | 
				
			||||||
					MDB_dbi database = is_state_block_v1 ? state_blocks_v1 : table_to_dbi (block_database (block->type ()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					auto status = mdb_put (env.tx (transaction_a), database, nano::mdb_val (hash), value, 0);
 | 
					 | 
				
			||||||
					release_assert (success (status));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					nano::block_predecessor_set<MDB_val, nano::mdb_store> predecessor (transaction_a, *this);
 | 
					 | 
				
			||||||
					block->visit (predecessor);
 | 
					 | 
				
			||||||
					debug_assert (block->previous ().is_zero () || block_successor (transaction_a, block->previous ()) == hash);
 | 
					 | 
				
			||||||
					cost += 16;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					cost += 1;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				hash = sideband.successor;
 | 
					 | 
				
			||||||
				++height;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			account = first.number () + 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			account = not_an_account;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (account == not_an_account)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		logger.always_log ("Completed sideband upgrade");
 | 
					 | 
				
			||||||
		version_put (transaction_a, 13);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v13_to_v14 (nano::write_transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Upgrade all accounts to have a confirmation of 0 (except genesis which should have 1)
 | 
					 | 
				
			||||||
	version_put (transaction_a, 14);
 | 
					 | 
				
			||||||
	nano::mdb_merge_iterator<nano::account, nano::account_info_v13> i (transaction_a, accounts_v0, accounts_v1);
 | 
					 | 
				
			||||||
	nano::mdb_merge_iterator<nano::account, nano::account_info_v13> n{};
 | 
					 | 
				
			||||||
	std::vector<std::pair<nano::account, nano::account_info_v14>> account_infos;
 | 
					 | 
				
			||||||
	account_infos.reserve (count (transaction_a, accounts_v0) + count (transaction_a, accounts_v1));
 | 
					 | 
				
			||||||
	for (; i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account account (i->first);
 | 
					 | 
				
			||||||
		nano::account_info_v13 account_info_v13 (i->second);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		uint64_t confirmation_height = 0;
 | 
					 | 
				
			||||||
		if (account == network_params.ledger.genesis_account)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			confirmation_height = 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		account_infos.emplace_back (account, nano::account_info_v14{ account_info_v13.head, account_info_v13.rep_block, account_info_v13.open_block, account_info_v13.balance, account_info_v13.modified, account_info_v13.block_count, confirmation_height, i.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1 });
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (auto const & account_info : account_infos)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto status1 (mdb_put (env.tx (transaction_a), account_info.second.epoch == nano::epoch::epoch_0 ? accounts_v0 : accounts_v1, nano::mdb_val (account_info.first), nano::mdb_val (account_info.second), 0));
 | 
					 | 
				
			||||||
		release_assert (status1 == 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	logger.always_log ("Completed confirmation height upgrade");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::uint256_union node_id_mdb_key (3);
 | 
					 | 
				
			||||||
	auto error (mdb_del (env.tx (transaction_a), meta, nano::mdb_val (node_id_mdb_key), nullptr));
 | 
					 | 
				
			||||||
	release_assert (!error || error == MDB_NOTFOUND);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::mdb_store::upgrade_v14_to_v15 (nano::write_transaction & transaction_a)
 | 
					void nano::mdb_store::upgrade_v14_to_v15 (nano::write_transaction & transaction_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	logger.always_log ("Preparing v14 to v15 database upgrade...");
 | 
						logger.always_log ("Preparing v14 to v15 database upgrade...");
 | 
				
			||||||
| 
						 | 
					@ -885,39 +565,6 @@ void nano::mdb_store::version_put (nano::write_transaction const & transaction_a
 | 
				
			||||||
	nano::uint256_union version_value (version_a);
 | 
						nano::uint256_union version_value (version_a);
 | 
				
			||||||
	auto status (mdb_put (env.tx (transaction_a), meta, nano::mdb_val (version_key), nano::mdb_val (version_value), 0));
 | 
						auto status (mdb_put (env.tx (transaction_a), meta, nano::mdb_val (version_key), nano::mdb_val (version_value), 0));
 | 
				
			||||||
	release_assert (status == 0);
 | 
						release_assert (status == 0);
 | 
				
			||||||
	if (blocks_info == 0 && !full_sideband (transaction_a))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto status (mdb_dbi_open (env.tx (transaction_a), "blocks_info", MDB_CREATE, &blocks_info));
 | 
					 | 
				
			||||||
		release_assert (status == MDB_SUCCESS);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (blocks_info != 0 && full_sideband (transaction_a))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto status (mdb_drop (env.tx (transaction_a), blocks_info, 1));
 | 
					 | 
				
			||||||
		release_assert (status == MDB_SUCCESS);
 | 
					 | 
				
			||||||
		blocks_info = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool nano::mdb_store::block_info_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_info & block_info_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (!full_sideband (transaction_a));
 | 
					 | 
				
			||||||
	nano::mdb_val value;
 | 
					 | 
				
			||||||
	auto status (mdb_get (env.tx (transaction_a), blocks_info, nano::mdb_val (hash_a), value));
 | 
					 | 
				
			||||||
	release_assert (status == 0 || status == MDB_NOTFOUND);
 | 
					 | 
				
			||||||
	bool result (true);
 | 
					 | 
				
			||||||
	if (status != MDB_NOTFOUND)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		result = false;
 | 
					 | 
				
			||||||
		debug_assert (value.size () == sizeof (block_info_a.account.bytes) + sizeof (block_info_a.balance.bytes));
 | 
					 | 
				
			||||||
		nano::bufferstream stream (reinterpret_cast<uint8_t const *> (value.data ()), value.size ());
 | 
					 | 
				
			||||||
		auto error1 (nano::try_read (stream, block_info_a.account));
 | 
					 | 
				
			||||||
		(void)error1;
 | 
					 | 
				
			||||||
		debug_assert (!error1);
 | 
					 | 
				
			||||||
		auto error2 (nano::try_read (stream, block_info_a.balance));
 | 
					 | 
				
			||||||
		(void)error2;
 | 
					 | 
				
			||||||
		debug_assert (!error2);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool nano::mdb_store::exists (nano::transaction const & transaction_a, tables table_a, nano::mdb_val const & key_a) const
 | 
					bool nano::mdb_store::exists (nano::transaction const & transaction_a, tables table_a, nano::mdb_val const & key_a) const
 | 
				
			||||||
| 
						 | 
					@ -986,8 +633,6 @@ MDB_dbi nano::mdb_store::table_to_dbi (tables table_a) const
 | 
				
			||||||
			return state_blocks;
 | 
								return state_blocks;
 | 
				
			||||||
		case tables::pending:
 | 
							case tables::pending:
 | 
				
			||||||
			return pending;
 | 
								return pending;
 | 
				
			||||||
		case tables::blocks_info:
 | 
					 | 
				
			||||||
			return blocks_info;
 | 
					 | 
				
			||||||
		case tables::unchecked:
 | 
							case tables::unchecked:
 | 
				
			||||||
			return unchecked;
 | 
								return unchecked;
 | 
				
			||||||
		case tables::vote:
 | 
							case tables::vote:
 | 
				
			||||||
| 
						 | 
					@ -1082,25 +727,9 @@ bool nano::mdb_store::init_error () const
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// All the v14 functions below are only needed during upgrades
 | 
					// All the v14 functions below are only needed during upgrades
 | 
				
			||||||
bool nano::mdb_store::entry_has_sideband_v14 (size_t entry_size_a, nano::block_type type_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (entry_size_a == nano::block::size (type_a) + nano::block_sideband_v14::size (type_a));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
size_t nano::mdb_store::block_successor_offset_v14 (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const
 | 
					size_t nano::mdb_store::block_successor_offset_v14 (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t result;
 | 
						return entry_size_a - nano::block_sideband_v14::size (type_a);
 | 
				
			||||||
	if (full_sideband (transaction_a) || entry_has_sideband_v14 (entry_size_a, type_a))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		result = entry_size_a - nano::block_sideband_v14::size (type_a);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// Read old successor-only sideband
 | 
					 | 
				
			||||||
		debug_assert (entry_size_a == nano::block::size (type_a) + sizeof (nano::uint256_union));
 | 
					 | 
				
			||||||
		result = entry_size_a - sizeof (nano::uint256_union);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::block_hash nano::mdb_store::block_successor_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					nano::block_hash nano::mdb_store::block_successor_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
				
			||||||
| 
						 | 
					@ -1198,69 +827,6 @@ boost::optional<nano::mdb_val> nano::mdb_store::block_raw_get_by_type_v14 (nano:
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::account nano::mdb_store::block_account_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::block_sideband_v14 sideband;
 | 
					 | 
				
			||||||
	auto block (block_get_v14 (transaction_a, hash_a, &sideband));
 | 
					 | 
				
			||||||
	nano::account result (block->account ());
 | 
					 | 
				
			||||||
	if (result.is_zero ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		result = sideband.account;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	debug_assert (!result.is_zero ());
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Return account containing hash
 | 
					 | 
				
			||||||
nano::account nano::mdb_store::block_account_computed_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (!full_sideband (transaction_a));
 | 
					 | 
				
			||||||
	nano::account result (0);
 | 
					 | 
				
			||||||
	auto hash (hash_a);
 | 
					 | 
				
			||||||
	while (result.is_zero ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto block (block_get_v14 (transaction_a, hash));
 | 
					 | 
				
			||||||
		debug_assert (block);
 | 
					 | 
				
			||||||
		result = block->account ();
 | 
					 | 
				
			||||||
		if (result.is_zero ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto type (nano::block_type::invalid);
 | 
					 | 
				
			||||||
			auto value (block_raw_get_v14 (transaction_a, block->previous (), type));
 | 
					 | 
				
			||||||
			if (entry_has_sideband_v14 (value.size (), type))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				result = block_account_v14 (transaction_a, block->previous ());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				nano::block_info block_info;
 | 
					 | 
				
			||||||
				if (!block_info_get (transaction_a, hash, block_info))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					result = block_info.account;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					result = frontier_get (transaction_a, hash);
 | 
					 | 
				
			||||||
					if (result.is_zero ())
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						auto successor (block_successor_v14 (transaction_a, hash));
 | 
					 | 
				
			||||||
						debug_assert (!successor.is_zero ());
 | 
					 | 
				
			||||||
						hash = successor;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	debug_assert (!result.is_zero ());
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::uint128_t nano::mdb_store::block_balance_computed_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (!full_sideband (transaction_a));
 | 
					 | 
				
			||||||
	summation_visitor visitor (transaction_a, *this, true);
 | 
					 | 
				
			||||||
	return visitor.compute_balance (hash_a);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::shared_ptr<nano::block> nano::mdb_store::block_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_sideband_v14 * sideband_a, bool * is_state_v1) const
 | 
					std::shared_ptr<nano::block> nano::mdb_store::block_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_sideband_v14 * sideband_a, bool * is_state_v1) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::block_type type;
 | 
						nano::block_type type;
 | 
				
			||||||
| 
						 | 
					@ -1274,21 +840,9 @@ std::shared_ptr<nano::block> nano::mdb_store::block_get_v14 (nano::transaction c
 | 
				
			||||||
		if (sideband_a)
 | 
							if (sideband_a)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			sideband_a->type = type;
 | 
								sideband_a->type = type;
 | 
				
			||||||
			if (full_sideband (transaction_a) || entry_has_sideband_v14 (value.size (), type))
 | 
								bool error = sideband_a->deserialize (stream);
 | 
				
			||||||
			{
 | 
								(void)error;
 | 
				
			||||||
				bool error = sideband_a->deserialize (stream);
 | 
								debug_assert (!error);
 | 
				
			||||||
				(void)error;
 | 
					 | 
				
			||||||
				debug_assert (!error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// Reconstruct sideband data for block.
 | 
					 | 
				
			||||||
				sideband_a->account = block_account_computed_v14 (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband_a->balance = block_balance_computed_v14 (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband_a->successor = block_successor_v14 (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband_a->height = 0;
 | 
					 | 
				
			||||||
				sideband_a->timestamp = 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,14 +37,12 @@ public:
 | 
				
			||||||
	using block_store_partial::block_exists;
 | 
						using block_store_partial::block_exists;
 | 
				
			||||||
	using block_store_partial::unchecked_put;
 | 
						using block_store_partial::unchecked_put;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mdb_store (nano::logger_mt &, boost::filesystem::path const &, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, size_t batch_size = 512, bool backup_before_upgrade = false);
 | 
						mdb_store (nano::logger_mt &, boost::filesystem::path const &, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false);
 | 
				
			||||||
	nano::write_transaction tx_begin_write (std::vector<nano::tables> const & tables_requiring_lock = {}, std::vector<nano::tables> const & tables_no_lock = {}) override;
 | 
						nano::write_transaction tx_begin_write (std::vector<nano::tables> const & tables_requiring_lock = {}, std::vector<nano::tables> const & tables_no_lock = {}) override;
 | 
				
			||||||
	nano::read_transaction tx_begin_read () override;
 | 
						nano::read_transaction tx_begin_read () override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::string vendor_get () const override;
 | 
						std::string vendor_get () const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool block_info_get (nano::transaction const &, nano::block_hash const &, nano::block_info &) const override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void version_put (nano::write_transaction const &, int) override;
 | 
						void version_put (nano::write_transaction const &, int) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void serialize_mdb_tracker (boost::property_tree::ptree &, std::chrono::milliseconds, std::chrono::milliseconds) override;
 | 
						void serialize_mdb_tracker (boost::property_tree::ptree &, std::chrono::milliseconds, std::chrono::milliseconds) override;
 | 
				
			||||||
| 
						 | 
					@ -77,7 +75,7 @@ public:
 | 
				
			||||||
	MDB_dbi accounts_v1{ 0 };
 | 
						MDB_dbi accounts_v1{ 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch. (Removed)
 | 
						 * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch
 | 
				
			||||||
	 * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch
 | 
						 * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	MDB_dbi accounts{ 0 };
 | 
						MDB_dbi accounts{ 0 };
 | 
				
			||||||
| 
						 | 
					@ -142,12 +140,6 @@ public:
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	MDB_dbi pending{ 0 };
 | 
						MDB_dbi pending{ 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Maps block hash to account and balance. (Removed)
 | 
					 | 
				
			||||||
	 * block_hash -> nano::account, nano::amount
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	MDB_dbi blocks_info{ 0 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Representative weights. (Removed)
 | 
						 * Representative weights. (Removed)
 | 
				
			||||||
	 * nano::account -> nano::uint128_t
 | 
						 * nano::account -> nano::uint128_t
 | 
				
			||||||
| 
						 | 
					@ -217,29 +209,13 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// These are only use in the upgrade process.
 | 
						// These are only use in the upgrade process.
 | 
				
			||||||
	std::shared_ptr<nano::block> block_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_sideband_v14 * sideband_a = nullptr, bool * is_state_v1 = nullptr) const override;
 | 
						std::shared_ptr<nano::block> block_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_sideband_v14 * sideband_a = nullptr, bool * is_state_v1 = nullptr) const override;
 | 
				
			||||||
	bool entry_has_sideband_v14 (size_t entry_size_a, nano::block_type type_a) const;
 | 
					 | 
				
			||||||
	size_t block_successor_offset_v14 (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const;
 | 
						size_t block_successor_offset_v14 (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const;
 | 
				
			||||||
	nano::block_hash block_successor_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
 | 
						nano::block_hash block_successor_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
 | 
				
			||||||
	nano::mdb_val block_raw_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1 = nullptr) const;
 | 
						nano::mdb_val block_raw_get_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1 = nullptr) const;
 | 
				
			||||||
	boost::optional<nano::mdb_val> block_raw_get_by_type_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1) const;
 | 
						boost::optional<nano::mdb_val> block_raw_get_by_type_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1) const;
 | 
				
			||||||
	nano::account block_account_computed_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
 | 
					 | 
				
			||||||
	nano::account block_account_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
 | 
					 | 
				
			||||||
	nano::uint128_t block_balance_computed_v14 (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	bool do_upgrades (nano::write_transaction &, bool &, size_t);
 | 
						bool do_upgrades (nano::write_transaction &, bool &);
 | 
				
			||||||
	void upgrade_v1_to_v2 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v2_to_v3 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v3_to_v4 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v4_to_v5 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v5_to_v6 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v6_to_v7 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v7_to_v8 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v8_to_v9 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v10_to_v11 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v11_to_v12 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v12_to_v13 (nano::write_transaction &, size_t);
 | 
					 | 
				
			||||||
	void upgrade_v13_to_v14 (nano::write_transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v14_to_v15 (nano::write_transaction &);
 | 
						void upgrade_v14_to_v15 (nano::write_transaction &);
 | 
				
			||||||
	void upgrade_v15_to_v16 (nano::write_transaction const &);
 | 
						void upgrade_v15_to_v16 (nano::write_transaction const &);
 | 
				
			||||||
	void upgrade_v16_to_v17 (nano::write_transaction const &);
 | 
						void upgrade_v16_to_v17 (nano::write_transaction const &);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,26 +226,12 @@ bool nano::logging::upgrade_json (unsigned version_a, nano::jsonconfig & json)
 | 
				
			||||||
	switch (version_a)
 | 
						switch (version_a)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
			json.put ("vote", vote_logging_value);
 | 
					 | 
				
			||||||
		case 2:
 | 
							case 2:
 | 
				
			||||||
			json.put ("rotation_size", rotation_size);
 | 
					 | 
				
			||||||
			json.put ("flush", true);
 | 
					 | 
				
			||||||
		case 3:
 | 
							case 3:
 | 
				
			||||||
			json.put ("network_node_id_handshake", false);
 | 
					 | 
				
			||||||
		case 4:
 | 
							case 4:
 | 
				
			||||||
			json.put ("upnp_details", "false");
 | 
					 | 
				
			||||||
			json.put ("timing", "false");
 | 
					 | 
				
			||||||
		case 5:
 | 
							case 5:
 | 
				
			||||||
			uintmax_t config_max_size;
 | 
					 | 
				
			||||||
			json.get<uintmax_t> ("max_size", config_max_size);
 | 
					 | 
				
			||||||
			max_size = std::max (max_size, config_max_size);
 | 
					 | 
				
			||||||
			json.put ("max_size", max_size);
 | 
					 | 
				
			||||||
			json.put ("log_ipc", true);
 | 
					 | 
				
			||||||
		case 6:
 | 
							case 6:
 | 
				
			||||||
			json.put ("min_time_between_output", min_time_between_log_output.count ());
 | 
								throw std::runtime_error ("logging_config version is unsupported for upgrade. Upgrade to a v19, v20 or v21 node first, or delete the config and ledger files");
 | 
				
			||||||
			json.put ("network_timeout", network_timeout_logging_value);
 | 
					 | 
				
			||||||
			json.erase ("log_rpc");
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 7:
 | 
							case 7:
 | 
				
			||||||
			json.put ("single_line_record", single_line_record_value);
 | 
								json.put ("single_line_record", single_line_record_value);
 | 
				
			||||||
		case 8:
 | 
							case 8:
 | 
				
			||||||
| 
						 | 
					@ -260,23 +246,7 @@ bool nano::logging::upgrade_json (unsigned version_a, nano::jsonconfig & json)
 | 
				
			||||||
nano::error nano::logging::deserialize_json (bool & upgraded_a, nano::jsonconfig & json)
 | 
					nano::error nano::logging::deserialize_json (bool & upgraded_a, nano::jsonconfig & json)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int version_l{ 1 };
 | 
						int version_l{ 1 };
 | 
				
			||||||
	if (!json.has_key ("version"))
 | 
						json.get_required<int> ("version", version_l);
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		json.put ("version", version_l);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto work_peers_l (json.get_optional_child ("work_peers"));
 | 
					 | 
				
			||||||
		if (!work_peers_l)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			nano::jsonconfig peers;
 | 
					 | 
				
			||||||
			json.put_child ("work_peers", peers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		upgraded_a = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		json.get_required<int> ("version", version_l);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	upgraded_a |= upgrade_json (version_l, json);
 | 
						upgraded_a |= upgrade_json (version_l, json);
 | 
				
			||||||
	json.get<bool> ("ledger", ledger_logging_value);
 | 
						json.get<bool> ("ledger", ledger_logging_value);
 | 
				
			||||||
	json.get<bool> ("ledger_duplicate", ledger_duplicate_logging_value);
 | 
						json.get<bool> ("ledger_duplicate", ledger_duplicate_logging_value);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ alarm (alarm_a),
 | 
				
			||||||
work (work_a),
 | 
					work (work_a),
 | 
				
			||||||
distributed_work (*this),
 | 
					distributed_work (*this),
 | 
				
			||||||
logger (config_a.logging.min_time_between_log_output),
 | 
					logger (config_a.logging.min_time_between_log_output),
 | 
				
			||||||
store_impl (nano::make_store (logger, application_path_a, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, flags.sideband_batch_size, config_a.backup_before_upgrade, config_a.rocksdb_config.enable)),
 | 
					store_impl (nano::make_store (logger, application_path_a, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade, config_a.rocksdb_config.enable)),
 | 
				
			||||||
store (*store_impl),
 | 
					store (*store_impl),
 | 
				
			||||||
wallets_store_impl (std::make_unique<nano::mdb_wallets_store> (application_path_a / "wallets.ldb", config_a.lmdb_config)),
 | 
					wallets_store_impl (std::make_unique<nano::mdb_wallets_store> (application_path_a / "wallets.ldb", config_a.lmdb_config)),
 | 
				
			||||||
wallets_store (*wallets_store_impl),
 | 
					wallets_store (*wallets_store_impl),
 | 
				
			||||||
| 
						 | 
					@ -1694,7 +1694,7 @@ nano::node_flags const & nano::inactive_node_flag_defaults ()
 | 
				
			||||||
	return node_flags;
 | 
						return node_flags;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<nano::block_store> nano::make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool read_only, bool add_db_postfix, nano::rocksdb_config const & rocksdb_config, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, size_t batch_size, bool backup_before_upgrade, bool use_rocksdb_backend)
 | 
					std::unique_ptr<nano::block_store> nano::make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool read_only, bool add_db_postfix, nano::rocksdb_config const & rocksdb_config, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, nano::lmdb_config const & lmdb_config_a, bool backup_before_upgrade, bool use_rocksdb_backend)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if NANO_ROCKSDB
 | 
					#if NANO_ROCKSDB
 | 
				
			||||||
	auto make_rocksdb = [&logger, add_db_postfix, &path, &rocksdb_config, read_only]() {
 | 
						auto make_rocksdb = [&logger, add_db_postfix, &path, &rocksdb_config, read_only]() {
 | 
				
			||||||
| 
						 | 
					@ -1725,5 +1725,5 @@ std::unique_ptr<nano::block_store> nano::make_store (nano::logger_mt & logger, b
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return std::make_unique<nano::mdb_store> (logger, add_db_postfix ? path / "data.ldb" : path, txn_tracking_config_a, block_processor_batch_max_time_a, lmdb_config_a, batch_size, backup_before_upgrade);
 | 
						return std::make_unique<nano::mdb_store> (logger, add_db_postfix ? path / "data.ldb" : path, txn_tracking_config_a, block_processor_batch_max_time_a, lmdb_config_a, backup_before_upgrade);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,39 +43,6 @@ nano::error nano::node_rpc_config::deserialize_toml (nano::tomlconfig & toml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::error nano::node_rpc_config::deserialize_json (bool & upgraded_a, nano::jsonconfig & json, boost::filesystem::path const & data_path)
 | 
					nano::error nano::node_rpc_config::deserialize_json (bool & upgraded_a, nano::jsonconfig & json, boost::filesystem::path const & data_path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto version_l (json.get_optional<unsigned> ("version"));
 | 
					 | 
				
			||||||
	if (!version_l)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		json.erase ("frontier_request_limit");
 | 
					 | 
				
			||||||
		json.erase ("chain_request_limit");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Don't migrate enable_sign_hash as this is not needed by the external rpc process, but first save it.
 | 
					 | 
				
			||||||
		json.get_optional ("enable_sign_hash", enable_sign_hash, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		json.erase ("enable_sign_hash");
 | 
					 | 
				
			||||||
		json.erase ("max_work_generate_difficulty");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		migrate (json, data_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		json.put ("enable_sign_hash", enable_sign_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Remove options no longer needed after migration
 | 
					 | 
				
			||||||
		json.erase ("enable_control");
 | 
					 | 
				
			||||||
		json.erase ("address");
 | 
					 | 
				
			||||||
		json.erase ("port");
 | 
					 | 
				
			||||||
		json.erase ("max_json_depth");
 | 
					 | 
				
			||||||
		json.erase ("max_request_size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		version_l = 1;
 | 
					 | 
				
			||||||
		json.put ("version", *version_l);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		nano::jsonconfig child_process_l;
 | 
					 | 
				
			||||||
		child_process_l.put ("enable", child_process.enable);
 | 
					 | 
				
			||||||
		child_process_l.put ("rpc_path", child_process.rpc_path);
 | 
					 | 
				
			||||||
		json.put_child ("child_process", child_process_l);
 | 
					 | 
				
			||||||
		upgraded_a = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	json.get_optional<bool> ("enable_sign_hash", enable_sign_hash);
 | 
						json.get_optional<bool> ("enable_sign_hash", enable_sign_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto child_process_l (json.get_optional_child ("child_process"));
 | 
						auto child_process_l (json.get_optional_child ("child_process"));
 | 
				
			||||||
| 
						 | 
					@ -87,15 +54,3 @@ nano::error nano::node_rpc_config::deserialize_json (bool & upgraded_a, nano::js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return json.get_error ();
 | 
						return json.get_error ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::node_rpc_config::migrate (nano::jsonconfig & json, boost::filesystem::path const & data_path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::jsonconfig rpc_json;
 | 
					 | 
				
			||||||
	auto rpc_config_path = nano::get_rpc_config_path (data_path);
 | 
					 | 
				
			||||||
	auto rpc_error (rpc_json.read (rpc_config_path));
 | 
					 | 
				
			||||||
	if (rpc_error || rpc_json.empty ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// Migrate RPC info across
 | 
					 | 
				
			||||||
		json.write (rpc_config_path);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,8 +36,5 @@ public:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	void migrate (nano::jsonconfig & json, boost::filesystem::path const & data_path);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -513,119 +513,22 @@ bool nano::node_config::upgrade_json (unsigned version_a, nano::jsonconfig & jso
 | 
				
			||||||
	switch (version_a)
 | 
						switch (version_a)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto reps_l (json.get_required_child ("preconfigured_representatives"));
 | 
					 | 
				
			||||||
			nano::jsonconfig reps;
 | 
					 | 
				
			||||||
			reps_l.array_entries<std::string> ([&reps](std::string entry) {
 | 
					 | 
				
			||||||
				nano::account account;
 | 
					 | 
				
			||||||
				account.decode_account (entry);
 | 
					 | 
				
			||||||
				reps.push (account.to_account ());
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			json.replace_child ("preconfigured_representatives", reps);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 2:
 | 
							case 2:
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			json.put ("inactive_supply", nano::uint128_union (0).to_string_dec ());
 | 
					 | 
				
			||||||
			json.put ("password_fanout", std::to_string (1024));
 | 
					 | 
				
			||||||
			json.put ("io_threads", std::to_string (io_threads));
 | 
					 | 
				
			||||||
			json.put ("work_threads", std::to_string (work_threads));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 3:
 | 
							case 3:
 | 
				
			||||||
			json.erase ("receive_minimum");
 | 
					 | 
				
			||||||
			json.put ("receive_minimum", nano::xrb_ratio.convert_to<std::string> ());
 | 
					 | 
				
			||||||
		case 4:
 | 
							case 4:
 | 
				
			||||||
			json.erase ("receive_minimum");
 | 
					 | 
				
			||||||
			json.put ("receive_minimum", nano::xrb_ratio.convert_to<std::string> ());
 | 
					 | 
				
			||||||
		case 5:
 | 
							case 5:
 | 
				
			||||||
			json.put ("enable_voting", enable_voting);
 | 
					 | 
				
			||||||
			json.erase ("packet_delay_microseconds");
 | 
					 | 
				
			||||||
			json.erase ("rebroadcast_delay");
 | 
					 | 
				
			||||||
			json.erase ("creation_rebroadcast");
 | 
					 | 
				
			||||||
		case 6:
 | 
							case 6:
 | 
				
			||||||
			json.put ("bootstrap_connections", 16);
 | 
					 | 
				
			||||||
			json.put ("callback_address", "");
 | 
					 | 
				
			||||||
			json.put ("callback_port", 0);
 | 
					 | 
				
			||||||
			json.put ("callback_target", "");
 | 
					 | 
				
			||||||
		case 7:
 | 
							case 7:
 | 
				
			||||||
			json.put ("lmdb_max_dbs", 128);
 | 
					 | 
				
			||||||
		case 8:
 | 
							case 8:
 | 
				
			||||||
			json.put ("bootstrap_connections_max", "64");
 | 
					 | 
				
			||||||
		case 9:
 | 
							case 9:
 | 
				
			||||||
			json.put ("state_block_parse_canary", nano::block_hash (0).to_string ());
 | 
					 | 
				
			||||||
			json.put ("state_block_generate_canary", nano::block_hash (0).to_string ());
 | 
					 | 
				
			||||||
		case 10:
 | 
							case 10:
 | 
				
			||||||
			json.put ("online_weight_minimum", online_weight_minimum.to_string_dec ());
 | 
					 | 
				
			||||||
			json.put ("online_weight_quorom", std::to_string (online_weight_quorum));
 | 
					 | 
				
			||||||
			json.erase ("inactive_supply");
 | 
					 | 
				
			||||||
		case 11:
 | 
							case 11:
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Rename
 | 
					 | 
				
			||||||
			std::string online_weight_quorum_l;
 | 
					 | 
				
			||||||
			json.get<std::string> ("online_weight_quorom", online_weight_quorum_l);
 | 
					 | 
				
			||||||
			json.erase ("online_weight_quorom");
 | 
					 | 
				
			||||||
			json.put ("online_weight_quorum", online_weight_quorum_l);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 12:
 | 
							case 12:
 | 
				
			||||||
			json.erase ("state_block_parse_canary");
 | 
					 | 
				
			||||||
			json.erase ("state_block_generate_canary");
 | 
					 | 
				
			||||||
		case 13:
 | 
							case 13:
 | 
				
			||||||
			json.put ("generate_hash_votes_at", 0);
 | 
					 | 
				
			||||||
		case 14:
 | 
							case 14:
 | 
				
			||||||
			json.put ("network_threads", std::to_string (network_threads));
 | 
					 | 
				
			||||||
			json.erase ("generate_hash_votes_at");
 | 
					 | 
				
			||||||
			json.put ("block_processor_batch_max_time", block_processor_batch_max_time.count ());
 | 
					 | 
				
			||||||
		case 15:
 | 
							case 15:
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			json.put ("allow_local_peers", allow_local_peers);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Update to the new preconfigured_peers url for rebrand if it is found (rai -> nano)
 | 
					 | 
				
			||||||
			auto peers_l (json.get_required_child (preconfigured_peers_key));
 | 
					 | 
				
			||||||
			nano::jsonconfig peers;
 | 
					 | 
				
			||||||
			peers_l.array_entries<std::string> ([&peers](std::string entry) {
 | 
					 | 
				
			||||||
				if (entry == "rai-beta.raiblocks.net")
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					entry = default_beta_peer_network;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else if (entry == "rai.raiblocks.net")
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					entry = default_live_peer_network;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				peers.push (std::move (entry));
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			json.replace_child (preconfigured_peers_key, peers);
 | 
					 | 
				
			||||||
			json.put ("vote_minimum", vote_minimum.to_string_dec ());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			nano::jsonconfig ipc_l;
 | 
					 | 
				
			||||||
			ipc_config.serialize_json (ipc_l);
 | 
					 | 
				
			||||||
			json.put_child ("ipc", ipc_l);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			json.put (signature_checker_threads_key, signature_checker_threads);
 | 
					 | 
				
			||||||
			json.put ("unchecked_cutoff_time", unchecked_cutoff_time.count ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 16:
 | 
							case 16:
 | 
				
			||||||
		{
 | 
								throw std::runtime_error ("node_config version unsupported for upgrade. Upgrade to a v19, v20 or v21 node first, or delete the config and ledger files");
 | 
				
			||||||
			nano::jsonconfig websocket_l;
 | 
					 | 
				
			||||||
			websocket_config.serialize_json (websocket_l);
 | 
					 | 
				
			||||||
			json.put_child ("websocket", websocket_l);
 | 
					 | 
				
			||||||
			nano::jsonconfig diagnostics_l;
 | 
					 | 
				
			||||||
			diagnostics_config.serialize_json (diagnostics_l);
 | 
					 | 
				
			||||||
			json.put_child ("diagnostics", diagnostics_l);
 | 
					 | 
				
			||||||
			json.put ("tcp_io_timeout", tcp_io_timeout.count ());
 | 
					 | 
				
			||||||
			json.put (pow_sleep_interval_key, pow_sleep_interval.count ());
 | 
					 | 
				
			||||||
			json.put ("external_address", external_address);
 | 
					 | 
				
			||||||
			json.put ("external_port", external_port);
 | 
					 | 
				
			||||||
			json.put ("tcp_incoming_connections_max", tcp_incoming_connections_max);
 | 
					 | 
				
			||||||
			json.put ("vote_generator_delay", vote_generator_delay.count ());
 | 
					 | 
				
			||||||
			json.put ("vote_generator_threshold", vote_generator_threshold);
 | 
					 | 
				
			||||||
			json.put ("use_memory_pools", use_memory_pools);
 | 
					 | 
				
			||||||
			json.put ("confirmation_history_size", confirmation_history_size);
 | 
					 | 
				
			||||||
			json.put ("active_elections_size", active_elections_size);
 | 
					 | 
				
			||||||
			json.put ("bandwidth_limit", bandwidth_limit);
 | 
					 | 
				
			||||||
			json.put ("conf_height_processor_batch_min_time", conf_height_processor_batch_min_time.count ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		case 17:
 | 
							case 17:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			json.put ("active_elections_size", 10000); // Update value
 | 
								json.put ("active_elections_size", 10000); // Update value
 | 
				
			||||||
| 
						 | 
					@ -645,21 +548,8 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	try
 | 
						try
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto version_l (json.get_optional<unsigned> ("version"));
 | 
							auto version_l (json.get<unsigned> ("version"));
 | 
				
			||||||
		if (!version_l)
 | 
							upgraded_a |= upgrade_json (version_l, json);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			version_l = 1;
 | 
					 | 
				
			||||||
			json.put ("version", version_l);
 | 
					 | 
				
			||||||
			auto work_peers_l (json.get_optional_child ("work_peers"));
 | 
					 | 
				
			||||||
			if (!work_peers_l)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				nano::jsonconfig empty;
 | 
					 | 
				
			||||||
				json.put_child ("work_peers", empty);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			upgraded_a = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		upgraded_a |= upgrade_json (version_l.get (), json);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto logging_l (json.get_required_child ("logging"));
 | 
							auto logging_l (json.get_required_child ("logging"));
 | 
				
			||||||
		logging.deserialize_json (upgraded_a, logging_l);
 | 
							logging.deserialize_json (upgraded_a, logging_l);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,6 @@ public:
 | 
				
			||||||
	nano::confirmation_height_mode confirmation_height_processor_mode{ nano::confirmation_height_mode::automatic };
 | 
						nano::confirmation_height_mode confirmation_height_processor_mode{ nano::confirmation_height_mode::automatic };
 | 
				
			||||||
	nano::generate_cache generate_cache;
 | 
						nano::generate_cache generate_cache;
 | 
				
			||||||
	bool inactive_node{ false };
 | 
						bool inactive_node{ false };
 | 
				
			||||||
	size_t sideband_batch_size{ 512 };
 | 
					 | 
				
			||||||
	size_t block_processor_batch_size{ 0 };
 | 
						size_t block_processor_batch_size{ 0 };
 | 
				
			||||||
	size_t block_processor_full_size{ 65536 };
 | 
						size_t block_processor_full_size{ 65536 };
 | 
				
			||||||
	size_t block_processor_verification_size{ 0 };
 | 
						size_t block_processor_verification_size{ 0 };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,8 +171,6 @@ rocksdb::ColumnFamilyHandle * nano::rocksdb_store::table_to_column_family (table
 | 
				
			||||||
			return get_handle ("state_blocks");
 | 
								return get_handle ("state_blocks");
 | 
				
			||||||
		case tables::pending:
 | 
							case tables::pending:
 | 
				
			||||||
			return get_handle ("pending");
 | 
								return get_handle ("pending");
 | 
				
			||||||
		case tables::blocks_info:
 | 
					 | 
				
			||||||
			debug_assert (false);
 | 
					 | 
				
			||||||
		case tables::representation:
 | 
							case tables::representation:
 | 
				
			||||||
			return get_handle ("representation");
 | 
								return get_handle ("representation");
 | 
				
			||||||
		case tables::unchecked:
 | 
							case tables::unchecked:
 | 
				
			||||||
| 
						 | 
					@ -191,7 +189,7 @@ rocksdb::ColumnFamilyHandle * nano::rocksdb_store::table_to_column_family (table
 | 
				
			||||||
			return get_handle ("confirmation_height");
 | 
								return get_handle ("confirmation_height");
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			release_assert (false);
 | 
								release_assert (false);
 | 
				
			||||||
			return get_handle ("peers");
 | 
								return get_handle ("");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,13 +225,6 @@ int nano::rocksdb_store::del (nano::write_transaction const & transaction_a, tab
 | 
				
			||||||
	return tx (transaction_a)->Delete (table_to_column_family (table_a), key_a).code ();
 | 
						return tx (transaction_a)->Delete (table_to_column_family (table_a), key_a).code ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool nano::rocksdb_store::block_info_get (nano::transaction const &, nano::block_hash const &, nano::block_info &) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Should not be called as the RocksDB backend does not use this table
 | 
					 | 
				
			||||||
	debug_assert (false);
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::rocksdb_store::version_put (nano::write_transaction const & transaction_a, int version_a)
 | 
					void nano::rocksdb_store::version_put (nano::write_transaction const & transaction_a, int version_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	debug_assert (transaction_a.contains (tables::meta));
 | 
						debug_assert (transaction_a.contains (tables::meta));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,6 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::string vendor_get () const override;
 | 
						std::string vendor_get () const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool block_info_get (nano::transaction const &, nano::block_hash const &, nano::block_info &) const override;
 | 
					 | 
				
			||||||
	size_t count (nano::transaction const & transaction_a, tables table_a) const override;
 | 
						size_t count (nano::transaction const & transaction_a, tables table_a) const override;
 | 
				
			||||||
	void version_put (nano::write_transaction const &, int) override;
 | 
						void version_put (nano::write_transaction const &, int) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,12 +157,6 @@ bool nano::wallet_store::attempt_password (nano::transaction const & transaction
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (version (transaction_a))
 | 
							switch (version (transaction_a))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case version_1:
 | 
					 | 
				
			||||||
				upgrade_v1_v2 (transaction_a);
 | 
					 | 
				
			||||||
			case version_2:
 | 
					 | 
				
			||||||
				upgrade_v2_v3 (transaction_a);
 | 
					 | 
				
			||||||
			case version_3:
 | 
					 | 
				
			||||||
				upgrade_v3_v4 (transaction_a);
 | 
					 | 
				
			||||||
			case version_4:
 | 
								case version_4:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
| 
						 | 
					@ -651,102 +645,6 @@ void nano::wallet_store::version_put (nano::transaction const & transaction_a, u
 | 
				
			||||||
	entry_put_raw (transaction_a, nano::wallet_store::version_special, nano::wallet_value (entry, 0));
 | 
						entry_put_raw (transaction_a, nano::wallet_store::version_special, nano::wallet_value (entry, 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::wallet_store::upgrade_v1_v2 (nano::transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (version (transaction_a) == 1);
 | 
					 | 
				
			||||||
	nano::raw_key zero_password;
 | 
					 | 
				
			||||||
	nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::wallet_key_special));
 | 
					 | 
				
			||||||
	nano::raw_key kdf;
 | 
					 | 
				
			||||||
	kdf.data.clear ();
 | 
					 | 
				
			||||||
	zero_password.decrypt (value.key, kdf, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
	derive_key (kdf, transaction_a, "");
 | 
					 | 
				
			||||||
	nano::raw_key empty_password;
 | 
					 | 
				
			||||||
	empty_password.decrypt (value.key, kdf, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
	for (auto i (begin (transaction_a)), n (end ()); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::public_key const & key (i->first);
 | 
					 | 
				
			||||||
		nano::raw_key prv;
 | 
					 | 
				
			||||||
		if (fetch (transaction_a, key, prv))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Key failed to decrypt despite valid password
 | 
					 | 
				
			||||||
			nano::wallet_value data (entry_get_raw (transaction_a, key));
 | 
					 | 
				
			||||||
			prv.decrypt (data.key, zero_password, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
			nano::public_key compare (nano::pub_key (prv.as_private_key ()));
 | 
					 | 
				
			||||||
			if (compare == key)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// If we successfully decrypted it, rewrite the key back with the correct wallet key
 | 
					 | 
				
			||||||
				insert_adhoc (transaction_a, prv);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// Also try the empty password
 | 
					 | 
				
			||||||
				nano::wallet_value data (entry_get_raw (transaction_a, key));
 | 
					 | 
				
			||||||
				prv.decrypt (data.key, empty_password, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
				nano::public_key compare (nano::pub_key (prv.as_private_key ()));
 | 
					 | 
				
			||||||
				if (compare == key)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					// If we successfully decrypted it, rewrite the key back with the correct wallet key
 | 
					 | 
				
			||||||
					insert_adhoc (transaction_a, prv);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	version_put (transaction_a, 2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::wallet_store::upgrade_v2_v3 (nano::transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (version (transaction_a) == 2);
 | 
					 | 
				
			||||||
	nano::raw_key seed;
 | 
					 | 
				
			||||||
	random_pool::generate_block (seed.data.bytes.data (), seed.data.bytes.size ());
 | 
					 | 
				
			||||||
	seed_set (transaction_a, seed);
 | 
					 | 
				
			||||||
	entry_put_raw (transaction_a, nano::wallet_store::deterministic_index_special, nano::wallet_value (nano::uint256_union (0), 0));
 | 
					 | 
				
			||||||
	version_put (transaction_a, 3);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::wallet_store::upgrade_v3_v4 (nano::transaction const & transaction_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (version (transaction_a) == 3);
 | 
					 | 
				
			||||||
	version_put (transaction_a, 4);
 | 
					 | 
				
			||||||
	debug_assert (valid_password (transaction_a));
 | 
					 | 
				
			||||||
	nano::raw_key seed;
 | 
					 | 
				
			||||||
	nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::seed_special));
 | 
					 | 
				
			||||||
	nano::raw_key password_l;
 | 
					 | 
				
			||||||
	wallet_key (password_l, transaction_a);
 | 
					 | 
				
			||||||
	seed.decrypt (value.key, password_l, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
	nano::uint256_union ciphertext;
 | 
					 | 
				
			||||||
	ciphertext.encrypt (seed, password_l, salt (transaction_a).owords[seed_iv_index]);
 | 
					 | 
				
			||||||
	entry_put_raw (transaction_a, nano::wallet_store::seed_special, nano::wallet_value (ciphertext, 0));
 | 
					 | 
				
			||||||
	for (auto i (begin (transaction_a)), n (end ()); i != n; ++i)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::wallet_value value (i->second);
 | 
					 | 
				
			||||||
		if (!value.key.is_zero ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			switch (key_type (i->second))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				case nano::key_type::adhoc:
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					nano::raw_key key;
 | 
					 | 
				
			||||||
					if (fetch (transaction_a, nano::public_key (i->first), key))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						// Key failed to decrypt despite valid password
 | 
					 | 
				
			||||||
						key.decrypt (value.key, password_l, salt (transaction_a).owords[0]);
 | 
					 | 
				
			||||||
						nano::uint256_union new_key_ciphertext;
 | 
					 | 
				
			||||||
						new_key_ciphertext.encrypt (key, password_l, (nano::uint256_union (i->first)).owords[0].number ());
 | 
					 | 
				
			||||||
						nano::wallet_value new_value (new_key_ciphertext, value.work);
 | 
					 | 
				
			||||||
						erase (transaction_a, nano::public_key (i->first));
 | 
					 | 
				
			||||||
						entry_put_raw (transaction_a, nano::public_key (i->first), new_value);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				case nano::key_type::deterministic:
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					debug_assert (false);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::kdf::phs (nano::raw_key & result_a, std::string const & password_a, nano::uint256_union const & salt_a)
 | 
					void nano::kdf::phs (nano::raw_key & result_a, std::string const & password_a, nano::uint256_union const & salt_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static nano::network_params network_params;
 | 
						static nano::network_params network_params;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,9 +91,6 @@ public:
 | 
				
			||||||
	void work_put (nano::transaction const &, nano::public_key const &, uint64_t);
 | 
						void work_put (nano::transaction const &, nano::public_key const &, uint64_t);
 | 
				
			||||||
	unsigned version (nano::transaction const &);
 | 
						unsigned version (nano::transaction const &);
 | 
				
			||||||
	void version_put (nano::transaction const &, unsigned);
 | 
						void version_put (nano::transaction const &, unsigned);
 | 
				
			||||||
	void upgrade_v1_v2 (nano::transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v2_v3 (nano::transaction const &);
 | 
					 | 
				
			||||||
	void upgrade_v3_v4 (nano::transaction const &);
 | 
					 | 
				
			||||||
	nano::fan password;
 | 
						nano::fan password;
 | 
				
			||||||
	nano::fan wallet_key_mem;
 | 
						nano::fan wallet_key_mem;
 | 
				
			||||||
	static unsigned const version_1 = 1;
 | 
						static unsigned const version_1 = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7061,30 +7061,6 @@ TEST (rpc_config, serialization)
 | 
				
			||||||
	ASSERT_EQ (config2.rpc_process.num_ipc_connections, config1.rpc_process.num_ipc_connections);
 | 
						ASSERT_EQ (config2.rpc_process.num_ipc_connections, config1.rpc_process.num_ipc_connections);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST (rpc_config, migrate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nano::jsonconfig rpc;
 | 
					 | 
				
			||||||
	rpc.put ("address", "::1");
 | 
					 | 
				
			||||||
	rpc.put ("port", 11111);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool updated = false;
 | 
					 | 
				
			||||||
	auto data_path = nano::unique_path ();
 | 
					 | 
				
			||||||
	boost::filesystem::create_directory (data_path);
 | 
					 | 
				
			||||||
	nano::node_rpc_config nano_rpc_config;
 | 
					 | 
				
			||||||
	nano_rpc_config.deserialize_json (updated, rpc, data_path);
 | 
					 | 
				
			||||||
	ASSERT_TRUE (updated);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Check that the rpc config file is created
 | 
					 | 
				
			||||||
	auto rpc_path = nano::get_rpc_config_path (data_path);
 | 
					 | 
				
			||||||
	nano::rpc_config rpc_config;
 | 
					 | 
				
			||||||
	nano::jsonconfig json;
 | 
					 | 
				
			||||||
	updated = false;
 | 
					 | 
				
			||||||
	ASSERT_FALSE (json.read_and_update (rpc_config, rpc_path));
 | 
					 | 
				
			||||||
	ASSERT_FALSE (updated);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ASSERT_EQ (rpc_config.port, 11111);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST (rpc, deprecated_account_format)
 | 
					TEST (rpc, deprecated_account_format)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nano::system system;
 | 
						nano::system system;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,249 +1,6 @@
 | 
				
			||||||
#include <nano/lib/threading.hpp>
 | 
					#include <nano/lib/threading.hpp>
 | 
				
			||||||
#include <nano/secure/blockstore.hpp>
 | 
					#include <nano/secure/blockstore.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::summation_visitor::summation_visitor (nano::transaction const & transaction_a, nano::block_store const & store_a, bool is_v14_upgrade_a) :
 | 
					 | 
				
			||||||
transaction (transaction_a),
 | 
					 | 
				
			||||||
store (store_a),
 | 
					 | 
				
			||||||
is_v14_upgrade (is_v14_upgrade_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::send_block (nano::send_block const & block_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
	if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		sum_set (block_a.hashables.balance.number ());
 | 
					 | 
				
			||||||
		current->balance_hash = block_a.hashables.previous;
 | 
					 | 
				
			||||||
		current->amount_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		sum_add (block_a.hashables.balance.number ());
 | 
					 | 
				
			||||||
		current->balance_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::state_block (nano::state_block const & block_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
	sum_set (block_a.hashables.balance.number ());
 | 
					 | 
				
			||||||
	if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current->balance_hash = block_a.hashables.previous;
 | 
					 | 
				
			||||||
		current->amount_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current->balance_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::receive_block (nano::receive_block const & block_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
	if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current->amount_hash = block_a.hashables.source;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::block_info block_info;
 | 
					 | 
				
			||||||
		if (!store.block_info_get (transaction, block_a.hash (), block_info))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			sum_add (block_info.balance.number ());
 | 
					 | 
				
			||||||
			current->balance_hash = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			current->amount_hash = block_a.hashables.source;
 | 
					 | 
				
			||||||
			current->balance_hash = block_a.hashables.previous;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::open_block (nano::open_block const & block_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
	if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (block_a.hashables.source != network_params.ledger.genesis_account)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			current->amount_hash = block_a.hashables.source;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			sum_set (network_params.ledger.genesis_amount);
 | 
					 | 
				
			||||||
			current->amount_hash = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current->amount_hash = block_a.hashables.source;
 | 
					 | 
				
			||||||
		current->balance_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::change_block (nano::change_block const & block_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
	if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		sum_set (0);
 | 
					 | 
				
			||||||
		current->amount_hash = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::block_info block_info;
 | 
					 | 
				
			||||||
		if (!store.block_info_get (transaction, block_a.hash (), block_info))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			sum_add (block_info.balance.number ());
 | 
					 | 
				
			||||||
			current->balance_hash = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			current->balance_hash = block_a.hashables.previous;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::summation_visitor::frame nano::summation_visitor::push (nano::summation_visitor::summation_type type_a, nano::block_hash const & hash_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	frames.emplace (type_a, type_a == summation_type::balance ? hash_a : 0, type_a == summation_type::amount ? hash_a : 0);
 | 
					 | 
				
			||||||
	return frames.top ();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::sum_add (nano::uint128_t addend_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	current->sum += addend_a;
 | 
					 | 
				
			||||||
	result = current->sum;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::sum_set (nano::uint128_t value_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	current->sum = value_a;
 | 
					 | 
				
			||||||
	result = current->sum;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::uint128_t nano::summation_visitor::compute_internal (nano::summation_visitor::summation_type type_a, nano::block_hash const & hash_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	push (type_a, hash_a);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 Invocation loop representing balance and amount computations calling each other.
 | 
					 | 
				
			||||||
	 This is usually better done by recursion or something like boost::coroutine2, but
 | 
					 | 
				
			||||||
	 segmented stacks are not supported on all platforms so we do it manually to avoid
 | 
					 | 
				
			||||||
	 stack overflow (the mutual calls are not tail-recursive so we cannot rely on the
 | 
					 | 
				
			||||||
	 compiler optimizing that into a loop, though a future alternative is to do a
 | 
					 | 
				
			||||||
	 CPS-style implementation to enforce tail calls.)
 | 
					 | 
				
			||||||
	*/
 | 
					 | 
				
			||||||
	while (!frames.empty ())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		current = &frames.top ();
 | 
					 | 
				
			||||||
		debug_assert (current->type != summation_type::invalid && current != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (current->type == summation_type::balance)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (current->awaiting_result)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				sum_add (current->incoming_result);
 | 
					 | 
				
			||||||
				current->awaiting_result = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			while (!current->awaiting_result && (!current->balance_hash.is_zero () || !current->amount_hash.is_zero ()))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (!current->amount_hash.is_zero ())
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					// Compute amount
 | 
					 | 
				
			||||||
					current->awaiting_result = true;
 | 
					 | 
				
			||||||
					push (summation_type::amount, current->amount_hash);
 | 
					 | 
				
			||||||
					current->amount_hash = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					auto block (block_get (transaction, current->balance_hash));
 | 
					 | 
				
			||||||
					debug_assert (block != nullptr);
 | 
					 | 
				
			||||||
					block->visit (*this);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			epilogue ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (current->type == summation_type::amount)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (current->awaiting_result)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				sum_set (current->sum < current->incoming_result ? current->incoming_result - current->sum : current->sum - current->incoming_result);
 | 
					 | 
				
			||||||
				current->awaiting_result = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			while (!current->awaiting_result && (!current->amount_hash.is_zero () || !current->balance_hash.is_zero ()))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (!current->amount_hash.is_zero ())
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					auto block = block_get (transaction, current->amount_hash);
 | 
					 | 
				
			||||||
					if (block != nullptr)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						block->visit (*this);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						if (current->amount_hash == network_params.ledger.genesis_account)
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							sum_set ((std::numeric_limits<nano::uint128_t>::max) ());
 | 
					 | 
				
			||||||
							current->amount_hash = 0;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						else
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							debug_assert (false);
 | 
					 | 
				
			||||||
							sum_set (0);
 | 
					 | 
				
			||||||
							current->amount_hash = 0;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					// Compute balance
 | 
					 | 
				
			||||||
					current->awaiting_result = true;
 | 
					 | 
				
			||||||
					push (summation_type::balance, current->balance_hash);
 | 
					 | 
				
			||||||
					current->balance_hash = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			epilogue ();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void nano::summation_visitor::epilogue ()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!current->awaiting_result)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		frames.pop ();
 | 
					 | 
				
			||||||
		if (!frames.empty ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			frames.top ().incoming_result = current->sum;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::uint128_t nano::summation_visitor::compute_amount (nano::block_hash const & block_hash)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return compute_internal (summation_type::amount, block_hash);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::uint128_t nano::summation_visitor::compute_balance (nano::block_hash const & block_hash)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return compute_internal (summation_type::balance, block_hash);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::shared_ptr<nano::block> nano::summation_visitor::block_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return is_v14_upgrade ? store.block_get_v14 (transaction, hash_a) : store.block_get_no_sideband (transaction, hash_a);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::representative_visitor::representative_visitor (nano::transaction const & transaction_a, nano::block_store & store_a) :
 | 
					nano::representative_visitor::representative_visitor (nano::transaction const & transaction_a, nano::block_store & store_a) :
 | 
				
			||||||
transaction (transaction_a),
 | 
					transaction (transaction_a),
 | 
				
			||||||
store (store_a),
 | 
					store (store_a),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,11 +57,6 @@ public:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	db_val (nano::account_info_v13 const & val_a) :
 | 
					 | 
				
			||||||
	db_val (val_a.db_size (), const_cast<nano::account_info_v13 *> (&val_a))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db_val (nano::account_info_v14 const & val_a) :
 | 
						db_val (nano::account_info_v14 const & val_a) :
 | 
				
			||||||
	db_val (val_a.db_size (), const_cast<nano::account_info_v14 *> (&val_a))
 | 
						db_val (val_a.db_size (), const_cast<nano::account_info_v14 *> (&val_a))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -152,14 +147,6 @@ public:
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	explicit operator nano::account_info_v13 () const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		nano::account_info_v13 result;
 | 
					 | 
				
			||||||
		debug_assert (size () == result.db_size ());
 | 
					 | 
				
			||||||
		std::copy (reinterpret_cast<uint8_t const *> (data ()), reinterpret_cast<uint8_t const *> (data ()) + result.db_size (), reinterpret_cast<uint8_t *> (&result));
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	explicit operator nano::account_info_v14 () const
 | 
						explicit operator nano::account_info_v14 () const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		nano::account_info_v14 result;
 | 
							nano::account_info_v14 result;
 | 
				
			||||||
| 
						 | 
					@ -403,82 +390,6 @@ private:
 | 
				
			||||||
class transaction;
 | 
					class transaction;
 | 
				
			||||||
class block_store;
 | 
					class block_store;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Summation visitor for blocks, supporting amount and balance computations. These
 | 
					 | 
				
			||||||
 * computations are mutually dependant. The natural solution is to use mutual recursion
 | 
					 | 
				
			||||||
 * between balance and amount visitors, but this leads to very deep stacks. Hence, the
 | 
					 | 
				
			||||||
 * summation visitor uses an iterative approach.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class summation_visitor final : public nano::block_visitor
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	enum summation_type
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		invalid = 0,
 | 
					 | 
				
			||||||
		balance = 1,
 | 
					 | 
				
			||||||
		amount = 2
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** Represents an invocation frame */
 | 
					 | 
				
			||||||
	class frame final
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		frame (summation_type type_a, nano::block_hash balance_hash_a, nano::block_hash amount_hash_a) :
 | 
					 | 
				
			||||||
		type (type_a), balance_hash (balance_hash_a), amount_hash (amount_hash_a)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/** The summation type guides the block visitor handlers */
 | 
					 | 
				
			||||||
		summation_type type{ invalid };
 | 
					 | 
				
			||||||
		/** Accumulated balance or amount */
 | 
					 | 
				
			||||||
		nano::uint128_t sum{ 0 };
 | 
					 | 
				
			||||||
		/** The current balance hash */
 | 
					 | 
				
			||||||
		nano::block_hash balance_hash{ 0 };
 | 
					 | 
				
			||||||
		/** The current amount hash */
 | 
					 | 
				
			||||||
		nano::block_hash amount_hash{ 0 };
 | 
					 | 
				
			||||||
		/** If true, this frame is awaiting an invocation result */
 | 
					 | 
				
			||||||
		bool awaiting_result{ false };
 | 
					 | 
				
			||||||
		/** Set by the invoked frame, representing the return value */
 | 
					 | 
				
			||||||
		nano::uint128_t incoming_result{ 0 };
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	summation_visitor (nano::transaction const &, nano::block_store const &, bool is_v14_upgrade = false);
 | 
					 | 
				
			||||||
	virtual ~summation_visitor () = default;
 | 
					 | 
				
			||||||
	/** Computes the balance as of \p block_hash */
 | 
					 | 
				
			||||||
	nano::uint128_t compute_balance (nano::block_hash const & block_hash);
 | 
					 | 
				
			||||||
	/** Computes the amount delta between \p block_hash and its predecessor */
 | 
					 | 
				
			||||||
	nano::uint128_t compute_amount (nano::block_hash const & block_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
protected:
 | 
					 | 
				
			||||||
	nano::transaction const & transaction;
 | 
					 | 
				
			||||||
	nano::block_store const & store;
 | 
					 | 
				
			||||||
	nano::network_params network_params;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** The final result */
 | 
					 | 
				
			||||||
	nano::uint128_t result{ 0 };
 | 
					 | 
				
			||||||
	/** The current invocation frame */
 | 
					 | 
				
			||||||
	frame * current{ nullptr };
 | 
					 | 
				
			||||||
	/** Invocation frames */
 | 
					 | 
				
			||||||
	std::stack<frame> frames;
 | 
					 | 
				
			||||||
	/** Push a copy of \p hash of the given summation \p type */
 | 
					 | 
				
			||||||
	nano::summation_visitor::frame push (nano::summation_visitor::summation_type type, nano::block_hash const & hash);
 | 
					 | 
				
			||||||
	void sum_add (nano::uint128_t addend_a);
 | 
					 | 
				
			||||||
	void sum_set (nano::uint128_t value_a);
 | 
					 | 
				
			||||||
	/** The epilogue yields the result to previous frame, if any */
 | 
					 | 
				
			||||||
	void epilogue ();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::uint128_t compute_internal (nano::summation_visitor::summation_type type, nano::block_hash const &);
 | 
					 | 
				
			||||||
	void send_block (nano::send_block const &) override;
 | 
					 | 
				
			||||||
	void receive_block (nano::receive_block const &) override;
 | 
					 | 
				
			||||||
	void open_block (nano::open_block const &) override;
 | 
					 | 
				
			||||||
	void change_block (nano::change_block const &) override;
 | 
					 | 
				
			||||||
	void state_block (nano::state_block const &) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	bool is_v14_upgrade;
 | 
					 | 
				
			||||||
	std::shared_ptr<nano::block> block_get (nano::transaction const &, nano::block_hash const &) const;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Determine the representative for this block
 | 
					 * Determine the representative for this block
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -572,7 +483,6 @@ private:
 | 
				
			||||||
enum class tables
 | 
					enum class tables
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	accounts,
 | 
						accounts,
 | 
				
			||||||
	blocks_info, // LMDB only
 | 
					 | 
				
			||||||
	cached_counts, // RocksDB only
 | 
						cached_counts, // RocksDB only
 | 
				
			||||||
	change_blocks,
 | 
						change_blocks,
 | 
				
			||||||
	confirmation_height,
 | 
						confirmation_height,
 | 
				
			||||||
| 
						 | 
					@ -703,7 +613,6 @@ public:
 | 
				
			||||||
	virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_begin (nano::transaction const &) = 0;
 | 
						virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_begin (nano::transaction const &) = 0;
 | 
				
			||||||
	virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_end () = 0;
 | 
						virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_end () = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	virtual bool block_info_get (nano::transaction const &, nano::block_hash const &, nano::block_info &) const = 0;
 | 
					 | 
				
			||||||
	virtual nano::uint128_t block_balance (nano::transaction const &, nano::block_hash const &) = 0;
 | 
						virtual nano::uint128_t block_balance (nano::transaction const &, nano::block_hash const &) = 0;
 | 
				
			||||||
	virtual nano::uint128_t block_balance_calculated (std::shared_ptr<nano::block> const &) const = 0;
 | 
						virtual nano::uint128_t block_balance_calculated (std::shared_ptr<nano::block> const &) const = 0;
 | 
				
			||||||
	virtual nano::epoch block_version (nano::transaction const &, nano::block_hash const &) = 0;
 | 
						virtual nano::epoch block_version (nano::transaction const &, nano::block_hash const &) = 0;
 | 
				
			||||||
| 
						 | 
					@ -779,7 +688,7 @@ public:
 | 
				
			||||||
	virtual std::string vendor_get () const = 0;
 | 
						virtual std::string vendor_get () const = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<nano::block_store> make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool open_read_only = false, bool add_db_postfix = false, nano::rocksdb_config const & rocksdb_config = nano::rocksdb_config{}, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, size_t batch_size = 512, bool backup_before_upgrade = false, bool rocksdb_backend = false);
 | 
					std::unique_ptr<nano::block_store> make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool open_read_only = false, bool add_db_postfix = false, nano::rocksdb_config const & rocksdb_config = nano::rocksdb_config{}, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), nano::lmdb_config const & lmdb_config_a = nano::lmdb_config{}, bool backup_before_upgrade = false, bool rocksdb_backend = false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace std
 | 
					namespace std
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,21 +137,9 @@ public:
 | 
				
			||||||
			result = nano::deserialize_block (stream, type);
 | 
								result = nano::deserialize_block (stream, type);
 | 
				
			||||||
			debug_assert (result != nullptr);
 | 
								debug_assert (result != nullptr);
 | 
				
			||||||
			nano::block_sideband sideband;
 | 
								nano::block_sideband sideband;
 | 
				
			||||||
			if (full_sideband (transaction_a) || entry_has_sideband (value.size (), type))
 | 
								auto error (sideband.deserialize (stream, type));
 | 
				
			||||||
			{
 | 
								(void)error;
 | 
				
			||||||
				auto error (sideband.deserialize (stream, type));
 | 
								debug_assert (!error);
 | 
				
			||||||
				(void)error;
 | 
					 | 
				
			||||||
				debug_assert (!error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// Reconstruct sideband data for block.
 | 
					 | 
				
			||||||
				sideband.account = block_account_computed (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband.balance = block_balance_computed (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband.successor = block_successor (transaction_a, hash_a);
 | 
					 | 
				
			||||||
				sideband.height = 0;
 | 
					 | 
				
			||||||
				sideband.timestamp = 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			result->sideband_set (sideband);
 | 
								result->sideband_set (sideband);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
| 
						 | 
					@ -263,11 +251,6 @@ public:
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool full_sideband (nano::transaction const & transaction_a) const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return version_get (transaction_a) > 12;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void block_successor_clear (nano::write_transaction const & transaction_a, nano::block_hash const & hash_a) override
 | 
						void block_successor_clear (nano::write_transaction const & transaction_a, nano::block_hash const & hash_a) override
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		nano::block_type type;
 | 
							nano::block_type type;
 | 
				
			||||||
| 
						 | 
					@ -416,7 +399,7 @@ public:
 | 
				
			||||||
		nano::uint256_union version_key (1);
 | 
							nano::uint256_union version_key (1);
 | 
				
			||||||
		nano::db_val<Val> data;
 | 
							nano::db_val<Val> data;
 | 
				
			||||||
		auto status = get (transaction_a, tables::meta, nano::db_val<Val> (version_key), data);
 | 
							auto status = get (transaction_a, tables::meta, nano::db_val<Val> (version_key), data);
 | 
				
			||||||
		int result (1);
 | 
							int result (minimum_version);
 | 
				
			||||||
		if (!not_found (status))
 | 
							if (!not_found (status))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			nano::uint256_union version_value (data);
 | 
								nano::uint256_union version_value (data);
 | 
				
			||||||
| 
						 | 
					@ -797,11 +780,13 @@ public:
 | 
				
			||||||
		return count (transaction_a, tables::unchecked);
 | 
							return count (transaction_a, tables::unchecked);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int const minimum_version{ 14 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
	nano::network_params network_params;
 | 
						nano::network_params network_params;
 | 
				
			||||||
	std::unordered_map<nano::account, std::shared_ptr<nano::vote>> vote_cache_l1;
 | 
						std::unordered_map<nano::account, std::shared_ptr<nano::vote>> vote_cache_l1;
 | 
				
			||||||
	std::unordered_map<nano::account, std::shared_ptr<nano::vote>> vote_cache_l2;
 | 
						std::unordered_map<nano::account, std::shared_ptr<nano::vote>> vote_cache_l2;
 | 
				
			||||||
	static int constexpr version{ 18 };
 | 
						int const version{ 18 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template <typename T>
 | 
						template <typename T>
 | 
				
			||||||
	std::shared_ptr<nano::block> block_random (nano::transaction const & transaction_a, tables table_a)
 | 
						std::shared_ptr<nano::block> block_random (nano::transaction const & transaction_a, tables table_a)
 | 
				
			||||||
| 
						 | 
					@ -830,11 +815,6 @@ protected:
 | 
				
			||||||
		return static_cast<Derived_Store const &> (*this).template make_iterator<Key, Value> (transaction_a, table_a, key);
 | 
							return static_cast<Derived_Store const &> (*this).template make_iterator<Key, Value> (transaction_a, table_a, key);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool entry_has_sideband (size_t entry_size_a, nano::block_type type_a) const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return entry_size_a == nano::block::size (type_a) + nano::block_sideband::size (type_a);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::db_val<Val> block_raw_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const
 | 
						nano::db_val<Val> block_raw_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		nano::db_val<Val> result;
 | 
							nano::db_val<Val> result;
 | 
				
			||||||
| 
						 | 
					@ -854,70 +834,9 @@ protected:
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Return account containing hash
 | 
					 | 
				
			||||||
	nano::account block_account_computed (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		debug_assert (!full_sideband (transaction_a));
 | 
					 | 
				
			||||||
		nano::account result (0);
 | 
					 | 
				
			||||||
		auto hash (hash_a);
 | 
					 | 
				
			||||||
		while (result.is_zero ())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			auto block (block_get_no_sideband (transaction_a, hash));
 | 
					 | 
				
			||||||
			debug_assert (block);
 | 
					 | 
				
			||||||
			result = block->account ();
 | 
					 | 
				
			||||||
			if (result.is_zero ())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				auto type (nano::block_type::invalid);
 | 
					 | 
				
			||||||
				auto value (block_raw_get (transaction_a, block->previous (), type));
 | 
					 | 
				
			||||||
				if (entry_has_sideband (value.size (), type))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					result = block_account (transaction_a, block->previous ());
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					nano::block_info block_info;
 | 
					 | 
				
			||||||
					if (!block_info_get (transaction_a, hash, block_info))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						result = block_info.account;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						result = frontier_get (transaction_a, hash);
 | 
					 | 
				
			||||||
						if (result.is_zero ())
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							auto successor (block_successor (transaction_a, hash));
 | 
					 | 
				
			||||||
							debug_assert (!successor.is_zero ());
 | 
					 | 
				
			||||||
							hash = successor;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		debug_assert (!result.is_zero ());
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nano::uint128_t block_balance_computed (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		debug_assert (!full_sideband (transaction_a));
 | 
					 | 
				
			||||||
		summation_visitor visitor (transaction_a, *this);
 | 
					 | 
				
			||||||
		return visitor.compute_balance (hash_a);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	size_t block_successor_offset (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const
 | 
						size_t block_successor_offset (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		size_t result;
 | 
							return entry_size_a - nano::block_sideband::size (type_a);
 | 
				
			||||||
		if (full_sideband (transaction_a) || entry_has_sideband (entry_size_a, type_a))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			result = entry_size_a - nano::block_sideband::size (type_a);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Read old successor-only sideband
 | 
					 | 
				
			||||||
			debug_assert (entry_size_a == nano::block::size (type_a) + sizeof (nano::block_hash));
 | 
					 | 
				
			||||||
			result = entry_size_a - sizeof (nano::block_hash);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	boost::optional<nano::db_val<Val>> block_raw_get_by_type (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const
 | 
						boost::optional<nano::db_val<Val>> block_raw_get_by_type (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,35 +4,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <lmdb/libraries/liblmdb/lmdb.h>
 | 
					#include <lmdb/libraries/liblmdb/lmdb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::account_info_v1::account_info_v1 (MDB_val const & val_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (val_a.mv_size == sizeof (*this));
 | 
					 | 
				
			||||||
	static_assert (sizeof (head) + sizeof (rep_block) + sizeof (balance) + sizeof (modified) == sizeof (*this), "Class not packed");
 | 
					 | 
				
			||||||
	std::copy (reinterpret_cast<uint8_t const *> (val_a.mv_data), reinterpret_cast<uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast<uint8_t *> (this));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::account_info_v1::account_info_v1 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::amount const & balance_a, uint64_t modified_a) :
 | 
					 | 
				
			||||||
head (head_a),
 | 
					 | 
				
			||||||
rep_block (rep_block_a),
 | 
					 | 
				
			||||||
balance (balance_a),
 | 
					 | 
				
			||||||
modified (modified_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::pending_info_v3::pending_info_v3 (MDB_val const & val_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (val_a.mv_size == sizeof (*this));
 | 
					 | 
				
			||||||
	static_assert (sizeof (source) + sizeof (amount) + sizeof (destination) == sizeof (*this), "Packed class");
 | 
					 | 
				
			||||||
	std::copy (reinterpret_cast<uint8_t const *> (val_a.mv_data), reinterpret_cast<uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast<uint8_t *> (this));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::pending_info_v3::pending_info_v3 (nano::account const & source_a, nano::amount const & amount_a, nano::account const & destination_a) :
 | 
					 | 
				
			||||||
source (source_a),
 | 
					 | 
				
			||||||
amount (amount_a),
 | 
					 | 
				
			||||||
destination (destination_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::pending_info_v14::pending_info_v14 (nano::account const & source_a, nano::amount const & amount_a, nano::epoch epoch_a) :
 | 
					nano::pending_info_v14::pending_info_v14 (nano::account const & source_a, nano::amount const & amount_a, nano::epoch epoch_a) :
 | 
				
			||||||
source (source_a),
 | 
					source (source_a),
 | 
				
			||||||
amount (amount_a),
 | 
					amount (amount_a),
 | 
				
			||||||
| 
						 | 
					@ -66,44 +37,6 @@ bool nano::pending_info_v14::operator== (nano::pending_info_v14 const & other_a)
 | 
				
			||||||
	return source == other_a.source && amount == other_a.amount && epoch == other_a.epoch;
 | 
						return source == other_a.source && amount == other_a.amount && epoch == other_a.epoch;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano::account_info_v5::account_info_v5 (MDB_val const & val_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (val_a.mv_size == sizeof (*this));
 | 
					 | 
				
			||||||
	static_assert (sizeof (head) + sizeof (rep_block) + sizeof (open_block) + sizeof (balance) + sizeof (modified) == sizeof (*this), "Class not packed");
 | 
					 | 
				
			||||||
	std::copy (reinterpret_cast<uint8_t const *> (val_a.mv_data), reinterpret_cast<uint8_t const *> (val_a.mv_data) + sizeof (*this), reinterpret_cast<uint8_t *> (this));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::account_info_v5::account_info_v5 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, uint64_t modified_a) :
 | 
					 | 
				
			||||||
head (head_a),
 | 
					 | 
				
			||||||
rep_block (rep_block_a),
 | 
					 | 
				
			||||||
open_block (open_block_a),
 | 
					 | 
				
			||||||
balance (balance_a),
 | 
					 | 
				
			||||||
modified (modified_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::account_info_v13::account_info_v13 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, uint64_t modified_a, uint64_t block_count_a, nano::epoch epoch_a) :
 | 
					 | 
				
			||||||
head (head_a),
 | 
					 | 
				
			||||||
rep_block (rep_block_a),
 | 
					 | 
				
			||||||
open_block (open_block_a),
 | 
					 | 
				
			||||||
balance (balance_a),
 | 
					 | 
				
			||||||
modified (modified_a),
 | 
					 | 
				
			||||||
block_count (block_count_a),
 | 
					 | 
				
			||||||
epoch (epoch_a)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
size_t nano::account_info_v13::db_size () const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (this) == reinterpret_cast<const uint8_t *> (&head));
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (&head) + sizeof (head) == reinterpret_cast<const uint8_t *> (&rep_block));
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (&rep_block) + sizeof (rep_block) == reinterpret_cast<const uint8_t *> (&open_block));
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (&open_block) + sizeof (open_block) == reinterpret_cast<const uint8_t *> (&balance));
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (&balance) + sizeof (balance) == reinterpret_cast<const uint8_t *> (&modified));
 | 
					 | 
				
			||||||
	debug_assert (reinterpret_cast<const uint8_t *> (&modified) + sizeof (modified) == reinterpret_cast<const uint8_t *> (&block_count));
 | 
					 | 
				
			||||||
	return sizeof (head) + sizeof (rep_block) + sizeof (open_block) + sizeof (balance) + sizeof (modified) + sizeof (block_count);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nano::account_info_v14::account_info_v14 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, uint64_t modified_a, uint64_t block_count_a, uint64_t confirmation_height_a, nano::epoch epoch_a) :
 | 
					nano::account_info_v14::account_info_v14 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, uint64_t modified_a, uint64_t block_count_a, uint64_t confirmation_height_a, nano::epoch epoch_a) :
 | 
				
			||||||
head (head_a),
 | 
					head (head_a),
 | 
				
			||||||
rep_block (rep_block_a),
 | 
					rep_block (rep_block_a),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,27 +7,6 @@ struct MDB_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nano
 | 
					namespace nano
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
class account_info_v1 final
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	account_info_v1 () = default;
 | 
					 | 
				
			||||||
	explicit account_info_v1 (MDB_val const &);
 | 
					 | 
				
			||||||
	account_info_v1 (nano::block_hash const &, nano::block_hash const &, nano::amount const &, uint64_t);
 | 
					 | 
				
			||||||
	nano::block_hash head{ 0 };
 | 
					 | 
				
			||||||
	nano::block_hash rep_block{ 0 };
 | 
					 | 
				
			||||||
	nano::amount balance{ 0 };
 | 
					 | 
				
			||||||
	uint64_t modified{ 0 };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class pending_info_v3 final
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	pending_info_v3 () = default;
 | 
					 | 
				
			||||||
	explicit pending_info_v3 (MDB_val const &);
 | 
					 | 
				
			||||||
	pending_info_v3 (nano::account const &, nano::amount const &, nano::account const &);
 | 
					 | 
				
			||||||
	nano::account source{ 0 };
 | 
					 | 
				
			||||||
	nano::amount amount{ 0 };
 | 
					 | 
				
			||||||
	nano::account destination{ 0 };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class pending_info_v14 final
 | 
					class pending_info_v14 final
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					@ -40,32 +19,6 @@ public:
 | 
				
			||||||
	nano::amount amount{ 0 };
 | 
						nano::amount amount{ 0 };
 | 
				
			||||||
	nano::epoch epoch{ nano::epoch::epoch_0 };
 | 
						nano::epoch epoch{ nano::epoch::epoch_0 };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
class account_info_v5 final
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	account_info_v5 () = default;
 | 
					 | 
				
			||||||
	explicit account_info_v5 (MDB_val const &);
 | 
					 | 
				
			||||||
	account_info_v5 (nano::block_hash const &, nano::block_hash const &, nano::block_hash const &, nano::amount const &, uint64_t);
 | 
					 | 
				
			||||||
	nano::block_hash head{ 0 };
 | 
					 | 
				
			||||||
	nano::block_hash rep_block{ 0 };
 | 
					 | 
				
			||||||
	nano::block_hash open_block{ 0 };
 | 
					 | 
				
			||||||
	nano::amount balance{ 0 };
 | 
					 | 
				
			||||||
	uint64_t modified{ 0 };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class account_info_v13 final
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	account_info_v13 () = default;
 | 
					 | 
				
			||||||
	account_info_v13 (nano::block_hash const &, nano::block_hash const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch);
 | 
					 | 
				
			||||||
	size_t db_size () const;
 | 
					 | 
				
			||||||
	nano::block_hash head{ 0 };
 | 
					 | 
				
			||||||
	nano::block_hash rep_block{ 0 };
 | 
					 | 
				
			||||||
	nano::block_hash open_block{ 0 };
 | 
					 | 
				
			||||||
	nano::amount balance{ 0 };
 | 
					 | 
				
			||||||
	uint64_t modified{ 0 };
 | 
					 | 
				
			||||||
	uint64_t block_count{ 0 };
 | 
					 | 
				
			||||||
	nano::epoch epoch{ nano::epoch::epoch_0 };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
class account_info_v14 final
 | 
					class account_info_v14 final
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue