diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 289e4adc99..ddaf19dd5d 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -90,7 +90,6 @@ TEST (block_store, block_details_serialization) TEST (block_store, sideband_serialization) { nano::block_sideband sideband1; - sideband1.type = nano::block_type::receive; sideband1.account = 1; sideband1.balance = 2; sideband1.height = 3; @@ -99,12 +98,11 @@ TEST (block_store, sideband_serialization) std::vector vector; { nano::vectorstream stream1 (vector); - sideband1.serialize (stream1); + sideband1.serialize (stream1, nano::block_type::receive); } nano::bufferstream stream2 (vector.data (), vector.size ()); nano::block_sideband sideband2; - sideband2.type = nano::block_type::receive; - ASSERT_FALSE (sideband2.deserialize (stream2)); + ASSERT_FALSE (sideband2.deserialize (stream2, nano::block_type::receive)); ASSERT_EQ (sideband1.account, sideband2.account); ASSERT_EQ (sideband1.balance, sideband2.balance); ASSERT_EQ (sideband1.height, sideband2.height); @@ -118,13 +116,13 @@ TEST (block_store, add_item) auto store = nano::make_store (logger, nano::unique_path ()); ASSERT_TRUE (!store->init_error ()); nano::open_block block (0, 1, 0, nano::keypair ().prv, 0, 0); + block.sideband_set ({}); auto hash1 (block.hash ()); auto transaction (store->tx_begin_write ()); auto latest1 (store->block_get (transaction, hash1)); ASSERT_EQ (nullptr, latest1); ASSERT_FALSE (store->block_exists (transaction, hash1)); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash1, block, sideband); + store->block_put (transaction, hash1, block); auto latest2 (store->block_get (transaction, hash1)); ASSERT_NE (nullptr, latest2); ASSERT_EQ (block, *latest2); @@ -141,20 +139,30 @@ TEST (block_store, clear_successor) auto store = nano::make_store (logger, nano::unique_path ()); ASSERT_TRUE (!store->init_error ()); nano::open_block block1 (0, 1, 0, nano::keypair ().prv, 0, 0); + block1.sideband_set ({}); auto transaction (store->tx_begin_write ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, block1.hash (), block1, sideband); + store->block_put (transaction, block1.hash (), block1); nano::open_block block2 (0, 2, 0, nano::keypair ().prv, 0, 0); - store->block_put (transaction, block2.hash (), block2, sideband); - ASSERT_NE (nullptr, store->block_get (transaction, block1.hash (), &sideband)); - ASSERT_EQ (0, sideband.successor.number ()); - sideband.successor = block2.hash (); - store->block_put (transaction, block1.hash (), block1, sideband); - ASSERT_NE (nullptr, store->block_get (transaction, block1.hash (), &sideband)); - ASSERT_EQ (block2.hash (), sideband.successor); + block2.sideband_set ({}); + store->block_put (transaction, block2.hash (), block2); + auto block2_store (store->block_get (transaction, block1.hash ())); + ASSERT_NE (nullptr, block2_store); + ASSERT_EQ (0, block2_store->sideband ().successor.number ()); + auto modified_sideband = block2_store->sideband (); + modified_sideband.successor = block2.hash (); + block1.sideband_set (modified_sideband); + store->block_put (transaction, block1.hash (), block1); + { + auto block1_store (store->block_get (transaction, block1.hash ())); + ASSERT_NE (nullptr, block1_store); + ASSERT_EQ (block2.hash (), block1_store->sideband ().successor); + } store->block_successor_clear (transaction, block1.hash ()); - ASSERT_NE (nullptr, store->block_get (transaction, block1.hash (), &sideband)); - ASSERT_EQ (0, sideband.successor.number ()); + { + auto block1_store (store->block_get (transaction, block1.hash ())); + ASSERT_NE (nullptr, block1_store); + ASSERT_EQ (0, block1_store->sideband ().successor.number ()); + } } TEST (block_store, add_nonempty_block) @@ -164,13 +172,13 @@ TEST (block_store, add_nonempty_block) ASSERT_TRUE (!store->init_error ()); nano::keypair key1; nano::open_block block (0, 1, 0, nano::keypair ().prv, 0, 0); + block.sideband_set ({}); auto hash1 (block.hash ()); block.signature = nano::sign_message (key1.prv, key1.pub, hash1); auto transaction (store->tx_begin_write ()); auto latest1 (store->block_get (transaction, hash1)); ASSERT_EQ (nullptr, latest1); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash1, block, sideband); + store->block_put (transaction, hash1, block); auto latest2 (store->block_get (transaction, hash1)); ASSERT_NE (nullptr, latest2); ASSERT_EQ (block, *latest2); @@ -183,21 +191,21 @@ TEST (block_store, add_two_items) ASSERT_TRUE (!store->init_error ()); nano::keypair key1; nano::open_block block (0, 1, 1, nano::keypair ().prv, 0, 0); + block.sideband_set ({}); auto hash1 (block.hash ()); block.signature = nano::sign_message (key1.prv, key1.pub, hash1); auto transaction (store->tx_begin_write ()); auto latest1 (store->block_get (transaction, hash1)); ASSERT_EQ (nullptr, latest1); nano::open_block block2 (0, 1, 3, nano::keypair ().prv, 0, 0); + block2.sideband_set ({}); block2.hashables.account = 3; auto hash2 (block2.hash ()); block2.signature = nano::sign_message (key1.prv, key1.pub, hash2); auto latest2 (store->block_get (transaction, hash2)); ASSERT_EQ (nullptr, latest2); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash1, block, sideband); - nano::block_sideband sideband2 (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash2, block2, sideband2); + store->block_put (transaction, hash1, block); + store->block_put (transaction, hash2, block2); auto latest3 (store->block_get (transaction, hash1)); ASSERT_NE (nullptr, latest3); ASSERT_EQ (block, *latest3); @@ -215,15 +223,15 @@ TEST (block_store, add_receive) nano::keypair key1; nano::keypair key2; nano::open_block block1 (0, 1, 0, nano::keypair ().prv, 0, 0); + block1.sideband_set ({}); auto transaction (store->tx_begin_write ()); - nano::block_sideband sideband1 (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, block1.hash (), block1, sideband1); + store->block_put (transaction, block1.hash (), block1); nano::receive_block block (block1.hash (), 1, nano::keypair ().prv, 2, 3); + block.sideband_set ({}); nano::block_hash hash1 (block.hash ()); auto latest1 (store->block_get (transaction, hash1)); ASSERT_EQ (nullptr, latest1); - nano::block_sideband sideband (nano::block_type::receive, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash1, block, sideband); + store->block_put (transaction, hash1, block); auto latest2 (store->block_get (transaction, hash1)); ASSERT_NE (nullptr, latest2); ASSERT_EQ (block, *latest2); @@ -463,9 +471,9 @@ TEST (block_store, one_block) auto store = nano::make_store (logger, nano::unique_path ()); ASSERT_TRUE (!store->init_error ()); nano::open_block block1 (0, 1, 0, nano::keypair ().prv, 0, 0); + block1.sideband_set ({}); auto transaction (store->tx_begin_write ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, block1.hash (), block1, sideband); + store->block_put (transaction, block1.hash (), block1); ASSERT_TRUE (store->block_exists (transaction, block1.hash ())); } @@ -560,19 +568,19 @@ TEST (block_store, two_block) auto store = nano::make_store (logger, nano::unique_path ()); ASSERT_TRUE (!store->init_error ()); nano::open_block block1 (0, 1, 1, nano::keypair ().prv, 0, 0); + block1.sideband_set ({}); block1.hashables.account = 1; std::vector hashes; std::vector blocks; hashes.push_back (block1.hash ()); blocks.push_back (block1); auto transaction (store->tx_begin_write ()); - nano::block_sideband sideband1 (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hashes[0], block1, sideband1); + store->block_put (transaction, hashes[0], block1); nano::open_block block2 (0, 1, 2, nano::keypair ().prv, 0, 0); + block2.sideband_set ({}); hashes.push_back (block2.hash ()); blocks.push_back (block2); - nano::block_sideband sideband2 (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hashes[1], block2, sideband2); + store->block_put (transaction, hashes[1], block2); ASSERT_TRUE (store->block_exists (transaction, block1.hash ())); ASSERT_TRUE (store->block_exists (transaction, block2.hash ())); } @@ -755,12 +763,12 @@ TEST (block_store, block_replace) auto store = nano::make_store (logger, nano::unique_path ()); ASSERT_TRUE (!store->init_error ()); nano::send_block send1 (0, 0, 0, nano::keypair ().prv, 0, 1); + send1.sideband_set ({}); nano::send_block send2 (0, 0, 0, nano::keypair ().prv, 0, 2); + send2.sideband_set ({}); auto transaction (store->tx_begin_write ()); - nano::block_sideband sideband1 (nano::block_type::send, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, 0, send1, sideband1); - nano::block_sideband sideband2 (nano::block_type::send, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, 0, send2, sideband2); + store->block_put (transaction, 0, send1); + store->block_put (transaction, 0, send2); auto block3 (store->block_get (transaction, 0)); ASSERT_NE (nullptr, block3); ASSERT_EQ (2, block3->block_work ()); @@ -775,9 +783,9 @@ TEST (block_store, block_count) auto transaction (store->tx_begin_write ()); ASSERT_EQ (0, store->block_count (transaction).sum ()); nano::open_block block (0, 1, 0, nano::keypair ().prv, 0, 0); + block.sideband_set ({}); auto hash1 (block.hash ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, hash1, block, sideband); + store->block_put (transaction, hash1, block); } auto transaction (store->tx_begin_read ()); ASSERT_EQ (1, store->block_count (transaction).sum ()); @@ -1172,13 +1180,13 @@ TEST (block_store, state_block) nano::genesis genesis; nano::keypair key1; nano::state_block block1 (1, genesis.hash (), 3, 4, 6, key1.prv, key1.pub, 7); + block1.sideband_set ({}); { nano::ledger_cache ledger_cache; auto transaction (store->tx_begin_write ()); store->initialize (transaction, genesis, ledger_cache); ASSERT_EQ (nano::block_type::state, block1.type ()); - nano::block_sideband sideband1 (nano::block_type::state, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (transaction, block1.hash (), block1, sideband1); + store->block_put (transaction, block1.hash (), block1); ASSERT_TRUE (store->block_exists (transaction, block1.hash ())); auto block2 (store->block_get (transaction, block1.hash ())); ASSERT_NE (nullptr, block2); @@ -1209,10 +1217,9 @@ TEST (mdb_block_store, upgrade_sideband_genesis) nano::ledger_cache ledger_cache; store.initialize (transaction, genesis, ledger_cache); modify_account_info_to_v13 (store, transaction, nano::genesis_account, nano::genesis_hash); - nano::block_sideband sideband; - auto genesis_block (store.block_get (transaction, genesis.hash (), &sideband)); + auto genesis_block (store.block_get (transaction, genesis.hash ())); ASSERT_NE (nullptr, genesis_block); - ASSERT_EQ (1, sideband.height); + 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; @@ -1226,10 +1233,9 @@ TEST (mdb_block_store, upgrade_sideband_genesis) ASSERT_FALSE (store.init_error ()); auto transaction (store.tx_begin_read ()); ASSERT_TRUE (store.full_sideband (transaction)); - nano::block_sideband sideband; - auto genesis_block (store.block_get (transaction, genesis.hash (), &sideband)); + auto genesis_block (store.block_get (transaction, genesis.hash ())); ASSERT_NE (nullptr, genesis_block); - ASSERT_EQ (1, sideband.height); + ASSERT_EQ (1, genesis_block->sideband ().height); } TEST (mdb_block_store, upgrade_sideband_two_blocks) @@ -1265,14 +1271,12 @@ TEST (mdb_block_store, upgrade_sideband_two_blocks) ASSERT_FALSE (store.init_error ()); auto transaction (store.tx_begin_read ()); ASSERT_TRUE (store.full_sideband (transaction)); - nano::block_sideband sideband; - auto genesis_block (store.block_get (transaction, genesis.hash (), &sideband)); + auto genesis_block (store.block_get (transaction, genesis.hash ())); ASSERT_NE (nullptr, genesis_block); - ASSERT_EQ (1, sideband.height); - nano::block_sideband sideband2; - auto block2 (store.block_get (transaction, hash2, &sideband2)); + ASSERT_EQ (1, genesis_block->sideband ().height); + auto block2 (store.block_get (transaction, hash2)); ASSERT_NE (nullptr, block2); - ASSERT_EQ (2, sideband2.height); + ASSERT_EQ (2, block2->sideband ().height); } TEST (mdb_block_store, upgrade_sideband_two_accounts) @@ -1314,18 +1318,15 @@ TEST (mdb_block_store, upgrade_sideband_two_accounts) ASSERT_FALSE (store.init_error ()); auto transaction (store.tx_begin_read ()); ASSERT_TRUE (store.full_sideband (transaction)); - nano::block_sideband sideband; - auto genesis_block (store.block_get (transaction, genesis.hash (), &sideband)); + auto genesis_block (store.block_get (transaction, genesis.hash ())); ASSERT_NE (nullptr, genesis_block); - ASSERT_EQ (1, sideband.height); - nano::block_sideband sideband2; - auto block2 (store.block_get (transaction, hash2, &sideband2)); + ASSERT_EQ (1, genesis_block->sideband ().height); + auto block2 (store.block_get (transaction, hash2)); ASSERT_NE (nullptr, block2); - ASSERT_EQ (2, sideband2.height); - nano::block_sideband sideband3; - auto block3 (store.block_get (transaction, hash3, &sideband3)); + ASSERT_EQ (2, block2->sideband ().height); + auto block3 (store.block_get (transaction, hash3)); ASSERT_NE (nullptr, block3); - ASSERT_EQ (1, sideband3.height); + ASSERT_EQ (1, block3->sideband ().height); } TEST (mdb_block_store, insert_after_legacy) @@ -1406,9 +1407,8 @@ TEST (mdb_block_store, upgrade_sideband_epoch) auto transaction (store.tx_begin_write ()); ASSERT_TRUE (store.full_sideband (transaction)); ASSERT_EQ (nano::epoch::epoch_1, store.block_version (transaction, hash2)); - nano::block_sideband sideband; - auto block1 (store.block_get (transaction, hash2, &sideband)); - ASSERT_NE (0, sideband.height); + 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 ())); @@ -1452,42 +1452,30 @@ TEST (mdb_block_store, sideband_height) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive).code); nano::open_block open (state_send3.hash (), nano::test_genesis_key.pub, key3.pub, key3.prv, key3.pub, *pool.generate (key3.pub)); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, open).code); - nano::block_sideband sideband1; - auto block1 (store.block_get (transaction, genesis.hash (), &sideband1)); - ASSERT_EQ (sideband1.height, 1); - nano::block_sideband sideband2; - auto block2 (store.block_get (transaction, send.hash (), &sideband2)); - ASSERT_EQ (sideband2.height, 2); - nano::block_sideband sideband3; - auto block3 (store.block_get (transaction, receive.hash (), &sideband3)); - ASSERT_EQ (sideband3.height, 3); - nano::block_sideband sideband4; - auto block4 (store.block_get (transaction, change.hash (), &sideband4)); - ASSERT_EQ (sideband4.height, 4); - nano::block_sideband sideband5; - auto block5 (store.block_get (transaction, state_send1.hash (), &sideband5)); - ASSERT_EQ (sideband5.height, 5); - nano::block_sideband sideband6; - auto block6 (store.block_get (transaction, state_send2.hash (), &sideband6)); - ASSERT_EQ (sideband6.height, 6); - nano::block_sideband sideband7; - auto block7 (store.block_get (transaction, state_send3.hash (), &sideband7)); - ASSERT_EQ (sideband7.height, 7); - nano::block_sideband sideband8; - auto block8 (store.block_get (transaction, state_open.hash (), &sideband8)); - ASSERT_EQ (sideband8.height, 1); - nano::block_sideband sideband9; - auto block9 (store.block_get (transaction, epoch.hash (), &sideband9)); - ASSERT_EQ (sideband9.height, 2); - nano::block_sideband sideband10; - auto block10 (store.block_get (transaction, epoch_open.hash (), &sideband10)); - ASSERT_EQ (sideband10.height, 1); - nano::block_sideband sideband11; - auto block11 (store.block_get (transaction, state_receive.hash (), &sideband11)); - ASSERT_EQ (sideband11.height, 2); - nano::block_sideband sideband12; - auto block12 (store.block_get (transaction, open.hash (), &sideband12)); - ASSERT_EQ (sideband12.height, 1); + auto block1 (store.block_get (transaction, genesis.hash ())); + ASSERT_EQ (block1->sideband ().height, 1); + auto block2 (store.block_get (transaction, send.hash ())); + ASSERT_EQ (block2->sideband ().height, 2); + auto block3 (store.block_get (transaction, receive.hash ())); + ASSERT_EQ (block3->sideband ().height, 3); + auto block4 (store.block_get (transaction, change.hash ())); + ASSERT_EQ (block4->sideband ().height, 4); + auto block5 (store.block_get (transaction, state_send1.hash ())); + ASSERT_EQ (block5->sideband ().height, 5); + auto block6 (store.block_get (transaction, state_send2.hash ())); + ASSERT_EQ (block6->sideband ().height, 6); + auto block7 (store.block_get (transaction, state_send3.hash ())); + ASSERT_EQ (block7->sideband ().height, 7); + auto block8 (store.block_get (transaction, state_open.hash ())); + ASSERT_EQ (block8->sideband ().height, 1); + auto block9 (store.block_get (transaction, epoch.hash ())); + ASSERT_EQ (block9->sideband ().height, 2); + auto block10 (store.block_get (transaction, epoch_open.hash ())); + ASSERT_EQ (block10->sideband ().height, 1); + auto block11 (store.block_get (transaction, state_receive.hash ())); + ASSERT_EQ (block11->sideband ().height, 2); + auto block12 (store.block_get (transaction, open.hash ())); + ASSERT_EQ (block12->sideband ().height, 1); } TEST (block_store, peers) @@ -1751,14 +1739,12 @@ TEST (mdb_block_store, upgrade_v14_v15) ASSERT_NE (error_get_state_v1, MDB_SUCCESS); // Check that the epochs are set correctly for the sideband, accounts and pending entries - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_send.hash (), &sideband); + auto block = store.block_get (transaction, state_send.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - block = store.block_get (transaction, send.hash (), &sideband); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + block = store.block_get (transaction, send.hash ()); ASSERT_NE (block, nullptr); - nano::block_sideband sideband1; - ASSERT_EQ (sideband1.details.epoch, nano::epoch::epoch_0); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); nano::pending_info pending_info; store.pending_get (transaction, nano::pending_key (nano::test_genesis_key.pub, send.hash ()), pending_info); @@ -1818,7 +1804,7 @@ TEST (mdb_block_store, upgrade_v16_v17) nano::state_block block2 (nano::test_genesis_key.pub, block1.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio - 1, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (block1.hash ())); nano::state_block block3 (nano::test_genesis_key.pub, block2.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio - 2, nano::test_genesis_key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (block2.hash ())); - auto code = [block1, block2, block3](auto confirmation_height, nano::block_hash const & expected_cemented_frontier) { + auto code = [&block1, &block2, &block3](auto confirmation_height, nano::block_hash const & expected_cemented_frontier) { auto path (nano::unique_path ()); nano::mdb_val value; { @@ -1937,124 +1923,112 @@ TEST (mdb_block_store, upgrade_v17_v18) // Check that sidebands are correctly populated { // Non-state unaffected - nano::block_sideband sideband; - auto block = store.block_get (transaction, send_zero.hash (), &sideband); + auto block = store.block_get (transaction, send_zero.hash ()); ASSERT_NE (block, nullptr); // All defaults - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_0); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State receive from old zero send - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_receive_zero.hash (), &sideband); + auto block = store.block_get (transaction, state_receive_zero.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_0); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); } { // Epoch - nano::block_sideband sideband; - auto block = store.block_get (transaction, epoch.hash (), &sideband); + auto block = store.block_get (transaction, epoch.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_TRUE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_TRUE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State send - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_send.hash (), &sideband); + auto block = store.block_get (transaction, state_send.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State receive - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_receive.hash (), &sideband); + auto block = store.block_get (transaction, state_receive.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); } { // State change - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_change.hash (), &sideband); + auto block = store.block_get (transaction, state_change.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State send + change - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_send_change.hash (), &sideband); + auto block = store.block_get (transaction, state_send_change.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // Epoch on unopened account - nano::block_sideband sideband; - auto block = store.block_get (transaction, epoch_first.hash (), &sideband); + auto block = store.block_get (transaction, epoch_first.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_2); - ASSERT_TRUE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); + ASSERT_TRUE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State open following epoch - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_receive2.hash (), &sideband); + auto block = store.block_get (transaction, state_receive2.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_2); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); } { // Another state send - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_send2.hash (), &sideband); + auto block = store.block_get (transaction, state_send2.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } { // State open - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_open.hash (), &sideband); + auto block = store.block_get (transaction, state_open.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); } { // State send to an epoch link - nano::block_sideband sideband; - auto block = store.block_get (transaction, state_send_epoch_link.hash (), &sideband); + auto block = store.block_get (transaction, state_send_epoch_link.hash ()); ASSERT_NE (block, nullptr); - ASSERT_EQ (sideband.details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); } // Version should be correct ASSERT_LT (17, store.version_get (transaction)); @@ -2166,8 +2140,8 @@ TEST (mdb_block_store, upgrade_confirmation_height_many) { nano::account account (i); nano::open_block open (1, nano::genesis_account, 3, nullptr); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store.block_put (transaction, open.hash (), open, sideband); + 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); @@ -2224,6 +2198,7 @@ TEST (block_store, reset_renew_existing_transaction) nano::keypair key1; nano::open_block block (0, 1, 1, nano::keypair ().prv, 0, 0); + block.sideband_set ({}); auto hash1 (block.hash ()); auto read_transaction = store->tx_begin_read (); @@ -2237,8 +2212,7 @@ TEST (block_store, reset_renew_existing_transaction) // Write the block { auto write_transaction (store->tx_begin_write ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store->block_put (write_transaction, hash1, block, sideband); + store->block_put (write_transaction, hash1, block); } read_transaction.renew (); @@ -2297,11 +2271,10 @@ void write_sideband_v12 (nano::mdb_store & store_a, nano::transaction & transact void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a) { - nano::block_sideband sideband; - auto block = store_a.block_get (transaction_a, block_a.hash (), &sideband); + auto block = store_a.block_get (transaction_a, block_a.hash ()); ASSERT_NE (block, nullptr); - nano::block_sideband_v14 sideband_v14 (sideband.type, sideband.account, sideband.successor, sideband.balance, sideband.timestamp, sideband.height); + nano::block_sideband_v14 sideband_v14 (block->type (), block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height); std::vector data; { nano::vectorstream stream (data); @@ -2310,23 +2283,22 @@ void write_sideband_v14 (nano::mdb_store & store_a, nano::transaction & transact } MDB_val val{ data.size (), data.data () }; - ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), sideband.details.epoch == nano::epoch::epoch_0 ? store_a.state_blocks_v0 : store_a.state_blocks_v1, nano::mdb_val (block_a.hash ()), &val, 0)); + ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), block->sideband ().details.epoch == nano::epoch::epoch_0 ? store_a.state_blocks_v0 : store_a.state_blocks_v1, nano::mdb_val (block_a.hash ()), &val, 0)); } void write_sideband_v15 (nano::mdb_store & store_a, nano::transaction & transaction_a, nano::block const & block_a) { - nano::block_sideband sideband; - auto block = store_a.block_get (transaction_a, block_a.hash (), &sideband); + auto block = store_a.block_get (transaction_a, block_a.hash ()); ASSERT_NE (block, nullptr); - ASSERT_LE (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 - nano::block_sideband sideband_v15 (sideband.type, sideband.account, sideband.successor, sideband.balance, sideband.timestamp, sideband.height, sideband.details.epoch, false, false, false); + 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); std::vector data; { nano::vectorstream stream (data); block_a.serialize (stream); - sideband_v15.serialize (stream); + sideband_v15.serialize (stream, block_a.type ()); } MDB_val val{ data.size (), data.data () }; diff --git a/nano/core_test/epochs.cpp b/nano/core_test/epochs.cpp index 96a9c3292d..4355885ab4 100644 --- a/nano/core_test/epochs.cpp +++ b/nano/core_test/epochs.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index ed438fa646..51e607cfd6 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -71,6 +71,21 @@ TEST (system, system_genesis) } } +TEST (ledger, process_modifies_sideband) +{ + nano::logger_mt logger; + auto store = nano::make_store (logger, nano::unique_path ()); + ASSERT_TRUE (!store->init_error ()); + nano::stat stats; + nano::ledger ledger (*store, stats); + nano::genesis genesis; + store->initialize (store->tx_begin_write (), genesis, ledger.cache); + nano::work_pool pool (std::numeric_limits::max ()); + nano::state_block send1 (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())); + ASSERT_EQ (nano::process_result::progress, ledger.process (store->tx_begin_write (), send1).code); + ASSERT_EQ (send1.sideband ().timestamp, store->block_get (store->tx_begin_read (), send1.hash ())->sideband ().timestamp); +} + // Create a send block and publish it. TEST (ledger, process_send) { @@ -92,6 +107,8 @@ TEST (ledger, process_send) ASSERT_EQ (1, info1.block_count); // This was a valid block, it should progress. auto return1 (ledger.process (transaction, send)); + ASSERT_EQ (nano::test_genesis_key.pub, send.sideband ().account); + ASSERT_EQ (2, send.sideband ().height); ASSERT_EQ (nano::genesis_amount - 50, ledger.amount (transaction, hash1)); ASSERT_TRUE (store->frontier_get (transaction, info1.head).is_zero ()); ASSERT_EQ (nano::test_genesis_key.pub, store->frontier_get (transaction, hash1)); @@ -113,6 +130,10 @@ TEST (ledger, process_send) nano::block_hash hash2 (open.hash ()); // This was a valid block, it should progress. auto return2 (ledger.process (transaction, open)); + ASSERT_EQ (nano::process_result::progress, return2.code); + ASSERT_EQ (key2.pub, open.sideband ().account); + ASSERT_EQ (nano::genesis_amount - 50, open.sideband ().balance.number ()); + ASSERT_EQ (1, open.sideband ().height); ASSERT_EQ (nano::genesis_amount - 50, ledger.amount (transaction, hash2)); ASSERT_EQ (nano::process_result::progress, return2.code); ASSERT_EQ (key2.pub, return2.account); @@ -190,6 +211,9 @@ TEST (ledger, process_receive) auto return1 (ledger.process (transaction, open)); ASSERT_EQ (nano::process_result::progress, return1.code); ASSERT_EQ (key2.pub, return1.account); + ASSERT_EQ (key2.pub, open.sideband ().account); + ASSERT_EQ (nano::genesis_amount - 50, open.sideband ().balance.number ()); + ASSERT_EQ (1, open.sideband ().height); ASSERT_EQ (nano::genesis_amount - 50, return1.amount.number ()); ASSERT_EQ (nano::genesis_amount - 50, ledger.weight (key3.pub)); nano::send_block send2 (hash1, key2.pub, 25, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (hash1)); @@ -199,6 +223,9 @@ TEST (ledger, process_receive) auto hash4 (receive.hash ()); ASSERT_EQ (key2.pub, store->frontier_get (transaction, hash2)); auto return2 (ledger.process (transaction, receive)); + ASSERT_EQ (key2.pub, receive.sideband ().account); + ASSERT_EQ (nano::genesis_amount - 25, receive.sideband ().balance.number ()); + ASSERT_EQ (2, receive.sideband ().height); ASSERT_EQ (25, ledger.amount (transaction, hash4)); ASSERT_TRUE (store->frontier_get (transaction, hash2).is_zero ()); ASSERT_EQ (key2.pub, store->frontier_get (transaction, hash4)); @@ -1680,22 +1707,21 @@ TEST (ledger, state_send_receive) nano::state_block send1 (nano::genesis_account, genesis.hash (), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send1).code); ASSERT_TRUE (store->block_exists (transaction, send1.hash ())); - nano::block_sideband sideband; - auto send2 (store->block_get (transaction, send1.hash (), &sideband)); + auto send2 (store->block_get (transaction, send1.hash ())); ASSERT_NE (nullptr, send2); ASSERT_EQ (send1, *send2); ASSERT_EQ (nano::genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1.hash ())); ASSERT_EQ (nano::genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::genesis_account)); ASSERT_TRUE (store->pending_exists (transaction, nano::pending_key (nano::genesis_account, send1.hash ()))); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); + ASSERT_EQ (2, send2->sideband ().height); + ASSERT_TRUE (send2->sideband ().details.is_send); + ASSERT_FALSE (send2->sideband ().details.is_receive); + ASSERT_FALSE (send2->sideband ().details.is_epoch); nano::state_block receive1 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, send1.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive1).code); ASSERT_TRUE (store->block_exists (transaction, receive1.hash ())); - nano::block_sideband sideband2; - auto receive2 (store->block_get (transaction, receive1.hash (), &sideband2)); + auto receive2 (store->block_get (transaction, receive1.hash ())); ASSERT_NE (nullptr, receive2); ASSERT_EQ (receive1, *receive2); ASSERT_EQ (nano::genesis_amount, ledger.balance (transaction, receive1.hash ())); @@ -1703,9 +1729,10 @@ TEST (ledger, state_send_receive) ASSERT_EQ (nano::genesis_amount, ledger.weight (nano::genesis_account)); ASSERT_FALSE (store->pending_exists (transaction, nano::pending_key (nano::genesis_account, send1.hash ()))); ASSERT_EQ (store->account_count (transaction), ledger.cache.account_count); - ASSERT_FALSE (sideband2.details.is_send); - ASSERT_TRUE (sideband2.details.is_receive); - ASSERT_FALSE (sideband2.details.is_epoch); + ASSERT_EQ (3, receive2->sideband ().height); + ASSERT_FALSE (receive2->sideband ().details.is_send); + ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->sideband ().details.is_epoch); } TEST (ledger, state_receive) @@ -1731,16 +1758,16 @@ TEST (ledger, state_receive) nano::state_block receive1 (nano::genesis_account, send1.hash (), nano::genesis_account, nano::genesis_amount, send1.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive1).code); ASSERT_TRUE (store->block_exists (transaction, receive1.hash ())); - nano::block_sideband sideband; - auto receive2 (store->block_get (transaction, receive1.hash (), &sideband)); + auto receive2 (store->block_get (transaction, receive1.hash ())); ASSERT_NE (nullptr, receive2); ASSERT_EQ (receive1, *receive2); ASSERT_EQ (nano::genesis_amount, ledger.balance (transaction, receive1.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1.hash ())); ASSERT_EQ (nano::genesis_amount, ledger.weight (nano::genesis_account)); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); + ASSERT_EQ (3, receive2->sideband ().height); + ASSERT_FALSE (receive2->sideband ().details.is_send); + ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->sideband ().details.is_epoch); } TEST (ledger, state_rep_change) @@ -1758,17 +1785,17 @@ TEST (ledger, state_rep_change) nano::state_block change1 (nano::genesis_account, genesis.hash (), rep.pub, nano::genesis_amount, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change1).code); ASSERT_TRUE (store->block_exists (transaction, change1.hash ())); - nano::block_sideband sideband; - auto change2 (store->block_get (transaction, change1.hash (), &sideband)); + auto change2 (store->block_get (transaction, change1.hash ())); ASSERT_NE (nullptr, change2); ASSERT_EQ (change1, *change2); ASSERT_EQ (nano::genesis_amount, ledger.balance (transaction, change1.hash ())); ASSERT_EQ (0, ledger.amount (transaction, change1.hash ())); ASSERT_EQ (0, ledger.weight (nano::genesis_account)); ASSERT_EQ (nano::genesis_amount, ledger.weight (rep.pub)); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); + ASSERT_EQ (2, change2->sideband ().height); + ASSERT_FALSE (change2->sideband ().details.is_send); + ASSERT_FALSE (change2->sideband ().details.is_receive); + ASSERT_FALSE (change2->sideband ().details.is_epoch); } TEST (ledger, state_open) @@ -1797,17 +1824,17 @@ TEST (ledger, state_open) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, open1).code); ASSERT_FALSE (store->pending_exists (transaction, nano::pending_key (destination.pub, send1.hash ()))); ASSERT_TRUE (store->block_exists (transaction, open1.hash ())); - nano::block_sideband sideband; - auto open2 (store->block_get (transaction, open1.hash (), &sideband)); + auto open2 (store->block_get (transaction, open1.hash ())); ASSERT_NE (nullptr, open2); ASSERT_EQ (open1, *open2); ASSERT_EQ (nano::Gxrb_ratio, ledger.balance (transaction, open1.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, open1.hash ())); ASSERT_EQ (nano::genesis_amount, ledger.weight (nano::genesis_account)); ASSERT_EQ (ledger.cache.account_count, store->account_count (transaction)); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); + ASSERT_EQ (1, open2->sideband ().height); + ASSERT_FALSE (open2->sideband ().details.is_send); + ASSERT_TRUE (open2->sideband ().details.is_receive); + ASSERT_FALSE (open2->sideband ().details.is_epoch); } // Make sure old block types can't be inserted after a state block. @@ -2050,17 +2077,17 @@ TEST (ledger, state_send_change) nano::state_block send1 (nano::genesis_account, genesis.hash (), rep.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send1).code); ASSERT_TRUE (store->block_exists (transaction, send1.hash ())); - nano::block_sideband sideband; - auto send2 (store->block_get (transaction, send1.hash (), &sideband)); + auto send2 (store->block_get (transaction, send1.hash ())); ASSERT_NE (nullptr, send2); ASSERT_EQ (send1, *send2); ASSERT_EQ (nano::genesis_amount - nano::Gxrb_ratio, ledger.balance (transaction, send1.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, send1.hash ())); ASSERT_EQ (0, ledger.weight (nano::genesis_account)); ASSERT_EQ (nano::genesis_amount - nano::Gxrb_ratio, ledger.weight (rep.pub)); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); + ASSERT_EQ (2, send2->sideband ().height); + ASSERT_TRUE (send2->sideband ().details.is_send); + ASSERT_FALSE (send2->sideband ().details.is_receive); + ASSERT_FALSE (send2->sideband ().details.is_epoch); } TEST (ledger, state_receive_change) @@ -2087,17 +2114,17 @@ TEST (ledger, state_receive_change) nano::state_block receive1 (nano::genesis_account, send1.hash (), rep.pub, nano::genesis_amount, send1.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive1).code); ASSERT_TRUE (store->block_exists (transaction, receive1.hash ())); - nano::block_sideband sideband2; - auto receive2 (store->block_get (transaction, receive1.hash (), &sideband2)); + auto receive2 (store->block_get (transaction, receive1.hash ())); ASSERT_NE (nullptr, receive2); ASSERT_EQ (receive1, *receive2); ASSERT_EQ (nano::genesis_amount, ledger.balance (transaction, receive1.hash ())); ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive1.hash ())); ASSERT_EQ (0, ledger.weight (nano::genesis_account)); ASSERT_EQ (nano::genesis_amount, ledger.weight (rep.pub)); - ASSERT_FALSE (sideband2.details.is_send); - ASSERT_TRUE (sideband2.details.is_receive); - ASSERT_FALSE (sideband2.details.is_epoch); + ASSERT_EQ (3, receive2->sideband ().height); + ASSERT_FALSE (receive2->sideband ().details.is_send); + ASSERT_TRUE (receive2->sideband ().details.is_receive); + ASSERT_FALSE (receive2->sideband ().details.is_epoch); } TEST (ledger, state_open_old) @@ -2341,13 +2368,9 @@ TEST (ledger, epoch_blocks_v1_general) nano::keypair destination; nano::state_block epoch1 (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, *pool.generate (genesis.hash ())); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code); - { - nano::block_sideband sideband; - (void)ledger.store.block_get (transaction, epoch1.hash (), &sideband); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_TRUE (sideband.details.is_epoch); - } + ASSERT_FALSE (epoch1.sideband ().details.is_send); + ASSERT_FALSE (epoch1.sideband ().details.is_receive); + ASSERT_TRUE (epoch1.sideband ().details.is_epoch); 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); nano::account_info genesis_info; @@ -2359,37 +2382,25 @@ TEST (ledger, epoch_blocks_v1_general) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch1).code); ASSERT_FALSE (ledger.store.account_get (transaction, nano::genesis_account, genesis_info)); ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_1); - { - nano::block_sideband sideband; - (void)ledger.store.block_get (transaction, epoch1.hash (), &sideband); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_TRUE (sideband.details.is_epoch); - } + ASSERT_FALSE (epoch1.sideband ().details.is_send); + ASSERT_FALSE (epoch1.sideband ().details.is_receive); + ASSERT_TRUE (epoch1.sideband ().details.is_epoch); 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); 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); - { - nano::block_sideband sideband; - (void)ledger.store.block_get (transaction, send1.hash (), &sideband); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); - } + ASSERT_TRUE (send1.sideband ().details.is_send); + ASSERT_FALSE (send1.sideband ().details.is_receive); + ASSERT_FALSE (send1.sideband ().details.is_epoch); 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); 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)); ASSERT_EQ (nano::process_result::representative_mismatch, ledger.process (transaction, epoch3).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)); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch4).code); - { - nano::block_sideband sideband; - (void)ledger.store.block_get (transaction, epoch4.hash (), &sideband); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_receive); - ASSERT_TRUE (sideband.details.is_epoch); - } + ASSERT_FALSE (epoch4.sideband ().details.is_send); + ASSERT_FALSE (epoch4.sideband ().details.is_receive); + ASSERT_TRUE (epoch4.sideband ().details.is_epoch); 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); nano::state_block receive2 (destination.pub, epoch4.hash (), destination.pub, nano::Gxrb_ratio, send1.hash (), destination.prv, destination.pub, *pool.generate (epoch4.hash ())); @@ -2399,13 +2410,9 @@ TEST (ledger, epoch_blocks_v1_general) ASSERT_EQ (nano::Gxrb_ratio, ledger.amount (transaction, receive2.hash ())); ASSERT_EQ (nano::genesis_amount - nano::Gxrb_ratio, ledger.weight (nano::genesis_account)); ASSERT_EQ (nano::Gxrb_ratio, ledger.weight (destination.pub)); - { - nano::block_sideband sideband; - (void)ledger.store.block_get (transaction, receive2.hash (), &sideband); - ASSERT_FALSE (sideband.details.is_send); - ASSERT_TRUE (sideband.details.is_receive); - ASSERT_FALSE (sideband.details.is_epoch); - } + ASSERT_FALSE (receive2.sideband ().details.is_send); + ASSERT_TRUE (receive2.sideband ().details.is_receive); + ASSERT_FALSE (receive2.sideband ().details.is_epoch); } TEST (ledger, epoch_blocks_v2_general) @@ -2804,12 +2811,12 @@ TEST (ledger, unchecked_epoch_invalid) nano::account_info info; ASSERT_FALSE (node1.store.account_get (transaction, destination.pub, info)); ASSERT_NE (info.epoch (), nano::epoch::epoch_1); - nano::block_sideband sideband; - ASSERT_NE (nullptr, node1.store.block_get (transaction, epoch2->hash (), &sideband)); - ASSERT_EQ (nano::epoch::epoch_0, sideband.details.epoch); - ASSERT_TRUE (sideband.details.is_send); - ASSERT_FALSE (sideband.details.is_epoch); - ASSERT_FALSE (sideband.details.is_receive); + auto epoch2_store (node1.store.block_get (transaction, epoch2->hash ())); + ASSERT_NE (nullptr, epoch2_store); + ASSERT_EQ (nano::epoch::epoch_0, epoch2_store->sideband ().details.epoch); + ASSERT_TRUE (epoch2_store->sideband ().details.is_send); + ASSERT_FALSE (epoch2_store->sideband ().details.is_epoch); + ASSERT_FALSE (epoch2_store->sideband ().details.is_receive); } } diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index b13f0d812d..e7ddc6d6c9 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1506,8 +1506,10 @@ TEST (node, fork_open_flip) nano::keypair rep1; nano::keypair rep2; auto send1 (std::make_shared (genesis.hash (), key1.pub, nano::genesis_amount - 1, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ()))); + // A copy is necessary to avoid data races during ledger processing, which sets the sideband + auto send1_copy (std::make_shared (*send1)); node1.process_active (send1); - node2.process_active (send1); + node2.process_active (send1_copy); // We should be keeping this block auto open1 (std::make_shared (send1->hash (), rep1.pub, key1.pub, key1.prv, key1.pub, *system.work.generate (key1.pub))); // This block should be evicted @@ -1741,9 +1743,6 @@ TEST (node, broadcast_elected) nano::keypair rep_big; nano::keypair rep_small; nano::keypair rep_other; - //std::cerr << "Big: " << rep_big.pub.to_account () << std::endl; - //std::cerr << "Small: " << rep_small.pub.to_account () << std::endl; - //std::cerr << "Other: " << rep_other.pub.to_account () << std::endl; { auto transaction0 (node0->store.tx_begin_write ()); auto transaction1 (node1->store.tx_begin_write ()); @@ -1784,14 +1783,14 @@ TEST (node, broadcast_elected) system.wallet (2)->insert_adhoc (rep_other.prv); auto fork0 (std::make_shared (node2->latest (nano::test_genesis_key.pub), rep_small.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); node0->work_generate_blocking (*fork0); + // A copy is necessary to avoid data races during ledger processing, which sets the sideband + auto fork0_copy (std::make_shared (*fork0)); node0->process_active (fork0); - node1->process_active (fork0); + node1->process_active (fork0_copy); auto fork1 (std::make_shared (node2->latest (nano::test_genesis_key.pub), rep_big.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); node0->work_generate_blocking (*fork1); system.wallet (2)->insert_adhoc (rep_small.prv); node2->process_active (fork1); - //std::cerr << "fork0: " << fork_hash.to_string () << std::endl; - //std::cerr << "fork1: " << fork1.hash ().to_string () << std::endl; system.deadline_set (10s); while (!node0->ledger.block_exists (fork0->hash ()) || !node1->ledger.block_exists (fork0->hash ())) { @@ -2488,15 +2487,17 @@ TEST (node, block_confirm) nano::keypair key; system.wallet (1)->insert_adhoc (nano::test_genesis_key.prv); auto send1 (std::make_shared (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, *node1.work_generate_blocking (genesis.hash ()))); + // A copy is necessary to avoid data races during ledger processing, which sets the sideband + auto send1_copy (std::make_shared (*send1)); node1.block_processor.add (send1, nano::seconds_since_epoch ()); - node2.block_processor.add (send1, nano::seconds_since_epoch ()); + node2.block_processor.add (send1_copy, nano::seconds_since_epoch ()); system.deadline_set (std::chrono::seconds (5)); - while (!node1.ledger.block_exists (send1->hash ()) || !node2.ledger.block_exists (send1->hash ())) + while (!node1.ledger.block_exists (send1->hash ()) || !node2.ledger.block_exists (send1_copy->hash ())) { ASSERT_NO_ERROR (system.poll ()); } ASSERT_TRUE (node1.ledger.block_exists (send1->hash ())); - ASSERT_TRUE (node2.ledger.block_exists (send1->hash ())); + ASSERT_TRUE (node2.ledger.block_exists (send1_copy->hash ())); auto send2 (std::make_shared (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Gxrb_ratio * 2, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *node1.work_generate_blocking (send1->hash ()))); { auto transaction (node1.store.tx_begin_write ()); diff --git a/nano/core_test/versioning.cpp b/nano/core_test/versioning.cpp index 7e5c8696d5..f47bec0b89 100644 --- a/nano/core_test/versioning.cpp +++ b/nano/core_test/versioning.cpp @@ -11,14 +11,14 @@ 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 ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store.block_put (transaction, open.hash (), open, sideband); + 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); @@ -47,14 +47,14 @@ 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 ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store.block_put (transaction, open.hash (), open, sideband); + 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); @@ -83,14 +83,14 @@ 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 ()); - nano::block_sideband sideband (nano::block_type::open, 0, 0, 0, 0, 0, nano::epoch::epoch_0, false, false, false); - store.block_put (transaction, open.hash (), open, sideband); + 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); diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index 69e9afd269..c0996b359c 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -25,6 +25,8 @@ add_library (nano_lib configbase.hpp diagnosticsconfig.hpp diagnosticsconfig.cpp + epoch.hpp + epoch.cpp errors.hpp errors.cpp ipc.hpp diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index 0907e376cc..e8ad752488 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -9,6 +9,8 @@ #include #include +#include + /** Compare blocks, first by type, then content. This is an optimization over dynamic_cast, which is very slow on some platforms. */ namespace { @@ -136,6 +138,17 @@ nano::block_hash nano::block::full_hash () const return result; } +nano::block_sideband const & nano::block::sideband () const +{ + debug_assert (sideband_m.is_initialized ()); + return *sideband_m; +} + +void nano::block::sideband_set (nano::block_sideband const & sideband_a) +{ + sideband_m = sideband_a; +} + nano::account const & nano::block::representative () const { static nano::account rep{ 0 }; @@ -176,6 +189,11 @@ void nano::send_block::visit (nano::block_visitor & visitor_a) const visitor_a.send_block (*this); } +void nano::send_block::visit (nano::mutable_block_visitor & visitor_a) +{ + visitor_a.send_block (*this); +} + void nano::send_block::hash (blake2b_state & hash_a) const { hashables.hash (hash_a); @@ -660,6 +678,11 @@ void nano::open_block::visit (nano::block_visitor & visitor_a) const visitor_a.open_block (*this); } +void nano::open_block::visit (nano::mutable_block_visitor & visitor_a) +{ + visitor_a.open_block (*this); +} + nano::block_type nano::open_block::type () const { return nano::block_type::open; @@ -896,6 +919,11 @@ void nano::change_block::visit (nano::block_visitor & visitor_a) const visitor_a.change_block (*this); } +void nano::change_block::visit (nano::mutable_block_visitor & visitor_a) +{ + visitor_a.change_block (*this); +} + nano::block_type nano::change_block::type () const { return nano::block_type::change; @@ -1203,6 +1231,11 @@ void nano::state_block::visit (nano::block_visitor & visitor_a) const visitor_a.state_block (*this); } +void nano::state_block::visit (nano::mutable_block_visitor & visitor_a) +{ + visitor_a.state_block (*this); +} + nano::block_type nano::state_block::type () const { return nano::block_type::state; @@ -1364,6 +1397,11 @@ void nano::receive_block::visit (nano::block_visitor & visitor_a) const visitor_a.receive_block (*this); } +void nano::receive_block::visit (nano::mutable_block_visitor & visitor_a) +{ + visitor_a.receive_block (*this); +} + bool nano::receive_block::operator== (nano::receive_block const & other_a) const { auto result (hashables.previous == other_a.hashables.previous && hashables.source == other_a.hashables.source && work == other_a.work && signature == other_a.signature); @@ -1608,6 +1646,157 @@ void nano::receive_hashables::hash (blake2b_state & hash_a) const blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); } +nano::block_details::block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a) : +epoch (epoch_a), is_send (is_send_a), is_receive (is_receive_a), is_epoch (is_epoch_a) +{ +} + +constexpr size_t nano::block_details::size () +{ + return 1; +} + +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; +} + +uint8_t nano::block_details::packed () const +{ + std::bitset<8> result (static_cast (epoch)); + result.set (7, is_send); + result.set (6, is_receive); + result.set (5, is_epoch); + return static_cast (result.to_ulong ()); +} + +void nano::block_details::unpack (uint8_t details_a) +{ + constexpr std::bitset<8> epoch_mask{ 0b00011111 }; + auto as_bitset = static_cast> (details_a); + is_send = as_bitset.test (7); + is_receive = as_bitset.test (6); + is_epoch = as_bitset.test (5); + epoch = static_cast ((as_bitset & epoch_mask).to_ulong ()); +} + +void nano::block_details::serialize (nano::stream & stream_a) const +{ + nano::write (stream_a, packed ()); +} + +bool nano::block_details::deserialize (nano::stream & stream_a) +{ + bool result (false); + try + { + uint8_t packed{ 0 }; + nano::read (stream_a, packed); + unpack (packed); + } + catch (std::runtime_error &) + { + result = true; + } + + return result; +} + +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) : +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::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 is larger than the epoch enum"); + result += nano::block_details::size (); + } + return result; +} + +void nano::block_sideband::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::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; +} + std::shared_ptr nano::block_uniquer::unique (std::shared_ptr block_a) { auto result (block_a); diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 16053bea40..793af471c6 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include +#include #include #include #include @@ -14,6 +16,7 @@ namespace nano { class block_visitor; +class mutable_block_visitor; enum class block_type : uint8_t { invalid = 0, @@ -24,6 +27,43 @@ enum class block_type : uint8_t change = 5, state = 6 }; +class block_details +{ + static_assert (std::is_same::type, uint8_t> (), "Epoch enum is not the proper type"); + static_assert (static_cast (nano::epoch::max) < (1 << 5), "Epoch max is too large for the sideband"); + +public: + 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); + static constexpr size_t size (); + bool operator== (block_details const & other_a) const; + void serialize (nano::stream &) const; + bool deserialize (nano::stream &); + nano::epoch epoch{ nano::epoch::epoch_0 }; + bool is_send{ false }; + bool is_receive{ false }; + bool is_epoch{ false }; + +private: + uint8_t packed () const; + void unpack (uint8_t); +}; + +class block_sideband final +{ +public: + block_sideband () = default; + 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); + 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; +}; class block { public: @@ -31,6 +71,8 @@ class block nano::block_hash const & hash () const; // Return a digest of hashables and non-hashables in this block. nano::block_hash full_hash () const; + nano::block_sideband const & sideband () const; + void sideband_set (nano::block_sideband const &); std::string to_json () const; virtual void hash (blake2b_state &) const = 0; virtual uint64_t block_work () const = 0; @@ -52,6 +94,7 @@ class block virtual void serialize_json (std::string &, bool = false) const = 0; virtual void serialize_json (boost::property_tree::ptree &) const = 0; virtual void visit (nano::block_visitor &) const = 0; + virtual void visit (nano::mutable_block_visitor &) = 0; virtual bool operator== (nano::block const &) const = 0; virtual nano::block_type type () const = 0; virtual nano::signature const & block_signature () const = 0; @@ -66,6 +109,12 @@ class block protected: mutable nano::block_hash cached_hash{ 0 }; + /** + * Contextual details about a block, some fields may or may not be set depending on block type. + * This field is set via sideband_set in ledger processing or deserializing blocks from the database. + * Otherwise it may be null (for example, an old block or fork). + */ + nano::optional_ptr sideband_m; private: nano::block_hash generate_hash () const; @@ -104,6 +153,7 @@ class send_block : public nano::block void serialize_json (boost::property_tree::ptree &) const override; bool deserialize_json (boost::property_tree::ptree const &); void visit (nano::block_visitor &) const override; + void visit (nano::mutable_block_visitor &) override; nano::block_type type () const override; nano::signature const & block_signature () const override; void signature_set (nano::signature const &) override; @@ -148,6 +198,7 @@ class receive_block : public nano::block void serialize_json (boost::property_tree::ptree &) const override; bool deserialize_json (boost::property_tree::ptree const &); void visit (nano::block_visitor &) const override; + void visit (nano::mutable_block_visitor &) override; nano::block_type type () const override; nano::signature const & block_signature () const override; void signature_set (nano::signature const &) override; @@ -196,6 +247,7 @@ class open_block : public nano::block void serialize_json (boost::property_tree::ptree &) const override; bool deserialize_json (boost::property_tree::ptree const &); void visit (nano::block_visitor &) const override; + void visit (nano::mutable_block_visitor &) override; nano::block_type type () const override; nano::signature const & block_signature () const override; void signature_set (nano::signature const &) override; @@ -240,6 +292,7 @@ class change_block : public nano::block void serialize_json (boost::property_tree::ptree &) const override; bool deserialize_json (boost::property_tree::ptree const &); void visit (nano::block_visitor &) const override; + void visit (nano::mutable_block_visitor &) override; nano::block_type type () const override; nano::signature const & block_signature () const override; void signature_set (nano::signature const &) override; @@ -300,6 +353,7 @@ class state_block : public nano::block void serialize_json (boost::property_tree::ptree &) const override; bool deserialize_json (boost::property_tree::ptree const &); void visit (nano::block_visitor &) const override; + void visit (nano::mutable_block_visitor &) override; nano::block_type type () const override; nano::signature const & block_signature () const override; void signature_set (nano::signature const &) override; @@ -321,6 +375,16 @@ class block_visitor virtual void state_block (nano::state_block const &) = 0; virtual ~block_visitor () = default; }; +class mutable_block_visitor +{ +public: + virtual void send_block (nano::send_block &) = 0; + virtual void receive_block (nano::receive_block &) = 0; + virtual void open_block (nano::open_block &) = 0; + virtual void change_block (nano::change_block &) = 0; + virtual void state_block (nano::state_block &) = 0; + virtual ~mutable_block_visitor () = default; +}; /** * This class serves to find and return unique variants of a block in order to minimize memory usage */ diff --git a/nano/secure/epoch.cpp b/nano/lib/epoch.cpp similarity index 98% rename from nano/secure/epoch.cpp rename to nano/lib/epoch.cpp index 352dd1f42c..226d1bb41c 100644 --- a/nano/secure/epoch.cpp +++ b/nano/lib/epoch.cpp @@ -1,5 +1,5 @@ +#include #include -#include nano::link const & nano::epochs::link (nano::epoch epoch_a) const { diff --git a/nano/secure/epoch.hpp b/nano/lib/epoch.hpp similarity index 100% rename from nano/secure/epoch.hpp rename to nano/lib/epoch.hpp diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index eeb5af6d03..bb9178f316 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -1000,14 +1000,14 @@ int main (int argc, char * const * argv) auto hash (info.open_block); nano::block_hash calculated_hash (0); - nano::block_sideband sideband; - auto block (node.node->store.block_get (transaction, hash, &sideband)); // Block data + auto block (node.node->store.block_get (transaction, hash)); // Block data uint64_t height (0); uint64_t previous_timestamp (0); nano::account calculated_representative (0); while (!hash.is_zero () && block != nullptr) { ++block_count; + auto const & sideband (block->sideband ()); // Check for state & open blocks if account field is correct if (block->type () == nano::block_type::open || block->type () == nano::block_type::state) { @@ -1130,7 +1130,7 @@ int main (int argc, char * const * argv) // Retrieving block data if (!hash.is_zero ()) { - block = node.node->store.block_get (transaction, hash, &sideband); + block = node.node->store.block_get (transaction, hash); } } // Check if required block exists diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 7e9923d589..a1a44543ec 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -29,8 +29,8 @@ thread ([this]() { }) { // Register a callback which will get called after a block is cemented - confirmation_height_processor.add_cemented_observer ([this](nano::block_w_sideband const & callback_data_a) { - this->block_cemented_callback (callback_data_a.block, callback_data_a.sideband); + confirmation_height_processor.add_cemented_observer ([this](std::shared_ptr callback_block_a) { + this->block_cemented_callback (callback_block_a); }); // Register a callback which will get called after a batch of blocks is written and observer calls finished @@ -124,7 +124,7 @@ void nano::active_transactions::search_frontiers (nano::transaction const & tran } } -void nano::active_transactions::block_cemented_callback (std::shared_ptr const & block_a, nano::block_sideband const & sideband_a) +void nano::active_transactions::block_cemented_callback (std::shared_ptr const & block_a) { auto transaction = node.store.tx_begin_read (); @@ -147,7 +147,7 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptrhash (), sideband_a, account, amount, is_state_send, pending_account); + node.process_confirmed_data (transaction, block_a, block_a->hash (), account, amount, is_state_send, pending_account); node.observers.blocks.notify (nano::election_status{ block_a, 0, std::chrono::duration_cast (std::chrono::system_clock::now ().time_since_epoch ()), std::chrono::duration_values::zero (), 0, 1, 0, nano::election_status_type::inactive_confirmation_height }, account, amount, is_state_send); } else @@ -172,7 +172,7 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptrstatus.type = *election_status_type; election->status.confirmation_request_count = election->confirmation_request_count; node.observers.blocks.notify (election->status, account, amount, is_state_send); diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index d1c68f45db..ce7d737085 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -109,7 +109,7 @@ class active_transactions final void stop (); bool publish (std::shared_ptr block_a); boost::optional confirm_block (nano::transaction const &, std::shared_ptr); - void block_cemented_callback (std::shared_ptr const & block_a, nano::block_sideband const & sideband_a); + void block_cemented_callback (std::shared_ptr const & block_a); void block_already_cemented_callback (nano::block_hash const &); // clang-format off boost::multi_index_container -nano::confirmation_height_bounded::confirmation_height_bounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger_mt & logger_a, std::atomic & stopped_a, nano::block_hash const & original_hash_a, std::function const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : +nano::confirmation_height_bounded::confirmation_height_bounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger_mt & logger_a, std::atomic & stopped_a, nano::block_hash const & original_hash_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : ledger (ledger_a), write_database_queue (write_database_queue_a), batch_separate_pending_min_time (batch_separate_pending_min_time_a), @@ -67,13 +67,12 @@ void nano::confirmation_height_bounded::process () current = hash_to_process.top; auto top_level_hash = current; - nano::block_sideband sideband; - auto block = ledger.store.block_get (transaction, current, &sideband); + auto block = ledger.store.block_get (transaction, current); debug_assert (block != nullptr); nano::account account (block->account ()); if (account.is_zero ()) { - account = sideband.account; + account = block->sideband ().account; } // Checks if we have encountered this account before but not commited changes yet, if so then update the cached confirmation height @@ -90,13 +89,13 @@ void nano::confirmation_height_bounded::process () (void)error; debug_assert (!error); // This block was added to the confirmation height processor but is already confirmed - if (first_iter && confirmation_height_info.height >= sideband.height && current == original_hash) + if (first_iter && confirmation_height_info.height >= block->sideband ().height && current == original_hash) { notify_block_already_cemented_observers_callback (original_hash); } } - auto block_height = sideband.height; + auto block_height = block->sideband ().height; bool already_cemented = confirmation_height_info.height >= block_height; // If we are not already at the bottom of the account chain (1 above cemented frontier) then find it @@ -199,14 +198,14 @@ void nano::confirmation_height_bounded::process () nano::block_hash nano::confirmation_height_bounded::get_least_unconfirmed_hash_from_top_level (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::account const & account_a, nano::confirmation_height_info const & confirmation_height_info_a, uint64_t & block_height_a) { nano::block_hash least_unconfirmed_hash = hash_a; - nano::block_sideband sideband; if (confirmation_height_info_a.height != 0) { if (block_height_a > confirmation_height_info_a.height) { - release_assert (ledger.store.block_get (transaction_a, confirmation_height_info_a.frontier, &sideband) != nullptr); - least_unconfirmed_hash = sideband.successor; - block_height_a = sideband.height + 1; + auto block (ledger.store.block_get (transaction_a, confirmation_height_info_a.frontier)); + release_assert (block != nullptr); + least_unconfirmed_hash = block->sideband ().successor; + block_height_a = block->sideband ().height + 1; } } else @@ -225,14 +224,13 @@ bool nano::confirmation_height_bounded::iterate (nano::read_transaction const & bool reached_target = false; bool hit_receive = false; auto hash = bottom_hash_a; - nano::block_sideband sideband; uint64_t num_blocks = 0; while (!hash.is_zero () && !reached_target && !stopped) { // Keep iterating upwards until we either reach the desired block or the second receive. // Once a receive is cemented, we can cement all blocks above it until the next receive, so store those details for later. ++num_blocks; - auto block = ledger.store.block_get (transaction_a, hash, &sideband); + auto block = ledger.store.block_get (transaction_a, hash); auto source (block->source ()); if (source.is_zero ()) { @@ -243,6 +241,7 @@ bool nano::confirmation_height_bounded::iterate (nano::read_transaction const & { hit_receive = true; reached_target = true; + auto const & sideband (block->sideband ()); auto next = !sideband.successor.is_zero () && sideband.successor != top_level_hash_a ? boost::optional (sideband.successor) : boost::none; receive_source_pairs_a.push_back ({ receive_chain_details{ account_a, sideband.height, hash, top_level_hash_a, next, bottom_height_a, bottom_hash_a }, source }); // Store a checkpoint every max_items so that we can always traverse a long number of accounts to genesis @@ -261,7 +260,7 @@ bool nano::confirmation_height_bounded::iterate (nano::read_transaction const & } else { - hash = sideband.successor; + hash = block->sideband ().successor; } } @@ -337,7 +336,7 @@ bool nano::confirmation_height_bounded::cement_blocks () { // Will contain all blocks that have been cemented (bounded by batch_write_size) // and will get run through the cemented observer callback - std::vector cemented_blocks; + std::vector> cemented_blocks; { // This only writes to the confirmation_height table and is the only place to do so in a single process auto transaction (ledger.store.tx_begin_write ({}, { nano::tables::confirmation_height })); @@ -354,9 +353,9 @@ bool nano::confirmation_height_bounded::cement_blocks () // Extra debug checks nano::confirmation_height_info confirmation_height_info; debug_assert (!ledger.store.confirmation_height_get (transaction, account, confirmation_height_info)); - nano::block_sideband sideband; - debug_assert (ledger.store.block_get (transaction, confirmed_frontier, &sideband)); - debug_assert (sideband.height == confirmation_height_info.height + num_blocks_cemented); + auto block (ledger.store.block_get (transaction, confirmed_frontier)); + debug_assert (block != nullptr); + debug_assert (block->sideband ().height == confirmation_height_info.height + num_blocks_cemented); #endif ledger.store.confirmation_height_put (transaction, account, nano::confirmation_height_info{ confirmation_height, confirmed_frontier }); ledger.cache.cemented_count += num_blocks_cemented; @@ -370,7 +369,6 @@ bool nano::confirmation_height_bounded::cement_blocks () // Some blocks need to be cemented at least if (pending.top_height > confirmation_height_info.height) { - nano::block_sideband sideband; // The highest hash which will be cemented nano::block_hash new_cemented_frontier; uint64_t num_blocks_confirmed = 0; @@ -385,8 +383,8 @@ bool nano::confirmation_height_bounded::cement_blocks () } else { - auto block = ledger.store.block_get (transaction, confirmation_height_info.frontier, &sideband); - new_cemented_frontier = sideband.successor; + auto block = ledger.store.block_get (transaction, confirmation_height_info.frontier); + new_cemented_frontier = block->sideband ().successor; num_blocks_confirmed = pending.top_height - confirmation_height_info.height; start_height = confirmation_height_info.height + 1; } @@ -394,7 +392,7 @@ bool nano::confirmation_height_bounded::cement_blocks () auto total_blocks_cemented = 0; auto num_blocks_iterated = 0; - auto block = ledger.store.block_get (transaction, new_cemented_frontier, &sideband); + auto block = ledger.store.block_get (transaction, new_cemented_frontier); // Cementing starts from the bottom of the chain and works upwards. This is because chains can have effectively // an infinite number of send/change blocks in a row. We don't want to hold the write transaction open for too long. @@ -409,7 +407,7 @@ bool nano::confirmation_height_bounded::cement_blocks () return true; } - cemented_blocks.emplace_back (block, sideband); + cemented_blocks.emplace_back (block); // We have likely hit a long chain, flush these callbacks and continue if (cemented_blocks.size () == confirmation_height::batch_write_size) @@ -427,8 +425,8 @@ bool nano::confirmation_height_bounded::cement_blocks () auto last_iteration = (num_blocks_confirmed - num_blocks_iterated) == 1; if (!last_iteration) { - new_cemented_frontier = sideband.successor; - block = ledger.store.block_get (transaction, new_cemented_frontier, &sideband); + new_cemented_frontier = block->sideband ().successor; + block = ledger.store.block_get (transaction, new_cemented_frontier); } else { diff --git a/nano/node/confirmation_height_bounded.hpp b/nano/node/confirmation_height_bounded.hpp index 8a444245b5..4d32ad36dd 100644 --- a/nano/node/confirmation_height_bounded.hpp +++ b/nano/node/confirmation_height_bounded.hpp @@ -15,7 +15,7 @@ class write_database_queue; class confirmation_height_bounded final { public: - confirmation_height_bounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger_mt &, std::atomic &, nano::block_hash const &, std::function const &)> const &, std::function const &, std::function const &); + confirmation_height_bounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger_mt &, std::atomic &, nano::block_hash const &, std::function> const &)> const &, std::function const &, std::function const &); bool pending_empty () const; void prepare_new (); void process (); @@ -114,7 +114,7 @@ class confirmation_height_bounded final nano::logger_mt & logger; std::atomic & stopped; nano::block_hash const & original_hash; - std::function const &)> notify_observers_callback; + std::function> const &)> notify_observers_callback; std::function notify_block_already_cemented_observers_callback; std::function awaiting_processing_size_callback; diff --git a/nano/node/confirmation_height_processor.cpp b/nano/node/confirmation_height_processor.cpp index f7ede3759d..cad2739572 100644 --- a/nano/node/confirmation_height_processor.cpp +++ b/nano/node/confirmation_height_processor.cpp @@ -165,7 +165,7 @@ void nano::confirmation_height_processor::set_next_hash () } // Not thread-safe, only call before this processor has begun cementing -void nano::confirmation_height_processor::add_cemented_observer (std::function const & callback_a) +void nano::confirmation_height_processor::add_cemented_observer (std::function)> const & callback_a) { cemented_observers.push_back (callback_a); } @@ -176,7 +176,7 @@ void nano::confirmation_height_processor::add_block_already_cemented_observer (s block_already_cemented_observers.push_back (callback_a); } -void nano::confirmation_height_processor::notify_observers (std::vector const & cemented_blocks) +void nano::confirmation_height_processor::notify_observers (std::vector> const & cemented_blocks) { for (auto const & block_callback_data : cemented_blocks) { diff --git a/nano/node/confirmation_height_processor.hpp b/nano/node/confirmation_height_processor.hpp index facc3e53e5..ea56f97511 100644 --- a/nano/node/confirmation_height_processor.hpp +++ b/nano/node/confirmation_height_processor.hpp @@ -35,7 +35,7 @@ class confirmation_height_processor final bool is_processing_block (nano::block_hash const &); nano::block_hash current (); - void add_cemented_observer (std::function const &); + void add_cemented_observer (std::function)> const &); void add_block_already_cemented_observer (std::function const &); private: @@ -51,7 +51,7 @@ class confirmation_height_processor final nano::condition_variable condition; std::atomic stopped{ false }; - std::vector> cemented_observers; + std::vector)>> cemented_observers; std::vector> block_already_cemented_observers; nano::ledger & ledger; @@ -61,7 +61,7 @@ class confirmation_height_processor final std::thread thread; void set_next_hash (); - void notify_observers (std::vector const &); + void notify_observers (std::vector> const &); void notify_observers (nano::block_hash const &); friend std::unique_ptr collect_container_info (confirmation_height_processor &, const std::string &); diff --git a/nano/node/confirmation_height_unbounded.cpp b/nano/node/confirmation_height_unbounded.cpp index bdca0bb28c..b2399839d3 100644 --- a/nano/node/confirmation_height_unbounded.cpp +++ b/nano/node/confirmation_height_unbounded.cpp @@ -5,7 +5,7 @@ #include -nano::confirmation_height_unbounded::confirmation_height_unbounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger_mt & logger_a, std::atomic & stopped_a, nano::block_hash const & original_hash_a, std::function const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : +nano::confirmation_height_unbounded::confirmation_height_unbounded (nano::ledger & ledger_a, nano::write_database_queue & write_database_queue_a, std::chrono::milliseconds batch_separate_pending_min_time_a, nano::logger_mt & logger_a, std::atomic & stopped_a, nano::block_hash const & original_hash_a, std::function> const &)> const & notify_observers_callback_a, std::function const & notify_block_already_cemented_observers_callback_a, std::function const & awaiting_processing_size_callback_a) : ledger (ledger_a), write_database_queue (write_database_queue_a), batch_separate_pending_min_time (batch_separate_pending_min_time_a), @@ -49,16 +49,14 @@ void nano::confirmation_height_unbounded::process () } } - std::shared_ptr block; - nano::block_sideband sideband; - get_block_and_sideband (current, read_transaction, block, sideband); + auto block (get_block_and_sideband (current, read_transaction)); nano::account account (block->account ()); if (account.is_zero ()) { - account = sideband.account; + account = block->sideband ().account; } - auto block_height = sideband.height; + auto block_height = block->sideband ().height; uint64_t confirmation_height = 0; auto account_it = confirmed_iterated_pairs.find (account); if (account_it != confirmed_iterated_pairs.cend ()) @@ -164,10 +162,7 @@ void nano::confirmation_height_unbounded::collect_unconfirmed_receive_and_source bool hit_receive = false; while ((num_to_confirm > 0) && !hash.is_zero () && !stopped) { - std::shared_ptr block; - nano::block_sideband sideband; - get_block_and_sideband (hash, transaction_a, block, sideband); - + auto block (get_block_and_sideband (hash, transaction_a)); if (block) { auto source (block->source ()); @@ -330,11 +325,10 @@ bool nano::confirmation_height_unbounded::cement_blocks () { #ifndef NDEBUG // Do more thorough checking in Debug mode, indicates programming error. - nano::block_sideband sideband; - auto block = ledger.store.block_get (transaction, pending.hash, &sideband); + auto block = ledger.store.block_get (transaction, pending.hash); static nano::network_constants network_constants; debug_assert (network_constants.is_test_network () || block != nullptr); - debug_assert (network_constants.is_test_network () || sideband.height == pending.height); + debug_assert (network_constants.is_test_network () || block->sideband ().height == pending.height); if (!block) { @@ -355,7 +349,7 @@ bool nano::confirmation_height_unbounded::cement_blocks () // Reverse it so that the callbacks start from the lowest newly cemented block and move upwards std::reverse (pending.block_callback_data.begin (), pending.block_callback_data.end ()); - std::vector callback_data; + std::vector> callback_data; callback_data.reserve (pending.block_callback_data.size ()); std::transform (pending.block_callback_data.begin (), pending.block_callback_data.end (), std::back_inserter (callback_data), [& block_cache = block_cache](auto const & hash_a) { debug_assert (block_cache.find (hash_a) != block_cache.end ()); @@ -373,19 +367,19 @@ bool nano::confirmation_height_unbounded::cement_blocks () return false; } -void nano::confirmation_height_unbounded::get_block_and_sideband (nano::block_hash const & hash_a, nano::transaction const & transaction_a, std::shared_ptr & block_a, nano::block_sideband & sideband_a) +std::shared_ptr nano::confirmation_height_unbounded::get_block_and_sideband (nano::block_hash const & hash_a, nano::transaction const & transaction_a) { auto block_cache_it = block_cache.find (hash_a); if (block_cache_it != block_cache.cend ()) { - block_a = block_cache_it->second.block; - sideband_a = block_cache_it->second.sideband; + return block_cache_it->second; } else { - block_a = ledger.store.block_get (transaction_a, hash_a, &sideband_a); - block_cache.emplace (std::piecewise_construct, std::forward_as_tuple (hash_a), std::forward_as_tuple (block_a, sideband_a)); + auto block (ledger.store.block_get (transaction_a, hash_a)); + block_cache.emplace (hash_a, block); ++block_cache_size; + return block; } } diff --git a/nano/node/confirmation_height_unbounded.hpp b/nano/node/confirmation_height_unbounded.hpp index 6ce3eefcbf..194599a5e1 100644 --- a/nano/node/confirmation_height_unbounded.hpp +++ b/nano/node/confirmation_height_unbounded.hpp @@ -16,7 +16,7 @@ class write_database_queue; class confirmation_height_unbounded final { public: - confirmation_height_unbounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger_mt &, std::atomic &, nano::block_hash const &, std::function const &)> const &, std::function const &, std::function const &); + confirmation_height_unbounded (nano::ledger &, nano::write_database_queue &, std::chrono::milliseconds, nano::logger_mt &, std::atomic &, nano::block_hash const &, std::function> const &)> const &, std::function const &, std::function const &); bool pending_empty () const; void prepare_new (); void process (); @@ -55,9 +55,9 @@ class confirmation_height_unbounded final std::unordered_map confirmed_iterated_pairs; std::atomic confirmed_iterated_pairs_size{ 0 }; - std::unordered_map block_cache; + std::unordered_map> block_cache; std::atomic block_cache_size{ 0 }; - void get_block_and_sideband (nano::block_hash const &, nano::transaction const &, std::shared_ptr &, nano::block_sideband &); + std::shared_ptr get_block_and_sideband (nano::block_hash const &, nano::transaction const &); std::deque pending_writes; std::atomic pending_writes_size{ 0 }; std::vector orig_block_callback_data; @@ -90,7 +90,7 @@ class confirmation_height_unbounded final nano::logger_mt & logger; std::atomic & stopped; nano::block_hash const & original_hash; - std::function const &)> notify_observers_callback; + std::function> const &)> notify_observers_callback; std::function notify_block_already_cemented_observers_callback; std::function awaiting_processing_size_callback; diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 80a5bc5b28..ae13611e7c 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -970,19 +970,18 @@ void nano::json_handler::block_info () auto hash (hash_impl ()); if (!ec) { - nano::block_sideband sideband; auto transaction (node.store.tx_begin_read ()); - auto block (node.store.block_get (transaction, hash, &sideband)); + auto block (node.store.block_get (transaction, hash)); if (block != nullptr) { - nano::account account (block->account ().is_zero () ? sideband.account : block->account ()); + nano::account account (block->account ().is_zero () ? block->sideband ().account : block->account ()); response_l.put ("block_account", account.to_account ()); auto amount (node.ledger.amount (transaction, hash)); response_l.put ("amount", amount.convert_to ()); auto balance (node.ledger.balance (transaction, hash)); response_l.put ("balance", balance.convert_to ()); - response_l.put ("height", std::to_string (sideband.height)); - response_l.put ("local_timestamp", std::to_string (sideband.timestamp)); + response_l.put ("height", std::to_string (block->sideband ().height)); + response_l.put ("local_timestamp", std::to_string (block->sideband ().timestamp)); auto confirmed (node.ledger.block_confirmed (transaction, hash)); response_l.put ("confirmed", confirmed); @@ -1121,19 +1120,18 @@ void nano::json_handler::blocks_info () nano::block_hash hash; if (!hash.decode_hex (hash_text)) { - nano::block_sideband sideband; - auto block (node.store.block_get (transaction, hash, &sideband)); + auto block (node.store.block_get (transaction, hash)); if (block != nullptr) { boost::property_tree::ptree entry; - nano::account account (block->account ().is_zero () ? sideband.account : block->account ()); + nano::account account (block->account ().is_zero () ? block->sideband ().account : block->account ()); entry.put ("block_account", account.to_account ()); auto amount (node.ledger.amount (transaction, hash)); entry.put ("amount", amount.convert_to ()); auto balance (node.ledger.balance (transaction, hash)); entry.put ("balance", balance.convert_to ()); - entry.put ("height", std::to_string (sideband.height)); - entry.put ("local_timestamp", std::to_string (sideband.timestamp)); + entry.put ("height", std::to_string (block->sideband ().height)); + entry.put ("local_timestamp", std::to_string (block->sideband ().timestamp)); auto confirmed (node.ledger.block_confirmed (transaction, hash)); entry.put ("confirmed", confirmed); @@ -2557,8 +2555,7 @@ void nano::json_handler::account_history () boost::property_tree::ptree history; bool output_raw (request.get_optional ("raw") == true); response_l.put ("account", account.to_account ()); - nano::block_sideband sideband; - auto block (node.store.block_get (transaction, hash, &sideband)); + auto block (node.store.block_get (transaction, hash)); while (block != nullptr && count > 0) { if (offset > 0) @@ -2572,8 +2569,8 @@ void nano::json_handler::account_history () block->visit (visitor); if (!entry.empty ()) { - entry.put ("local_timestamp", std::to_string (sideband.timestamp)); - entry.put ("height", std::to_string (sideband.height)); + entry.put ("local_timestamp", std::to_string (block->sideband ().timestamp)); + entry.put ("height", std::to_string (block->sideband ().height)); entry.put ("hash", hash.to_string ()); if (output_raw) { @@ -2585,7 +2582,7 @@ void nano::json_handler::account_history () } } hash = reverse ? node.store.block_successor (transaction, hash) : block->previous (); - block = node.store.block_get (transaction, hash, &sideband); + block = node.store.block_get (transaction, hash); } response_l.add_child ("history", history); if (!hash.is_zero ()) @@ -4580,9 +4577,8 @@ void nano::json_handler::wallet_history () auto hash (info.head); while (timestamp >= modified_since && !hash.is_zero ()) { - nano::block_sideband sideband; - auto block (node.store.block_get (block_transaction, hash, &sideband)); - timestamp = sideband.timestamp; + auto block (node.store.block_get (block_transaction, hash)); + timestamp = block->sideband ().timestamp; if (block != nullptr && timestamp >= modified_since) { boost::property_tree::ptree entry; diff --git a/nano/node/lmdb/lmdb.cpp b/nano/node/lmdb/lmdb.cpp index f013e06fb7..3cf7fb2df0 100644 --- a/nano/node/lmdb/lmdb.cpp +++ b/nano/node/lmdb/lmdb.cpp @@ -507,7 +507,7 @@ void nano::mdb_store::upgrade_v12_to_v13 (nano::write_transaction & transaction_ } nano::mdb_val value{ vector.size (), (void *)vector.data () }; - MDB_dbi database = is_state_block_v1 ? state_blocks_v1 : table_to_dbi (block_database (sideband.type)); + 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)); @@ -628,14 +628,14 @@ 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); auto & sideband_v14 = state_block_w_sideband_v14.sideband; - nano::block_sideband sideband (sideband_v14.type, 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 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 std::vector data; { nano::vectorstream stream (data); state_block_w_sideband_v14.state_block->serialize (stream); - sideband.serialize (stream); + sideband.serialize (stream, sideband_v14.type); } nano::mdb_val value{ data.size (), (void *)data.data () }; @@ -732,27 +732,25 @@ void nano::mdb_store::upgrade_v16_to_v17 (nano::write_transaction const & transa if (account_info_i->second.block_count / 2 >= confirmation_height) { // The confirmation height of the account is closer to the bottom of the chain, so start there and work up - nano::block_sideband sideband; - auto block = block_get (transaction_a, account_info.open_block, &sideband); + auto block = block_get (transaction_a, account_info.open_block); debug_assert (block); auto height = 1; while (height != confirmation_height) { - block = block_get (transaction_a, sideband.successor, &sideband); + block = block_get (transaction_a, block->sideband ().successor); debug_assert (block); ++height; } - debug_assert (sideband.height == confirmation_height); + debug_assert (block->sideband ().height == confirmation_height); confirmation_height_infos.emplace_back (account, confirmation_height_info{ confirmation_height, block->hash () }); } else { // The confirmation height of the account is closer to the top of the chain so start there and work down - nano::block_sideband sideband; - auto block = block_get (transaction_a, account_info.head, &sideband); - auto height = sideband.height; + auto block = block_get (transaction_a, account_info.head); + auto height = block->sideband ().height; while (height != confirmation_height) { block = block_get (transaction_a, block->previous ()); @@ -820,13 +818,13 @@ void nano::mdb_store::upgrade_v17_to_v18 (nano::write_transaction const & transa is_receive = true; } - nano::block_sideband new_sideband (sideband.type, sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, is_send, is_receive, is_epoch); + nano::block_sideband new_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, is_send, is_receive, is_epoch); // Write these out std::vector data; { nano::vectorstream stream (data); block->serialize (stream); - new_sideband.serialize (stream); + new_sideband.serialize (stream, block->type ()); } nano::mdb_val value{ data.size (), (void *)data.data () }; auto s = mdb_cursor_put (state_i.cursor, state_i->first, value, MDB_CURRENT); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index c921d78fd8..f64e23d5d6 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -610,7 +610,7 @@ void nano::node::process_active (std::shared_ptr incoming) block_processor.add (incoming, nano::seconds_since_epoch ()); } -nano::process_return nano::node::process (nano::block const & block_a) +nano::process_return nano::node::process (nano::block & block_a) { auto transaction (store.tx_begin_write ({ tables::accounts, tables::cached_counts, tables::change_blocks, tables::frontiers, tables::open_blocks, tables::pending, tables::receive_blocks, tables::representation, tables::send_blocks, tables::state_blocks }, { tables::confirmation_height })); auto result (ledger.process (transaction, block_a)); @@ -1212,18 +1212,18 @@ void nano::node::receive_confirmed (nano::transaction const & transaction_a, std block_a->visit (visitor); } -void nano::node::process_confirmed_data (nano::transaction const & transaction_a, std::shared_ptr block_a, nano::block_hash const & hash_a, nano::block_sideband const & sideband_a, nano::account & account_a, nano::uint128_t & amount_a, bool & is_state_send_a, nano::account & pending_account_a) +void nano::node::process_confirmed_data (nano::transaction const & transaction_a, std::shared_ptr block_a, nano::block_hash const & hash_a, nano::account & account_a, nano::uint128_t & amount_a, bool & is_state_send_a, nano::account & pending_account_a) { // Faster account calculation account_a = block_a->account (); if (account_a.is_zero ()) { - account_a = sideband_a.account; + account_a = block_a->sideband ().account; } // Faster amount calculation auto previous (block_a->previous ()); auto previous_balance (ledger.balance (transaction_a, previous)); - auto block_balance (store.block_balance_calculated (block_a, sideband_a)); + auto block_balance (store.block_balance_calculated (block_a)); if (hash_a != ledger.network_params.ledger.genesis_account) { amount_a = block_balance > previous_balance ? block_balance - previous_balance : previous_balance - block_balance; diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 7431619fef..e443beae96 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -103,10 +103,10 @@ class node final : public std::enable_shared_from_this std::shared_ptr shared (); int store_version (); void receive_confirmed (nano::transaction const &, std::shared_ptr, nano::block_hash const &); - void process_confirmed_data (nano::transaction const &, std::shared_ptr, nano::block_hash const &, nano::block_sideband const &, nano::account &, nano::uint128_t &, bool &, nano::account &); + void process_confirmed_data (nano::transaction const &, std::shared_ptr, nano::block_hash const &, nano::account &, nano::uint128_t &, bool &, nano::account &); void process_confirmed (nano::election_status const &, std::shared_ptr const &, uint8_t = 0); void process_active (std::shared_ptr); - nano::process_return process (nano::block const &); + nano::process_return process (nano::block &); nano::process_return process_local (std::shared_ptr, bool const = false); void keepalive_preconfigured (std::vector const &); nano::block_hash latest (nano::account const &); diff --git a/nano/secure/CMakeLists.txt b/nano/secure/CMakeLists.txt index cfe874160b..2098cceac3 100644 --- a/nano/secure/CMakeLists.txt +++ b/nano/secure/CMakeLists.txt @@ -41,8 +41,6 @@ add_library (secure buffer.hpp common.hpp common.cpp - epoch.hpp - epoch.cpp ledger.hpp ledger.cpp network_filter.hpp diff --git a/nano/secure/blockstore.cpp b/nano/secure/blockstore.cpp index 909dd2313e..1babdb2f54 100644 --- a/nano/secure/blockstore.cpp +++ b/nano/secure/blockstore.cpp @@ -1,162 +1,6 @@ #include #include -#include - -#include - -nano::block_details::block_details (nano::epoch const epoch_a, bool const is_send_a, bool const is_receive_a, bool const is_epoch_a) : -epoch (epoch_a), is_send (is_send_a), is_receive (is_receive_a), is_epoch (is_epoch_a) -{ -} - -constexpr size_t nano::block_details::size () -{ - return 1; -} - -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; -} - -uint8_t nano::block_details::packed () const -{ - std::bitset<8> result (static_cast (epoch)); - result.set (7, is_send); - result.set (6, is_receive); - result.set (5, is_epoch); - return static_cast (result.to_ulong ()); -} - -void nano::block_details::unpack (uint8_t details_a) -{ - constexpr std::bitset<8> epoch_mask{ 0b00011111 }; - auto as_bitset = static_cast> (details_a); - is_send = as_bitset.test (7); - is_receive = as_bitset.test (6); - is_epoch = as_bitset.test (5); - epoch = static_cast ((as_bitset & epoch_mask).to_ulong ()); -} - -void nano::block_details::serialize (nano::stream & stream_a) const -{ - nano::write (stream_a, packed ()); -} - -bool nano::block_details::deserialize (nano::stream & stream_a) -{ - bool result (false); - try - { - uint8_t packed{ 0 }; - nano::read (stream_a, packed); - unpack (packed); - } - catch (std::runtime_error &) - { - result = true; - } - - return result; -} - -nano::block_sideband::block_sideband (nano::block_type type_a, 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) : -type (type_a), -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::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 is larger than the epoch enum"); - result += nano::block_details::size (); - } - return result; -} - -void nano::block_sideband::serialize (nano::stream & stream_a) const -{ - nano::write (stream_a, successor.bytes); - if (type != nano::block_type::state && type != nano::block_type::open) - { - nano::write (stream_a, account.bytes); - } - if (type != nano::block_type::open) - { - nano::write (stream_a, boost::endian::native_to_big (height)); - } - if (type == nano::block_type::receive || type == nano::block_type::change || type == nano::block_type::open) - { - nano::write (stream_a, balance.bytes); - } - nano::write (stream_a, boost::endian::native_to_big (timestamp)); - if (type == nano::block_type::state) - { - details.serialize (stream_a); - } -} - -bool nano::block_sideband::deserialize (nano::stream & stream_a) -{ - bool result (false); - try - { - nano::read (stream_a, successor.bytes); - if (type != nano::block_type::state && type != nano::block_type::open) - { - nano::read (stream_a, account.bytes); - } - if (type != nano::block_type::open) - { - nano::read (stream_a, height); - boost::endian::big_to_native_inplace (height); - } - else - { - height = 1; - } - if (type == nano::block_type::receive || type == nano::block_type::change || type == nano::block_type::open) - { - nano::read (stream_a, balance.bytes); - } - nano::read (stream_a, timestamp); - boost::endian::big_to_native_inplace (timestamp); - if (type == nano::block_type::state) - { - result = details.deserialize (stream_a); - } - } - catch (std::runtime_error &) - { - result = true; - } - - return result; -} - 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), @@ -397,7 +241,7 @@ nano::uint128_t nano::summation_visitor::compute_balance (nano::block_hash const std::shared_ptr 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 (transaction, hash_a); + 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) : diff --git a/nano/secure/blockstore.hpp b/nano/secure/blockstore.hpp index 66ac7e8d52..310347a862 100644 --- a/nano/secure/blockstore.hpp +++ b/nano/secure/blockstore.hpp @@ -16,45 +16,6 @@ namespace nano { -class block_details -{ - static_assert (std::is_same::type, uint8_t> (), "Epoch enum is not the proper type"); - static_assert (static_cast (nano::epoch::max) < (1 << 5), "Epoch max is too large for the sideband"); - -public: - 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); - static constexpr size_t size (); - bool operator== (block_details const & other_a) const; - void serialize (nano::stream &) const; - bool deserialize (nano::stream &); - nano::epoch epoch{ nano::epoch::epoch_0 }; - bool is_send{ false }; - bool is_receive{ false }; - bool is_epoch{ false }; - -private: - uint8_t packed () const; - void unpack (uint8_t); -}; - -class block_sideband final -{ -public: - block_sideband () = default; - block_sideband (nano::block_type, 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 &) const; - bool deserialize (nano::stream &); - static size_t size (nano::block_type); - nano::block_type type{ nano::block_type::invalid }; - 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; -}; - // Move to versioning with a specific version if required for a future upgrade class state_block_w_sideband { @@ -311,33 +272,33 @@ class db_val return result; } -private: - // Common usage for versioning - template ::value || std::is_same::value>> - T as () const + explicit operator state_block_w_sideband () const { nano::bufferstream stream (reinterpret_cast (data ()), size ()); auto error (false); - T block_w_sideband; + nano::state_block_w_sideband block_w_sideband; block_w_sideband.state_block = std::make_shared (error, stream); debug_assert (!error); - block_w_sideband.sideband.type = nano::block_type::state; - error = block_w_sideband.sideband.deserialize (stream); + error = block_w_sideband.sideband.deserialize (stream, nano::block_type::state); debug_assert (!error); return block_w_sideband; } -public: - explicit operator state_block_w_sideband () const - { - return as (); - } - explicit operator state_block_w_sideband_v14 () const { - return as (); + nano::bufferstream stream (reinterpret_cast (data ()), size ()); + auto error (false); + nano::state_block_w_sideband_v14 block_w_sideband; + block_w_sideband.state_block = std::make_shared (error, stream); + debug_assert (!error); + + block_w_sideband.sideband.type = nano::block_type::state; + error = block_w_sideband.sideband.deserialize (stream); + debug_assert (!error); + + return block_w_sideband; } explicit operator nano::no_value () const @@ -441,19 +402,6 @@ class db_val class transaction; class block_store; -class block_w_sideband final -{ -public: - block_w_sideband (std::shared_ptr const & block_a, nano::block_sideband const & sideband_a) : - block (block_a), - sideband (sideband_a) - { - } - - std::shared_ptr block; - nano::block_sideband sideband; -}; - /** * Summation visitor for blocks, supporting amount and balance computations. These * computations are mutually dependant. The natural solution is to use mutual recursion @@ -714,10 +662,11 @@ class block_store public: virtual ~block_store () = default; virtual void initialize (nano::write_transaction const &, nano::genesis const &, nano::ledger_cache &) = 0; - virtual void block_put (nano::write_transaction const &, nano::block_hash const &, nano::block const &, nano::block_sideband const &) = 0; + virtual void block_put (nano::write_transaction const &, nano::block_hash const &, nano::block const &) = 0; virtual nano::block_hash block_successor (nano::transaction const &, nano::block_hash const &) const = 0; virtual void block_successor_clear (nano::write_transaction const &, nano::block_hash const &) = 0; - virtual std::shared_ptr block_get (nano::transaction const &, nano::block_hash const &, nano::block_sideband * = nullptr) const = 0; + virtual std::shared_ptr block_get (nano::transaction const &, nano::block_hash const &) const = 0; + virtual std::shared_ptr block_get_no_sideband (nano::transaction const &, nano::block_hash const &) const = 0; virtual std::shared_ptr block_get_v14 (nano::transaction const &, nano::block_hash const &, nano::block_sideband_v14 * = nullptr, bool * = nullptr) const = 0; virtual std::shared_ptr block_random (nano::transaction const &) = 0; virtual void block_del (nano::write_transaction const &, nano::block_hash const &, nano::block_type) = 0; @@ -753,7 +702,7 @@ class block_store 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_calculated (std::shared_ptr, nano::block_sideband const &) const = 0; + virtual nano::uint128_t block_balance_calculated (std::shared_ptr const &) const = 0; virtual nano::epoch block_version (nano::transaction const &, nano::block_hash const &) = 0; virtual void unchecked_clear (nano::write_transaction const &) = 0; diff --git a/nano/secure/blockstore_partial.hpp b/nano/secure/blockstore_partial.hpp index 6e837aacab..d58543d981 100644 --- a/nano/secure/blockstore_partial.hpp +++ b/nano/secure/blockstore_partial.hpp @@ -31,8 +31,8 @@ class block_store_partial : public block_store { auto hash_l (genesis_a.hash ()); debug_assert (latest_begin (transaction_a) == latest_end ()); - nano::block_sideband sideband (nano::block_type::open, network_params.ledger.genesis_account, 0, network_params.ledger.genesis_amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false); - block_put (transaction_a, hash_l, *genesis_a.open, sideband); + 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)); + block_put (transaction_a, hash_l, *genesis_a.open); ++ledger_cache_a.block_count; confirmation_height_put (transaction_a, network_params.ledger.genesis_account, nano::confirmation_height_info{ 1, genesis_a.hash () }); ++ledger_cache_a.cemented_count; @@ -44,9 +44,8 @@ class block_store_partial : public block_store nano::uint128_t block_balance (nano::transaction const & transaction_a, nano::block_hash const & hash_a) override { - nano::block_sideband sideband; - auto block (block_get (transaction_a, hash_a, &sideband)); - nano::uint128_t result (block_balance_calculated (block, sideband)); + auto block (block_get (transaction_a, hash_a)); + nano::uint128_t result (block_balance_calculated (block)); return result; } @@ -97,15 +96,14 @@ class block_store_partial : public block_store return result; } - void block_put (nano::write_transaction const & transaction_a, nano::block_hash const & hash_a, nano::block const & block_a, nano::block_sideband const & sideband_a) override + void block_put (nano::write_transaction const & transaction_a, nano::block_hash const & hash_a, nano::block const & block_a) override { - debug_assert (block_a.type () == sideband_a.type); - debug_assert (sideband_a.successor.is_zero () || block_exists (transaction_a, sideband_a.successor)); + debug_assert (block_a.sideband ().successor.is_zero () || block_exists (transaction_a, block_a.sideband ().successor)); std::vector vector; { nano::vectorstream stream (vector); block_a.serialize (stream); - sideband_a.serialize (stream); + block_a.sideband ().serialize (stream, block_a.type ()); } block_raw_put (transaction_a, vector, block_a.type (), hash_a); nano::block_predecessor_set predecessor (transaction_a, *this); @@ -116,13 +114,12 @@ class block_store_partial : public block_store // Converts a block hash to a block height uint64_t block_account_height (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const override { - nano::block_sideband sideband; - auto block = block_get (transaction_a, hash_a, &sideband); + auto block = block_get (transaction_a, hash_a); debug_assert (block != nullptr); - return sideband.height; + return block->sideband ().height; } - std::shared_ptr block_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_sideband * sideband_a = nullptr) const override + std::shared_ptr block_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const override { nano::block_type type; auto value (block_raw_get (transaction_a, hash_a, type)); @@ -132,25 +129,37 @@ class block_store_partial : public block_store nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); result = nano::deserialize_block (stream, type); debug_assert (result != nullptr); - if (sideband_a) + nano::block_sideband sideband; + if (full_sideband (transaction_a) || entry_has_sideband (value.size (), type)) { - sideband_a->type = type; - if (full_sideband (transaction_a) || entry_has_sideband (value.size (), type)) - { - auto error (sideband_a->deserialize (stream)); - (void)error; - debug_assert (!error); - } - else - { - // Reconstruct sideband data for block. - sideband_a->account = block_account_computed (transaction_a, hash_a); - sideband_a->balance = block_balance_computed (transaction_a, hash_a); - sideband_a->successor = block_successor (transaction_a, hash_a); - sideband_a->height = 0; - sideband_a->timestamp = 0; - } + auto error (sideband.deserialize (stream, type)); + (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); + } + return result; + } + + std::shared_ptr block_get_no_sideband (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const override + { + nano::block_type type; + auto value (block_raw_get (transaction_a, hash_a, type)); + std::shared_ptr result; + if (value.size () != 0) + { + nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); + result = nano::deserialize_block (stream, type); + debug_assert (result != nullptr); } return result; } @@ -186,18 +195,17 @@ class block_store_partial : public block_store nano::account block_account (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const override { - nano::block_sideband sideband; - auto block (block_get (transaction_a, hash_a, &sideband)); + auto block (block_get (transaction_a, hash_a)); nano::account result (block->account ()); if (result.is_zero ()) { - result = sideband.account; + result = block->sideband ().account; } debug_assert (!result.is_zero ()); return result; } - nano::uint128_t block_balance_calculated (std::shared_ptr block_a, nano::block_sideband const & sideband_a) const override + nano::uint128_t block_balance_calculated (std::shared_ptr const & block_a) const override { nano::uint128_t result; switch (block_a->type ()) @@ -205,7 +213,7 @@ class block_store_partial : public block_store case nano::block_type::open: case nano::block_type::receive: case nano::block_type::change: - result = sideband_a.balance.number (); + result = block_a->sideband ().balance.number (); break; case nano::block_type::send: result = boost::polymorphic_downcast (block_a.get ())->hashables.balance.number (); @@ -407,11 +415,10 @@ class block_store_partial : public block_store nano::epoch block_version (nano::transaction const & transaction_a, nano::block_hash const & hash_a) override { nano::db_val value; - nano::block_sideband sideband; - auto block = block_get (transaction_a, hash_a, &sideband); - if (sideband.type == nano::block_type::state) + auto block = block_get (transaction_a, hash_a); + if (block && block->type () == nano::block_type::state) { - return sideband.details.epoch; + return block->sideband ().details.epoch; } return nano::epoch::epoch_0; @@ -842,7 +849,7 @@ class block_store_partial : public block_store auto hash (hash_a); while (result.is_zero ()) { - auto block (block_get (transaction_a, hash)); + auto block (block_get_no_sideband (transaction_a, hash)); debug_assert (block); result = block->account (); if (result.is_zero ()) diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index 715ab3e19f..ea5a43ee6e 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -4,10 +4,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index 5f49b16095..3b74b2552a 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -172,18 +172,18 @@ class rollback_visitor : public nano::block_visitor bool error{ false }; }; -class ledger_processor : public nano::block_visitor +class ledger_processor : public nano::mutable_block_visitor { public: ledger_processor (nano::ledger &, nano::write_transaction const &, nano::signature_verification = nano::signature_verification::unknown); virtual ~ledger_processor () = default; - 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; - void state_block_impl (nano::state_block const &); - void epoch_block_impl (nano::state_block const &); + void send_block (nano::send_block &) override; + void receive_block (nano::receive_block &) override; + void open_block (nano::open_block &) override; + void change_block (nano::change_block &) override; + void state_block (nano::state_block &) override; + void state_block_impl (nano::state_block &); + void epoch_block_impl (nano::state_block &); nano::ledger & ledger; nano::write_transaction const & transaction; nano::signature_verification verification; @@ -230,7 +230,7 @@ bool ledger_processor::validate_epoch_block (nano::state_block const & block_a) return (block_a.hashables.balance == prev_balance); } -void ledger_processor::state_block (nano::state_block const & block_a) +void ledger_processor::state_block (nano::state_block & block_a) { result.code = nano::process_result::progress; auto is_epoch_block = false; @@ -253,7 +253,7 @@ void ledger_processor::state_block (nano::state_block const & block_a) } } -void ledger_processor::state_block_impl (nano::state_block const & block_a) +void ledger_processor::state_block_impl (nano::state_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -334,9 +334,8 @@ void ledger_processor::state_block_impl (nano::state_block const & block_a) if (result.code == nano::process_result::progress) { ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block); - result.state_is_send = is_send; - nano::block_sideband sideband (nano::block_type::state, block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, is_send, is_receive, false); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, is_send, is_receive, false)); + ledger.store.block_put (transaction, hash, block_a); if (!info.head.is_zero ()) { @@ -371,7 +370,7 @@ void ledger_processor::state_block_impl (nano::state_block const & block_a) } } -void ledger_processor::epoch_block_impl (nano::state_block const & block_a) +void ledger_processor::epoch_block_impl (nano::state_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -423,8 +422,8 @@ void ledger_processor::epoch_block_impl (nano::state_block const & block_a) ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block); result.account = block_a.hashables.account; result.amount = 0; - nano::block_sideband sideband (nano::block_type::state, block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, false, false, true); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (block_a.hashables.account /* unused */, 0, 0 /* unused */, info.block_count + 1, nano::seconds_since_epoch (), epoch, false, false, true)); + 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); ledger.change_latest (transaction, block_a.hashables.account, info, new_info); if (!ledger.store.frontier_get (transaction, info.head).is_zero ()) @@ -439,7 +438,7 @@ void ledger_processor::epoch_block_impl (nano::state_block const & block_a) } } -void ledger_processor::change_block (nano::change_block const & block_a) +void ledger_processor::change_block (nano::change_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -471,8 +470,8 @@ void ledger_processor::change_block (nano::change_block const & block_a) { debug_assert (!validate_message (account, hash, block_a.signature)); result.verified = nano::signature_verification::valid; - nano::block_sideband sideband (nano::block_type::change, account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false, false, false); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (account, 0, info.balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */)); + ledger.store.block_put (transaction, hash, block_a); 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 (info.representative, 0 - balance); @@ -490,7 +489,7 @@ void ledger_processor::change_block (nano::change_block const & block_a) } } -void ledger_processor::send_block (nano::send_block const & block_a) +void ledger_processor::send_block (nano::send_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -527,8 +526,8 @@ void ledger_processor::send_block (nano::send_block const & block_a) { auto amount (info.balance.number () - block_a.hashables.balance.number ()); ledger.cache.rep_weights.representation_add (info.representative, 0 - amount); - nano::block_sideband sideband (nano::block_type::send, account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */)); + 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); ledger.change_latest (transaction, account, info, new_info); ledger.store.pending_put (transaction, nano::pending_key (block_a.hashables.destination, hash), { account, amount, nano::epoch::epoch_0 }); @@ -546,7 +545,7 @@ void ledger_processor::send_block (nano::send_block const & block_a) } } -void ledger_processor::receive_block (nano::receive_block const & block_a) +void ledger_processor::receive_block (nano::receive_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -595,8 +594,8 @@ void ledger_processor::receive_block (nano::receive_block const & block_a) (void)error; debug_assert (!error); ledger.store.pending_del (transaction, key); - nano::block_sideband sideband (nano::block_type::receive, account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */)); + 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); ledger.change_latest (transaction, account, info, new_info); ledger.cache.rep_weights.representation_add (info.representative, pending.amount.number ()); @@ -620,7 +619,7 @@ void ledger_processor::receive_block (nano::receive_block const & block_a) } } -void ledger_processor::open_block (nano::open_block const & block_a) +void ledger_processor::open_block (nano::open_block & block_a) { auto hash (block_a.hash ()); auto existing (ledger.store.block_exists (transaction, block_a.type (), hash)); @@ -659,8 +658,8 @@ void ledger_processor::open_block (nano::open_block const & block_a) (void)error; debug_assert (!error); ledger.store.pending_del (transaction, key); - nano::block_sideband sideband (nano::block_type::open, block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */); - ledger.store.block_put (transaction, hash, block_a, sideband); + block_a.sideband_set (nano::block_sideband (block_a.hashables.account, 0, pending.amount, 1, nano::seconds_since_epoch (), nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */)); + 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); ledger.change_latest (transaction, block_a.hashables.account, info, new_info); ledger.cache.rep_weights.representation_add (block_a.representative (), pending.amount.number ()); @@ -752,7 +751,7 @@ nano::uint128_t nano::ledger::account_pending (nano::transaction const & transac return result; } -nano::process_return nano::ledger::process (nano::write_transaction const & transaction_a, nano::block const & block_a, nano::signature_verification verification) +nano::process_return nano::ledger::process (nano::write_transaction const & transaction_a, nano::block & block_a, nano::signature_verification verification) { debug_assert (!nano::work_validate (block_a)); ledger_processor processor (*this, transaction_a, verification); diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index 60e7106069..00a460c58b 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -38,7 +38,7 @@ class ledger final bool is_send (nano::transaction const &, nano::state_block const &) const; nano::account const & block_destination (nano::transaction const &, nano::block const &); nano::block_hash block_source (nano::transaction const &, nano::block const &); - nano::process_return process (nano::write_transaction const &, nano::block const &, nano::signature_verification = nano::signature_verification::unknown); + nano::process_return process (nano::write_transaction const &, nano::block &, nano::signature_verification = nano::signature_verification::unknown); bool rollback (nano::write_transaction const &, nano::block_hash const &, std::vector> &); bool rollback (nano::write_transaction const &, nano::block_hash const &); void change_latest (nano::write_transaction const &, nano::account const &, nano::account_info const &, nano::account_info const &);