Add source block epoch to sideband information (#2873)

* Add source block epoch to sideband information
With v18->v19 DB upgrade
To prevent rollback issues for pruned ledger in future versions.
* Fix build error & warnings
* Clang formatting
* Move source epoch out of block details & more tests
* Remove unused header
This commit is contained in:
Sergey Kroshnin 2020-08-10 14:54:16 +03:00 committed by GitHub
commit b795fd1cba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 277 additions and 45 deletions

View file

@ -909,7 +909,7 @@ TEST (active_transactions, dropped_cleanup)
nano::genesis genesis; nano::genesis genesis;
auto block = genesis.open; auto block = genesis.open;
block->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false)); block->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0));
// Add to network filter to ensure proper cleanup after the election is dropped // Add to network filter to ensure proper cleanup after the election is dropped
std::vector<uint8_t> block_bytes; std::vector<uint8_t> block_bytes;

View file

@ -1623,10 +1623,13 @@ TEST (mdb_block_store, upgrade_v18_v19)
auto path (nano::unique_path ()); auto path (nano::unique_path ());
nano::keypair key1; nano::keypair key1;
nano::work_pool pool (std::numeric_limits<unsigned>::max ()); nano::work_pool pool (std::numeric_limits<unsigned>::max ());
nano::network_params network_params;
nano::send_block send (nano::genesis_hash, nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (nano::genesis_hash)); nano::send_block send (nano::genesis_hash, nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (nano::genesis_hash));
nano::receive_block receive (send.hash (), send.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send.hash ())); nano::receive_block receive (send.hash (), send.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send.hash ()));
nano::change_block change (receive.hash (), 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (receive.hash ())); nano::change_block change (receive.hash (), 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (receive.hash ()));
nano::state_block state (nano::test_genesis_key.pub, change.hash (), 0, nano::genesis_amount - nano::Gxrb_ratio, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (change.hash ())); nano::state_block state_epoch (nano::test_genesis_key.pub, change.hash (), 0, nano::genesis_amount, network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (change.hash ()));
nano::state_block state_send (nano::test_genesis_key.pub, state_epoch.hash (), 0, nano::genesis_amount - nano::Gxrb_ratio, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (state_epoch.hash ()));
nano::state_block state_open (key1.pub, 0, 0, nano::Gxrb_ratio, state_send.hash (), key1.prv, key1.pub, *pool.generate (key1.pub));
{ {
nano::genesis genesis; nano::genesis genesis;
@ -1640,7 +1643,9 @@ TEST (mdb_block_store, upgrade_v18_v19)
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_epoch).code);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_open).code);
// These tables need to be re-opened and populated so that an upgrade can be done // These tables need to be re-opened and populated so that an upgrade can be done
auto txn = store.env.tx (transaction); auto txn = store.env.tx (transaction);
@ -1655,7 +1660,9 @@ TEST (mdb_block_store, upgrade_v18_v19)
write_block_w_sideband_v18 (store, store.send_blocks, transaction, send); write_block_w_sideband_v18 (store, store.send_blocks, transaction, send);
write_block_w_sideband_v18 (store, store.receive_blocks, transaction, receive); write_block_w_sideband_v18 (store, store.receive_blocks, transaction, receive);
write_block_w_sideband_v18 (store, store.change_blocks, transaction, change); write_block_w_sideband_v18 (store, store.change_blocks, transaction, change);
write_block_w_sideband_v18 (store, store.state_blocks, transaction, state); write_block_w_sideband_v18 (store, store.state_blocks, transaction, state_epoch);
write_block_w_sideband_v18 (store, store.state_blocks, transaction, state_send);
write_block_w_sideband_v18 (store, store.state_blocks, transaction, state_open);
store.version_put (transaction, 18); store.version_put (transaction, 18);
} }
@ -1678,9 +1685,22 @@ TEST (mdb_block_store, upgrade_v18_v19)
ASSERT_TRUE (store.block_get (transaction, receive.hash ())); ASSERT_TRUE (store.block_get (transaction, receive.hash ()));
ASSERT_TRUE (store.block_get (transaction, change.hash ())); ASSERT_TRUE (store.block_get (transaction, change.hash ()));
ASSERT_TRUE (store.block_get (transaction, nano::genesis_hash)); ASSERT_TRUE (store.block_get (transaction, nano::genesis_hash));
ASSERT_TRUE (store.block_get (transaction, state.hash ())); auto state_epoch_disk (store.block_get (transaction, state_epoch.hash ()));
ASSERT_NE (nullptr, state_epoch_disk);
ASSERT_EQ (nano::epoch::epoch_1, state_epoch_disk->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, state_epoch_disk->sideband ().source_epoch); // Not used for epoch state blocks
ASSERT_TRUE (store.block_get (transaction, state_send.hash ()));
auto state_send_disk (store.block_get (transaction, state_send.hash ()));
ASSERT_NE (nullptr, state_send_disk);
ASSERT_EQ (nano::epoch::epoch_1, state_send_disk->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, state_send_disk->sideband ().source_epoch); // Not used for send state blocks
ASSERT_TRUE (store.block_get (transaction, state_open.hash ()));
auto state_open_disk (store.block_get (transaction, state_open.hash ()));
ASSERT_NE (nullptr, state_open_disk);
ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().source_epoch);
ASSERT_EQ (5, store.count (transaction, store.blocks)); ASSERT_EQ (7, store.count (transaction, store.blocks));
// Version should be correct // Version should be correct
ASSERT_LT (18, store.version_get (transaction)); ASSERT_LT (18, store.version_get (transaction));
@ -1879,7 +1899,7 @@ void write_sideband_v15 (nano::mdb_store & store_a, nano::transaction & transact
ASSERT_LE (block->sideband ().details.epoch, nano::epoch::max); ASSERT_LE (block->sideband ().details.epoch, nano::epoch::max);
// Simulated by writing 0 on every of the most significant bits, leaving out epoch only, as if pre-upgrade // Simulated by writing 0 on every of the most significant bits, leaving out epoch only, as if pre-upgrade
nano::block_sideband sideband_v15 (block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height, block->sideband ().details.epoch, false, false, false); nano::block_sideband_v18 sideband_v15 (block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height, block->sideband ().details.epoch, false, false, false);
std::vector<uint8_t> data; std::vector<uint8_t> data;
{ {
nano::vectorstream stream (data); nano::vectorstream stream (data);
@ -1895,12 +1915,14 @@ void write_block_w_sideband_v18 (nano::mdb_store & store_a, MDB_dbi database, na
{ {
auto block = store_a.block_get (transaction_a, block_a.hash ()); auto block = store_a.block_get (transaction_a, block_a.hash ());
ASSERT_NE (block, nullptr); ASSERT_NE (block, nullptr);
auto new_sideband (block->sideband ());
nano::block_sideband_v18 sideband_v18 (new_sideband.account, new_sideband.successor, new_sideband.balance, new_sideband.height, new_sideband.timestamp, new_sideband.details.epoch, new_sideband.details.is_send, new_sideband.details.is_receive, new_sideband.details.is_epoch);
std::vector<uint8_t> data; std::vector<uint8_t> data;
{ {
nano::vectorstream stream (data); nano::vectorstream stream (data);
block->serialize (stream); block->serialize (stream);
block->sideband ().serialize (stream, block->type ()); sideband_v18.serialize (stream, block->type ());
} }
MDB_val val{ data.size (), data.data () }; MDB_val val{ data.size (), data.data () };

View file

@ -9,7 +9,7 @@ TEST (election, construction)
nano::system system (1); nano::system system (1);
nano::genesis genesis; nano::genesis genesis;
auto & node = *system.nodes[0]; auto & node = *system.nodes[0];
genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false)); genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0));
auto election = node.active.insert (genesis.open).election; auto election = node.active.insert (genesis.open).election;
ASSERT_TRUE (election->idle ()); ASSERT_TRUE (election->idle ());
election->transition_active (); election->transition_active ();

View file

@ -2369,6 +2369,8 @@ TEST (ledger, epoch_blocks_v1_general)
ASSERT_FALSE (epoch1.sideband ().details.is_send); ASSERT_FALSE (epoch1.sideband ().details.is_send);
ASSERT_FALSE (epoch1.sideband ().details.is_receive); ASSERT_FALSE (epoch1.sideband ().details.is_receive);
ASSERT_TRUE (epoch1.sideband ().details.is_epoch); ASSERT_TRUE (epoch1.sideband ().details.is_epoch);
ASSERT_EQ (nano::epoch::epoch_1, epoch1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch1.sideband ().source_epoch); // Not used for epoch blocks
nano::state_block epoch2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::state_block epoch2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, epoch2).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, epoch2).code);
nano::account_info genesis_info; nano::account_info genesis_info;
@ -2383,6 +2385,8 @@ TEST (ledger, epoch_blocks_v1_general)
ASSERT_FALSE (epoch1.sideband ().details.is_send); ASSERT_FALSE (epoch1.sideband ().details.is_send);
ASSERT_FALSE (epoch1.sideband ().details.is_receive); ASSERT_FALSE (epoch1.sideband ().details.is_receive);
ASSERT_TRUE (epoch1.sideband ().details.is_epoch); ASSERT_TRUE (epoch1.sideband ().details.is_epoch);
ASSERT_EQ (nano::epoch::epoch_1, epoch1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch1.sideband ().source_epoch); // Not used for epoch blocks
nano::change_block change1 (epoch1.hash (), nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::change_block change1 (epoch1.hash (), nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, change1).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, change1).code);
nano::state_block send1 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::state_block send1 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
@ -2390,6 +2394,8 @@ TEST (ledger, epoch_blocks_v1_general)
ASSERT_TRUE (send1.sideband ().details.is_send); ASSERT_TRUE (send1.sideband ().details.is_send);
ASSERT_FALSE (send1.sideband ().details.is_receive); ASSERT_FALSE (send1.sideband ().details.is_receive);
ASSERT_FALSE (send1.sideband ().details.is_epoch); ASSERT_FALSE (send1.sideband ().details.is_epoch);
ASSERT_EQ (nano::epoch::epoch_1, send1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, send1.sideband ().source_epoch); // Not used for send blocks
nano::open_block open1 (send1.hash (), nano::genesis_account, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub)); nano::open_block open1 (send1.hash (), nano::genesis_account, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub));
ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, open1).code); ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, open1).code);
nano::state_block epoch3 (destination.pub, 0, nano::genesis_account, 0, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination.pub)); nano::state_block epoch3 (destination.pub, 0, nano::genesis_account, 0, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination.pub));
@ -2399,10 +2405,14 @@ TEST (ledger, epoch_blocks_v1_general)
ASSERT_FALSE (epoch4.sideband ().details.is_send); ASSERT_FALSE (epoch4.sideband ().details.is_send);
ASSERT_FALSE (epoch4.sideband ().details.is_receive); ASSERT_FALSE (epoch4.sideband ().details.is_receive);
ASSERT_TRUE (epoch4.sideband ().details.is_epoch); ASSERT_TRUE (epoch4.sideband ().details.is_epoch);
ASSERT_EQ (nano::epoch::epoch_1, epoch4.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch4.sideband ().source_epoch); // Not used for epoch blocks
nano::receive_block receive1 (epoch4.hash (), send1.hash (), destination.prv, destination.pub, *pool.generate (epoch4.hash ())); nano::receive_block receive1 (epoch4.hash (), send1.hash (), destination.prv, destination.pub, *pool.generate (epoch4.hash ()));
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, receive1).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, receive1).code);
nano::state_block receive2 (destination.pub, epoch4.hash (), destination.pub, nano::Gxrb_ratio, send1.hash (), destination.prv, destination.pub, *pool.generate (epoch4.hash ())); nano::state_block receive2 (destination.pub, epoch4.hash (), destination.pub, nano::Gxrb_ratio, send1.hash (), destination.prv, destination.pub, *pool.generate (epoch4.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().source_epoch);
ASSERT_EQ (0, ledger.balance (transaction, epoch4.hash ())); ASSERT_EQ (0, ledger.balance (transaction, epoch4.hash ()));
ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2.hash ()));
ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2.hash ()));
@ -2431,8 +2441,12 @@ TEST (ledger, epoch_blocks_v2_general)
// Set it to the first epoch and it should now succeed // Set it to the first epoch and it should now succeed
epoch1 = nano::state_block (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, epoch1.work); epoch1 = nano::state_block (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, epoch1.work);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code);
ASSERT_EQ (nano::epoch::epoch_1, epoch1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch1.sideband ().source_epoch); // Not used for epoch blocks
nano::state_block epoch2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::state_block epoch2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch2).code);
ASSERT_EQ (nano::epoch::epoch_2, epoch2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch2.sideband ().source_epoch); // Not used for epoch blocks
nano::state_block epoch3 (nano::genesis_account, epoch2.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch2.hash ())); nano::state_block epoch3 (nano::genesis_account, epoch2.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch2.hash ()));
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, epoch3).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, epoch3).code);
nano::account_info genesis_info; nano::account_info genesis_info;
@ -2448,18 +2462,26 @@ TEST (ledger, epoch_blocks_v2_general)
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, change1).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, change1).code);
nano::state_block send1 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::state_block send1 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send1).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send1).code);
ASSERT_EQ (nano::epoch::epoch_1, send1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, send1.sideband ().source_epoch); // Not used for send blocks
nano::open_block open1 (send1.hash (), nano::genesis_account, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub)); nano::open_block open1 (send1.hash (), nano::genesis_account, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub));
ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, open1).code); ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, open1).code);
nano::state_block epoch4 (destination.pub, 0, 0, 0, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination.pub)); nano::state_block epoch4 (destination.pub, 0, 0, 0, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination.pub));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch4).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch4).code);
ASSERT_EQ (nano::epoch::epoch_1, epoch4.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch4.sideband ().source_epoch); // Not used for epoch blocks
nano::state_block epoch5 (destination.pub, epoch4.hash (), nano::genesis_account, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch4.hash ())); nano::state_block epoch5 (destination.pub, epoch4.hash (), nano::genesis_account, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch4.hash ()));
ASSERT_EQ (nano::process_result::representative_mismatch, ledger.process (transaction, epoch5).code); ASSERT_EQ (nano::process_result::representative_mismatch, ledger.process (transaction, epoch5).code);
nano::state_block epoch6 (destination.pub, epoch4.hash (), 0, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch4.hash ())); nano::state_block epoch6 (destination.pub, epoch4.hash (), 0, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch4.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch6).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch6).code);
ASSERT_EQ (nano::epoch::epoch_2, epoch6.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch6.sideband ().source_epoch); // Not used for epoch blocks
nano::receive_block receive1 (epoch6.hash (), send1.hash (), destination.prv, destination.pub, *pool.generate (epoch6.hash ())); nano::receive_block receive1 (epoch6.hash (), send1.hash (), destination.prv, destination.pub, *pool.generate (epoch6.hash ()));
ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, receive1).code); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, receive1).code);
nano::state_block receive2 (destination.pub, epoch6.hash (), destination.pub, nano::Gxrb_ratio, send1.hash (), destination.prv, destination.pub, *pool.generate (epoch6.hash ())); nano::state_block receive2 (destination.pub, epoch6.hash (), destination.pub, nano::Gxrb_ratio, send1.hash (), destination.prv, destination.pub, *pool.generate (epoch6.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code);
ASSERT_EQ (nano::epoch::epoch_2, receive2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().source_epoch);
ASSERT_EQ (0, ledger.balance (transaction, epoch6.hash ())); ASSERT_EQ (0, ledger.balance (transaction, epoch6.hash ()));
ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, receive2.hash ()));
ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2.hash ()));
@ -2485,19 +2507,32 @@ TEST (ledger, epoch_blocks_receive_upgrade)
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code);
nano::state_block send2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio * 2, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ())); nano::state_block send2 (nano::genesis_account, epoch1.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio * 2, destination.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (epoch1.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send2).code);
ASSERT_EQ (nano::epoch::epoch_1, send2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, send2.sideband ().source_epoch); // Not used for send blocks
nano::open_block open1 (send1.hash (), destination.pub, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub)); nano::open_block open1 (send1.hash (), destination.pub, destination.pub, destination.prv, destination.pub, *pool.generate (destination.pub));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, open1).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, open1).code);
ASSERT_EQ (nano::epoch::epoch_0, open1.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, open1.sideband ().source_epoch);
nano::receive_block receive1 (open1.hash (), send2.hash (), destination.prv, destination.pub, *pool.generate (open1.hash ())); nano::receive_block receive1 (open1.hash (), send2.hash (), destination.prv, destination.pub, *pool.generate (open1.hash ()));
ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, receive1).code); ASSERT_EQ (nano::process_result::unreceivable, ledger.process (transaction, receive1).code);
nano::state_block receive2 (destination.pub, open1.hash (), destination.pub, nano::Gxrb_ratio * 2, send2.hash (), destination.prv, destination.pub, *pool.generate (open1.hash ())); nano::state_block receive2 (destination.pub, open1.hash (), destination.pub, nano::Gxrb_ratio * 2, send2.hash (), destination.prv, destination.pub, *pool.generate (open1.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().source_epoch);
nano::account_info destination_info; nano::account_info destination_info;
ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info)); ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info));
ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1);
ASSERT_FALSE (ledger.rollback (transaction, receive2.hash ())); ASSERT_FALSE (ledger.rollback (transaction, receive2.hash ()));
ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info)); ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info));
ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_0); ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_0);
nano::pending_info pending_send2;
ASSERT_FALSE (ledger.store.pending_get (transaction, nano::pending_key (destination.pub, send2.hash ()), pending_send2));
ASSERT_EQ (nano::test_genesis_key.pub, pending_send2.source);
ASSERT_EQ (nano::Gxrb_ratio, pending_send2.amount.number ());
ASSERT_EQ (nano::epoch::epoch_1, pending_send2.epoch);
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive2).code);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_1, receive2.sideband ().source_epoch);
ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info)); ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info));
ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1);
nano::keypair destination2; nano::keypair destination2;
@ -2520,6 +2555,8 @@ TEST (ledger, epoch_blocks_receive_upgrade)
ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1);
nano::state_block receive3 (destination.pub, send3.hash (), destination.pub, nano::Gxrb_ratio * 2, send5.hash (), destination.prv, destination.pub, *pool.generate (send3.hash ())); nano::state_block receive3 (destination.pub, send3.hash (), destination.pub, nano::Gxrb_ratio * 2, send5.hash (), destination.prv, destination.pub, *pool.generate (send3.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive3).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive3).code);
ASSERT_EQ (nano::epoch::epoch_2, receive3.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_2, receive3.sideband ().source_epoch);
ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info)); ASSERT_FALSE (ledger.store.account_get (transaction, destination.pub, destination_info));
ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_2); ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_2);
// Upgrade an unopened account straight to epoch 2 // Upgrade an unopened account straight to epoch 2
@ -2528,6 +2565,8 @@ TEST (ledger, epoch_blocks_receive_upgrade)
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send6).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send6).code);
nano::state_block epoch4 (destination4.pub, 0, 0, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination4.pub)); nano::state_block epoch4 (destination4.pub, 0, 0, 0, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (destination4.pub));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch4).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch4).code);
ASSERT_EQ (nano::epoch::epoch_2, epoch4.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch4.sideband ().source_epoch); // Not used for epoch blocks
ASSERT_EQ (store->account_count (transaction), ledger.cache.account_count); ASSERT_EQ (store->account_count (transaction), ledger.cache.account_count);
} }
@ -2551,6 +2590,8 @@ TEST (ledger, epoch_blocks_fork)
ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, epoch2).code); ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, epoch2).code);
nano::state_block epoch3 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ())); nano::state_block epoch3 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ()));
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch3).code); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch3).code);
ASSERT_EQ (nano::epoch::epoch_1, epoch3.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch3.sideband ().source_epoch); // Not used for epoch state blocks
nano::state_block epoch4 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ())); nano::state_block epoch4 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, ledger.epoch_link (nano::epoch::epoch_2), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ()));
ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, epoch2).code); ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, epoch2).code);
} }
@ -2576,6 +2617,8 @@ TEST (ledger, successor_epoch)
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, epoch_open).code); ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, epoch_open).code);
ASSERT_EQ (change, *node1.ledger.successor (transaction, change.qualified_root ())); ASSERT_EQ (change, *node1.ledger.successor (transaction, change.qualified_root ()));
ASSERT_EQ (epoch_open, *node1.ledger.successor (transaction, epoch_open.qualified_root ())); ASSERT_EQ (epoch_open, *node1.ledger.successor (transaction, epoch_open.qualified_root ()));
ASSERT_EQ (nano::epoch::epoch_1, epoch_open.sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, epoch_open.sideband ().source_epoch); // Not used for epoch state blocks
} }
TEST (ledger, epoch_open_pending) TEST (ledger, epoch_open_pending)

View file

@ -28,7 +28,7 @@ TEST (vote_processor, codes)
ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel)); ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel));
// First vote from an account for an ongoing election // First vote from an account for an ongoing election
genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false)); genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0));
ASSERT_TRUE (node.active.insert (genesis.open).inserted); ASSERT_TRUE (node.active.insert (genesis.open).inserted);
ASSERT_EQ (nano::vote_code::vote, node.vote_processor.vote_blocking (vote, channel)); ASSERT_EQ (nano::vote_code::vote, node.vote_processor.vote_blocking (vote, channel));
@ -77,7 +77,7 @@ TEST (vote_processor, invalid_signature)
vote_invalid->signature.bytes[0] ^= 1; vote_invalid->signature.bytes[0] ^= 1;
auto channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version)); auto channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version));
genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false)); genesis.open->sideband_set (nano::block_sideband (nano::genesis_account, 0, nano::genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0));
auto election (node.active.insert (genesis.open)); auto election (node.active.insert (genesis.open));
ASSERT_TRUE (election.election && election.inserted); ASSERT_TRUE (election.election && election.inserted);
ASSERT_EQ (1, election.election->last_votes.size ()); ASSERT_EQ (1, election.election->last_votes.size ());

View file

@ -1240,6 +1240,8 @@ TEST (wallet, limited_difficulty)
ASSERT_EQ (node.max_work_generate_difficulty (nano::work_version::work_1), node.active.limited_active_difficulty (*genesis.open)); ASSERT_EQ (node.max_work_generate_difficulty (nano::work_version::work_1), node.active.limited_active_difficulty (*genesis.open));
auto send = wallet.send_action (nano::test_genesis_key.pub, nano::keypair ().pub, 1, 1); auto send = wallet.send_action (nano::test_genesis_key.pub, nano::keypair ().pub, 1, 1);
ASSERT_NE (nullptr, send); ASSERT_NE (nullptr, send);
ASSERT_EQ (nano::epoch::epoch_2, send->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, send->sideband ().source_epoch); // Not used for send state blocks
} }
TEST (wallet, epoch_2_validation) TEST (wallet, epoch_2_validation)
@ -1263,12 +1265,16 @@ TEST (wallet, epoch_2_validation)
{ {
auto send = wallet.send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, amount, 1); auto send = wallet.send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, amount, 1);
ASSERT_NE (nullptr, send); ASSERT_NE (nullptr, send);
ASSERT_EQ (nano::epoch::epoch_2, send->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_0, send->sideband ().source_epoch); // Not used for send state blocks
auto receive = wallet.receive_action (*send, nano::test_genesis_key.pub, amount, 1); auto receive = wallet.receive_action (*send, nano::test_genesis_key.pub, amount, 1);
ASSERT_NE (nullptr, receive); ASSERT_NE (nullptr, receive);
if (receive->difficulty () < node.network_params.network.publish_thresholds.base) if (receive->difficulty () < node.network_params.network.publish_thresholds.base)
{ {
ASSERT_GE (receive->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive); ASSERT_GE (receive->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, receive->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_2, receive->sideband ().source_epoch);
break; break;
} }
} }
@ -1325,6 +1331,7 @@ TEST (wallet, epoch_2_receive_propagation)
{ {
ASSERT_GE (receive2->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive); ASSERT_GE (receive2->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, node.store.block_version (node.store.tx_begin_read (), receive2->hash ())); ASSERT_EQ (nano::epoch::epoch_2, node.store.block_version (node.store.tx_begin_read (), receive2->hash ()));
ASSERT_EQ (nano::epoch::epoch_2, receive2->sideband ().source_epoch);
break; break;
} }
} }
@ -1374,6 +1381,7 @@ TEST (wallet, epoch_2_receive_unopened)
{ {
ASSERT_GE (receive1->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive); ASSERT_GE (receive1->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, node.store.block_version (node.store.tx_begin_read (), receive1->hash ())); ASSERT_EQ (nano::epoch::epoch_2, node.store.block_version (node.store.tx_begin_read (), receive1->hash ()));
ASSERT_EQ (nano::epoch::epoch_1, receive1->sideband ().source_epoch);
break; break;
} }
} }

View file

@ -1656,11 +1656,6 @@ epoch (epoch_a), is_send (is_send_a), is_receive (is_receive_a), is_epoch (is_ep
{ {
} }
constexpr size_t nano::block_details::size ()
{
return 1;
}
bool nano::block_details::operator== (nano::block_details const & other_a) const bool nano::block_details::operator== (nano::block_details const & other_a) const
{ {
return epoch == other_a.epoch && is_send == other_a.is_send && is_receive == other_a.is_receive && is_epoch == other_a.is_epoch; return epoch == other_a.epoch && is_send == other_a.is_send && is_receive == other_a.is_receive && is_epoch == other_a.is_epoch;
@ -1728,23 +1723,25 @@ std::string nano::state_subtype (nano::block_details const details_a)
} }
} }
nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::block_details const & details_a) : nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t const height_a, uint64_t const timestamp_a, nano::block_details const & details_a, nano::epoch const source_epoch_a) :
successor (successor_a), successor (successor_a),
account (account_a), account (account_a),
balance (balance_a), balance (balance_a),
height (height_a), height (height_a),
timestamp (timestamp_a), timestamp (timestamp_a),
details (details_a) details (details_a),
source_epoch (source_epoch_a)
{ {
} }
nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::epoch epoch_a, bool is_send, bool is_receive, bool is_epoch) : nano::block_sideband::block_sideband (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t const height_a, uint64_t const timestamp_a, nano::epoch const epoch_a, bool const is_send, bool const is_receive, bool const is_epoch, nano::epoch const source_epoch_a) :
successor (successor_a), successor (successor_a),
account (account_a), account (account_a),
balance (balance_a), balance (balance_a),
height (height_a), height (height_a),
timestamp (timestamp_a), timestamp (timestamp_a),
details (epoch_a, is_send, is_receive, is_epoch) details (epoch_a, is_send, is_receive, is_epoch),
source_epoch (source_epoch_a)
{ {
} }
@ -1768,7 +1765,7 @@ size_t nano::block_sideband::size (nano::block_type type_a)
if (type_a == nano::block_type::state) if (type_a == nano::block_type::state)
{ {
static_assert (sizeof (nano::epoch) == nano::block_details::size (), "block_details is larger than the epoch enum"); static_assert (sizeof (nano::epoch) == nano::block_details::size (), "block_details is larger than the epoch enum");
result += nano::block_details::size (); result += nano::block_details::size () + sizeof (nano::epoch);
} }
return result; return result;
} }
@ -1792,6 +1789,7 @@ void nano::block_sideband::serialize (nano::stream & stream_a, nano::block_type
if (type_a == nano::block_type::state) if (type_a == nano::block_type::state)
{ {
details.serialize (stream_a); details.serialize (stream_a);
nano::write (stream_a, static_cast<uint8_t> (source_epoch));
} }
} }
@ -1823,6 +1821,9 @@ bool nano::block_sideband::deserialize (nano::stream & stream_a, nano::block_typ
if (type_a == nano::block_type::state) if (type_a == nano::block_type::state)
{ {
result = details.deserialize (stream_a); result = details.deserialize (stream_a);
uint8_t source_epoch_uint8_t{ 0 };
nano::read (stream_a, source_epoch_uint8_t);
source_epoch = static_cast<nano::epoch> (source_epoch_uint8_t);
} }
} }
catch (std::runtime_error &) catch (std::runtime_error &)

View file

@ -35,7 +35,10 @@ class block_details
public: public:
block_details () = default; block_details () = default;
block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a); block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a);
static constexpr size_t size (); static constexpr size_t size ()
{
return 1;
}
bool operator== (block_details const & other_a) const; bool operator== (block_details const & other_a) const;
void serialize (nano::stream &) const; void serialize (nano::stream &) const;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
@ -55,8 +58,8 @@ class block_sideband final
{ {
public: public:
block_sideband () = default; block_sideband () = default;
block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::block_details const &); block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, uint64_t const, nano::block_details const &, nano::epoch const source_epoch_a);
block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch, bool is_send, bool is_receive, bool is_epoch); block_sideband (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t const, uint64_t const, nano::epoch const epoch_a, bool const is_send, bool const is_receive, bool const is_epoch, nano::epoch const source_epoch_a);
void serialize (nano::stream &, nano::block_type) const; void serialize (nano::stream &, nano::block_type) const;
bool deserialize (nano::stream &, nano::block_type); bool deserialize (nano::stream &, nano::block_type);
static size_t size (nano::block_type); static size_t size (nano::block_type);
@ -66,6 +69,7 @@ public:
uint64_t height{ 0 }; uint64_t height{ 0 };
uint64_t timestamp{ 0 }; uint64_t timestamp{ 0 };
nano::block_details details; nano::block_details details;
nano::epoch source_epoch{ nano::epoch::epoch_0 };
}; };
class block class block
{ {

View file

@ -1544,6 +1544,14 @@ int main (int argc, char * const * argv)
{ {
print_error_message (boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ())); print_error_message (boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ()));
} }
// Check link epoch version
if (sideband.details.is_receive)
{
if (sideband.source_epoch != node->store.block_version (transaction, block->link ()))
{
print_error_message (boost::str (boost::format ("Incorrect source epoch for block %1%\n") % hash.to_string ()));
}
}
// Check if block work value is correct // Check if block work value is correct
if (block->difficulty () < nano::work_threshold (block->work_version (), block->sideband ().details)) if (block->difficulty () < nano::work_threshold (block->work_version (), block->sideband ().details))
{ {

View file

@ -325,7 +325,7 @@ void nano::mdb_store::upgrade_v14_to_v15 (nano::write_transaction & transaction_
nano::state_block_w_sideband_v14 state_block_w_sideband_v14 (i_state->second); nano::state_block_w_sideband_v14 state_block_w_sideband_v14 (i_state->second);
auto & sideband_v14 = state_block_w_sideband_v14.sideband; auto & sideband_v14 = state_block_w_sideband_v14.sideband;
nano::block_sideband sideband (sideband_v14.account, sideband_v14.successor, sideband_v14.balance, sideband_v14.height, sideband_v14.timestamp, i_state.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1, false, false, false); nano::block_sideband_v18 sideband (sideband_v14.account, sideband_v14.successor, sideband_v14.balance, sideband_v14.height, sideband_v14.timestamp, i_state.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1, false, false, false);
// Write these out // Write these out
std::vector<uint8_t> data; std::vector<uint8_t> data;
@ -514,7 +514,7 @@ void nano::mdb_store::upgrade_v17_to_v18 (nano::write_transaction const & transa
is_receive = true; is_receive = true;
} }
nano::block_sideband new_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, is_send, is_receive, is_epoch); nano::block_sideband_v18 new_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, is_send, is_receive, is_epoch);
// Write these out // Write these out
std::vector<uint8_t> data; std::vector<uint8_t> data;
{ {
@ -551,17 +551,23 @@ void nano::mdb_store::upgrade_v18_to_v19 (nano::write_transaction const & transa
for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>>> (transaction_a, change_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>> (nullptr)); i != n; ++i) for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>>> (transaction_a, change_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::change_block>> (nullptr)); i != n; ++i)
{ {
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, i->second.sideband } }; nano::block_sideband_v18 const & old_sideband (i->second.sideband);
nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0);
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } };
} }
for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>>> (transaction_a, open_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>> (nullptr)); i != n; ++i) for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>>> (transaction_a, open_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::open_block>> (nullptr)); i != n; ++i)
{ {
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, i->second.sideband } }; nano::block_sideband_v18 const & old_sideband (i->second.sideband);
nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0);
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } };
} }
for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>>> (transaction_a, receive_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>> (nullptr)); i != n; ++i) for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>>> (transaction_a, receive_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::receive_block>> (nullptr)); i != n; ++i)
{ {
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, i->second.sideband } }; nano::block_sideband_v18 const & old_sideband (i->second.sideband);
nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0);
legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } };
} }
release_assert (!mdb_drop (env.tx (transaction_a), receive_blocks, 1)); release_assert (!mdb_drop (env.tx (transaction_a), receive_blocks, 1));
@ -607,7 +613,7 @@ void nano::mdb_store::upgrade_v18_to_v19 (nano::write_transaction const & transa
{ {
nano::vectorstream stream (data); nano::vectorstream stream (data);
nano::serialize_block (stream, *block_w_sideband_v18.block); nano::serialize_block (stream, *block_w_sideband_v18.block);
block_w_sideband_v18.sideband.serialize (stream, nano::block_type::send); block_w_sideband_v18.sideband.serialize (stream, nano::block_type::send); // Equal to new version for legacy blocks
} }
nano::mdb_val value{ data.size (), (void *)data.data () }; nano::mdb_val value{ data.size (), (void *)data.data () };
@ -643,17 +649,36 @@ void nano::mdb_store::upgrade_v18_to_v19 (nano::write_transaction const & transa
// Write state blocks to a new table (this was not done in memory as it would push us above memory requirements) // Write state blocks to a new table (this was not done in memory as it would push us above memory requirements)
MDB_dbi temp_state_blocks; MDB_dbi temp_state_blocks;
{ {
auto type_state (nano::block_type::state);
mdb_dbi_open (env.tx (transaction_a), "temp_state_blocks", MDB_CREATE, &temp_state_blocks); mdb_dbi_open (env.tx (transaction_a), "temp_state_blocks", MDB_CREATE, &temp_state_blocks);
for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>>> (transaction_a, state_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>> (nullptr)); i != n; ++i) for (auto i (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>> (std::make_unique<nano::mdb_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>>> (transaction_a, state_blocks))), n (nano::store_iterator<nano::block_hash, nano::block_w_sideband_v18<nano::state_block>> (nullptr)); i != n; ++i)
{ {
auto const & block_w_sideband_v18 (i->second); auto const & block_w_sideband_v18 (i->second);
nano::block_sideband_v18 const & old_sideband (block_w_sideband_v18.sideband);
nano::epoch source_epoch (nano::epoch::epoch_0);
// Source block v18 epoch
if (old_sideband.details.is_receive)
{
auto db_val (block_raw_get_by_type_v18 (transaction_a, block_w_sideband_v18.block->link (), type_state));
if (db_val.is_initialized ())
{
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (db_val.get ().data ()), db_val.get ().size ());
auto source_block (nano::deserialize_block (stream, type_state));
release_assert (source_block != nullptr);
nano::block_sideband_v18 source_sideband;
auto error (source_sideband.deserialize (stream, type_state));
release_assert (!error);
source_epoch = source_sideband.details.epoch;
}
}
nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, old_sideband.details.epoch, old_sideband.details.is_send, old_sideband.details.is_receive, old_sideband.details.is_epoch, source_epoch);
std::vector<uint8_t> data; std::vector<uint8_t> data;
{ {
nano::vectorstream stream (data); nano::vectorstream stream (data);
nano::serialize_block (stream, *block_w_sideband_v18.block); nano::serialize_block (stream, *block_w_sideband_v18.block);
block_w_sideband_v18.sideband.serialize (stream, nano::block_type::state); new_sideband.serialize (stream, nano::block_type::state);
} }
nano::mdb_val value{ data.size (), (void *)data.data () }; nano::mdb_val value{ data.size (), (void *)data.data () };
@ -888,10 +913,10 @@ std::shared_ptr<nano::block> nano::mdb_store::block_get_v18 (nano::transaction c
nano::bufferstream stream (reinterpret_cast<uint8_t const *> (value.data ()), value.size ()); nano::bufferstream stream (reinterpret_cast<uint8_t const *> (value.data ()), value.size ());
result = nano::deserialize_block (stream, type); result = nano::deserialize_block (stream, type);
release_assert (result != nullptr); release_assert (result != nullptr);
nano::block_sideband sideband; nano::block_sideband_v18 sideband;
auto error = (sideband.deserialize (stream, type)); auto error = (sideband.deserialize (stream, type));
release_assert (!error); release_assert (!error);
result->sideband_set (sideband); result->sideband_set (nano::block_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, sideband.details.is_send, sideband.details.is_receive, sideband.details.is_epoch, nano::epoch::epoch_0));
} }
return result; return result;
} }

View file

@ -23,7 +23,7 @@ class block_w_sideband_v18
{ {
public: public:
std::shared_ptr<T> block; std::shared_ptr<T> block;
nano::block_sideband sideband; nano::block_sideband_v18 sideband;
}; };
class block_w_sideband class block_w_sideband

View file

@ -31,7 +31,7 @@ public:
{ {
auto hash_l (genesis_a.hash ()); auto hash_l (genesis_a.hash ());
debug_assert (latest_begin (transaction_a) == latest_end ()); debug_assert (latest_begin (transaction_a) == latest_end ());
genesis_a.open->sideband_set (nano::block_sideband (network_params.ledger.genesis_account, 0, network_params.ledger.genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false)); genesis_a.open->sideband_set (nano::block_sideband (network_params.ledger.genesis_account, 0, network_params.ledger.genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0));
block_put (transaction_a, hash_l, *genesis_a.open); block_put (transaction_a, hash_l, *genesis_a.open);
++ledger_cache_a.block_count; ++ledger_cache_a.block_count;
confirmation_height_put (transaction_a, network_params.ledger.genesis_account, nano::confirmation_height_info{ 1, genesis_a.hash () }); confirmation_height_put (transaction_a, network_params.ledger.genesis_account, nano::confirmation_height_info{ 1, genesis_a.hash () });
@ -371,7 +371,6 @@ public:
nano::epoch block_version (nano::transaction const & transaction_a, nano::block_hash const & hash_a) override nano::epoch block_version (nano::transaction const & transaction_a, nano::block_hash const & hash_a) override
{ {
nano::db_val<Val> value;
auto block = block_get (transaction_a, hash_a); auto block = block_get (transaction_a, hash_a);
if (block && block->type () == nano::block_type::state) if (block && block->type () == nano::block_type::state)
{ {

View file

@ -141,8 +141,7 @@ public:
} }
else if (!block_a.hashables.link.is_zero () && !ledger.is_epoch_link (block_a.hashables.link)) else if (!block_a.hashables.link.is_zero () && !ledger.is_epoch_link (block_a.hashables.link))
{ {
auto source_version (ledger.store.block_version (transaction, block_a.hashables.link)); nano::pending_info pending_info (ledger.account (transaction, block_a.hashables.link), block_a.hashables.balance.number () - balance, block_a.sideband ().source_epoch);
nano::pending_info pending_info (ledger.account (transaction, block_a.hashables.link), block_a.hashables.balance.number () - balance, source_version);
ledger.store.pending_put (transaction, nano::pending_key (block_a.hashables.account, block_a.hashables.link), pending_info); ledger.store.pending_put (transaction, nano::pending_key (block_a.hashables.account, block_a.hashables.link), pending_info);
ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::receive); ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::receive);
} }
@ -274,6 +273,7 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress) if (result.code == nano::process_result::progress)
{ {
nano::epoch epoch (nano::epoch::epoch_0); nano::epoch epoch (nano::epoch::epoch_0);
nano::epoch source_epoch (nano::epoch::epoch_0);
nano::account_info info; nano::account_info info;
nano::amount amount (block_a.hashables.balance); nano::amount amount (block_a.hashables.balance);
auto is_send (false); auto is_send (false);
@ -323,7 +323,8 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress) if (result.code == nano::process_result::progress)
{ {
result.code = amount == pending.amount ? nano::process_result::progress : nano::process_result::balance_mismatch; result.code = amount == pending.amount ? nano::process_result::progress : nano::process_result::balance_mismatch;
epoch = std::max (epoch, pending.epoch); source_epoch = pending.epoch;
epoch = std::max (epoch, source_epoch);
} }
} }
} }
@ -341,7 +342,7 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress) if (result.code == nano::process_result::progress)
{ {
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block);
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details, source_epoch));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
if (!info.head.is_zero ()) if (!info.head.is_zero ())
@ -438,7 +439,7 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress) if (result.code == nano::process_result::progress)
{ {
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block);
block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch); nano::account_info new_info (hash, block_a.representative (), info.open_block.is_zero () ? hash : info.open_block, info.balance, nano::seconds_since_epoch (), info.block_count + 1, epoch);
ledger.change_latest (transaction, block_a.hashables.account, info, new_info); ledger.change_latest (transaction, block_a.hashables.account, info, new_info);
@ -502,7 +503,7 @@ void ledger_processor::change_block (nano::change_block & block_a)
{ {
debug_assert (!validate_message (account, hash, block_a.signature)); debug_assert (!validate_message (account, hash, block_a.signature));
result.verified = nano::signature_verification::valid; result.verified = nano::signature_verification::valid;
block_a.sideband_set (nano::block_sideband (account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
auto balance (ledger.balance (transaction, block_a.hashables.previous)); auto balance (ledger.balance (transaction, block_a.hashables.previous));
ledger.cache.rep_weights.representation_add (block_a.representative (), balance); ledger.cache.rep_weights.representation_add (block_a.representative (), balance);
@ -562,7 +563,7 @@ void ledger_processor::send_block (nano::send_block & block_a)
{ {
auto amount (info.balance.number () - block_a.hashables.balance.number ()); auto amount (info.balance.number () - block_a.hashables.balance.number ());
ledger.cache.rep_weights.representation_add (info.representative, 0 - amount); ledger.cache.rep_weights.representation_add (info.representative, 0 - amount);
block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
nano::account_info new_info (hash, info.representative, info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0); nano::account_info new_info (hash, info.representative, info.open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
ledger.change_latest (transaction, account, info, new_info); ledger.change_latest (transaction, account, info, new_info);
@ -633,7 +634,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a)
(void)error; (void)error;
debug_assert (!error); debug_assert (!error);
ledger.store.pending_del (transaction, key); ledger.store.pending_del (transaction, key);
block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
nano::account_info new_info (hash, info.representative, info.open_block, new_balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0); nano::account_info new_info (hash, info.representative, info.open_block, new_balance, nano::seconds_since_epoch (), info.block_count + 1, nano::epoch::epoch_0);
ledger.change_latest (transaction, account, info, new_info); ledger.change_latest (transaction, account, info, new_info);
@ -701,7 +702,7 @@ void ledger_processor::open_block (nano::open_block & block_a)
(void)error; (void)error;
debug_assert (!error); debug_assert (!error);
ledger.store.pending_del (transaction, key); ledger.store.pending_del (transaction, key);
block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), block_details)); block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */));
ledger.store.block_put (transaction, hash, block_a); ledger.store.block_put (transaction, hash, block_a);
nano::account_info new_info (hash, block_a.representative (), hash, pending.amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0); nano::account_info new_info (hash, block_a.representative (), hash, pending.amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0);
ledger.change_latest (transaction, block_a.hashables.account, info, new_info); ledger.change_latest (transaction, block_a.hashables.account, info, new_info);

View file

@ -142,3 +142,108 @@ bool nano::block_sideband_v14::deserialize (nano::stream & stream_a)
return result; return result;
} }
nano::block_sideband_v18::block_sideband_v18 (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::block_details const & details_a) :
successor (successor_a),
account (account_a),
balance (balance_a),
height (height_a),
timestamp (timestamp_a),
details (details_a)
{
}
nano::block_sideband_v18::block_sideband_v18 (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::epoch epoch_a, bool is_send, bool is_receive, bool is_epoch) :
successor (successor_a),
account (account_a),
balance (balance_a),
height (height_a),
timestamp (timestamp_a),
details (epoch_a, is_send, is_receive, is_epoch)
{
}
size_t nano::block_sideband_v18::size (nano::block_type type_a)
{
size_t result (0);
result += sizeof (successor);
if (type_a != nano::block_type::state && type_a != nano::block_type::open)
{
result += sizeof (account);
}
if (type_a != nano::block_type::open)
{
result += sizeof (height);
}
if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open)
{
result += sizeof (balance);
}
result += sizeof (timestamp);
if (type_a == nano::block_type::state)
{
static_assert (sizeof (nano::epoch) == nano::block_details::size (), "block_details_v18 is larger than the epoch enum");
result += nano::block_details::size ();
}
return result;
}
void nano::block_sideband_v18::serialize (nano::stream & stream_a, nano::block_type type_a) const
{
nano::write (stream_a, successor.bytes);
if (type_a != nano::block_type::state && type_a != nano::block_type::open)
{
nano::write (stream_a, account.bytes);
}
if (type_a != nano::block_type::open)
{
nano::write (stream_a, boost::endian::native_to_big (height));
}
if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open)
{
nano::write (stream_a, balance.bytes);
}
nano::write (stream_a, boost::endian::native_to_big (timestamp));
if (type_a == nano::block_type::state)
{
details.serialize (stream_a);
}
}
bool nano::block_sideband_v18::deserialize (nano::stream & stream_a, nano::block_type type_a)
{
bool result (false);
try
{
nano::read (stream_a, successor.bytes);
if (type_a != nano::block_type::state && type_a != nano::block_type::open)
{
nano::read (stream_a, account.bytes);
}
if (type_a != nano::block_type::open)
{
nano::read (stream_a, height);
boost::endian::big_to_native_inplace (height);
}
else
{
height = 1;
}
if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open)
{
nano::read (stream_a, balance.bytes);
}
nano::read (stream_a, timestamp);
boost::endian::big_to_native_inplace (timestamp);
if (type_a == nano::block_type::state)
{
result = details.deserialize (stream_a);
}
}
catch (std::runtime_error &)
{
result = true;
}
return result;
}

View file

@ -55,4 +55,20 @@ public:
std::shared_ptr<nano::state_block> state_block; std::shared_ptr<nano::state_block> state_block;
nano::block_sideband_v14 sideband; nano::block_sideband_v14 sideband;
}; };
class block_sideband_v18 final
{
public:
block_sideband_v18 () = default;
block_sideband_v18 (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::block_details const &);
block_sideband_v18 (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch, bool is_send, bool is_receive, bool is_epoch);
void serialize (nano::stream &, nano::block_type) const;
bool deserialize (nano::stream &, nano::block_type);
static size_t size (nano::block_type);
nano::block_hash successor{ 0 };
nano::account account{ 0 };
nano::amount balance{ 0 };
uint64_t height{ 0 };
uint64_t timestamp{ 0 };
nano::block_details details;
};
} }