diff --git a/rai/core_test/block_store.cpp b/rai/core_test/block_store.cpp index 93b3a71b..4622d2dc 100644 --- a/rai/core_test/block_store.cpp +++ b/rai/core_test/block_store.cpp @@ -240,7 +240,7 @@ TEST (bootstrap, simple) auto block3 (store.unchecked_get (transaction, block1->previous ())); ASSERT_FALSE (block3.empty ()); ASSERT_EQ (*block1, *block3[0]); - store.unchecked_del (transaction, block1->previous (), block1); + store.unchecked_del (transaction, rai::unchecked_key (block1->previous (), block1->hash ())); auto block4 (store.unchecked_get (transaction, block1->previous ())); ASSERT_TRUE (block4.empty ()); } @@ -391,9 +391,9 @@ TEST (block_store, one_bootstrap) auto begin (store.unchecked_begin (transaction)); auto end (store.unchecked_end ()); ASSERT_NE (end, begin); - rai::uint256_union hash1 (begin->first); + rai::uint256_union hash1 (begin->first.key ()); ASSERT_EQ (block1->hash (), hash1); - auto blocks (store.unchecked_get (transaction, rai::block_hash (begin->first))); + auto blocks (store.unchecked_get (transaction, hash1)); ASSERT_EQ (1, blocks.size ()); auto block2 (blocks[0]); ASSERT_EQ (*block1, *block2); @@ -877,7 +877,7 @@ TEST (block_store, upgrade_v6_v7) } // Databases need to be dropped in order to convert to dupsort compatible -TEST (block_store, change_dupsort) +TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table { auto path (rai::unique_path ()); bool init (false); diff --git a/rai/node/lmdb.cpp b/rai/node/lmdb.cpp index 4e1f576e..64f632e6 100644 --- a/rai/node/lmdb.cpp +++ b/rai/node/lmdb.cpp @@ -688,21 +688,21 @@ rai::store_iterator rai::mdb_store::representa return result; } -rai::store_iterator> rai::mdb_store::unchecked_begin (rai::transaction const & transaction_a) +rai::store_iterator> rai::mdb_store::unchecked_begin (rai::transaction const & transaction_a) { - rai::store_iterator> result (std::make_unique>> (transaction_a, unchecked)); + rai::store_iterator> result (std::make_unique>> (transaction_a, unchecked)); return result; } -rai::store_iterator> rai::mdb_store::unchecked_begin (rai::transaction const & transaction_a, rai::block_hash const & hash_a) +rai::store_iterator> rai::mdb_store::unchecked_begin (rai::transaction const & transaction_a, rai::unchecked_key const & key_a) { - rai::store_iterator> result (std::make_unique>> (transaction_a, unchecked, rai::mdb_val (hash_a))); + rai::store_iterator> result (std::make_unique>> (transaction_a, unchecked, rai::mdb_val (key_a))); return result; } -rai::store_iterator> rai::mdb_store::unchecked_end () +rai::store_iterator> rai::mdb_store::unchecked_end () { - rai::store_iterator> result (nullptr); + rai::store_iterator> result (nullptr); return result; } @@ -752,7 +752,7 @@ meta (0) error_a |= mdb_dbi_open (env.tx (transaction), "pending_v1", MDB_CREATE, &pending_v1) != 0; error_a |= mdb_dbi_open (env.tx (transaction), "blocks_info", MDB_CREATE, &blocks_info) != 0; error_a |= mdb_dbi_open (env.tx (transaction), "representation", MDB_CREATE, &representation) != 0; - error_a |= mdb_dbi_open (env.tx (transaction), "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked) != 0; + error_a |= mdb_dbi_open (env.tx (transaction), "unchecked", MDB_CREATE, &unchecked) != 0; error_a |= mdb_dbi_open (env.tx (transaction), "checksum", MDB_CREATE, &checksum) != 0; error_a |= mdb_dbi_open (env.tx (transaction), "vote", MDB_CREATE, &vote) != 0; error_a |= mdb_dbi_open (env.tx (transaction), "meta", MDB_CREATE, &meta) != 0; @@ -867,6 +867,8 @@ void rai::mdb_store::do_upgrades (rai::transaction const & transaction_a) case 10: upgrade_v10_to_v11 (transaction_a); case 11: + upgrade_v11_to_v12 (transaction_a); + case 12: break; default: assert (false); @@ -1068,6 +1070,13 @@ void rai::mdb_store::upgrade_v10_to_v11 (rai::transaction const & transaction_a) mdb_drop (env.tx (transaction_a), unsynced, 1); } +void rai::mdb_store::upgrade_v11_to_v12 (rai::transaction const & transaction_a) +{ + version_put (transaction_a, 12); + mdb_drop (env.tx (transaction_a), unchecked, 1); + mdb_dbi_open (env.tx (transaction_a), "unchecked", MDB_CREATE, &unchecked); +} + void rai::mdb_store::clear (MDB_dbi db_a) { auto transaction (tx_begin_write ()); @@ -1731,26 +1740,17 @@ void rai::mdb_store::unchecked_clear (rai::transaction const & transaction_a) release_assert (status == 0); } +void rai::mdb_store::unchecked_put (rai::transaction const & transaction_a, rai::unchecked_key const & key_a, std::shared_ptr const & block_a) +{ + mdb_val block (block_a); + auto status (mdb_put (env.tx (transaction_a), unchecked, rai::mdb_val (key_a), block, 0)); + release_assert (status == 0); +} + void rai::mdb_store::unchecked_put (rai::transaction const & transaction_a, rai::block_hash const & hash_a, std::shared_ptr const & block_a) { - // Checking if same unchecked block is already in database - bool exists (false); - auto block_hash (block_a->hash ()); - auto cached (unchecked_get (transaction_a, hash_a)); - for (auto i (cached.begin ()), n (cached.end ()); i != n && !exists; ++i) - { - if ((*i)->hash () == block_hash) - { - exists = true; - } - } - // Inserting block if it wasn't found in database - if (!exists) - { - mdb_val block (block_a); - auto status (mdb_put (env.tx (transaction_a), unchecked, rai::mdb_val (hash_a), block, 0)); - release_assert (status == 0); - } + rai::unchecked_key key (hash_a, block_a->hash ()); + unchecked_put (transaction_a, key, block_a); } std::shared_ptr rai::mdb_store::vote_get (rai::transaction const & transaction_a, rai::account const & account_a) @@ -1770,7 +1770,7 @@ std::shared_ptr rai::mdb_store::vote_get (rai::transaction const & tr std::vector> rai::mdb_store::unchecked_get (rai::transaction const & transaction_a, rai::block_hash const & hash_a) { std::vector> result; - for (auto i (unchecked_begin (transaction_a, hash_a)), n (unchecked_end ()); i != n && rai::block_hash (i->first) == hash_a; ++i) + for (auto i (unchecked_begin (transaction_a, rai::unchecked_key (hash_a, 0))), n (unchecked_end ()); i != n && rai::block_hash (i->first.key ()) == hash_a; ++i) { std::shared_ptr block (i->second); result.push_back (block); @@ -1778,10 +1778,15 @@ std::vector> rai::mdb_store::unchecked_get (rai::tra return result; } -void rai::mdb_store::unchecked_del (rai::transaction const & transaction_a, rai::block_hash const & hash_a, std::shared_ptr block_a) +bool rai::mdb_store::unchecked_exists (rai::transaction const & transaction_a, rai::unchecked_key const & key_a) { - rai::mdb_val block (block_a); - auto status (mdb_del (env.tx (transaction_a), unchecked, rai::mdb_val (hash_a), block)); + auto iterator (unchecked_begin (transaction_a, key_a)); + return iterator != unchecked_end () && rai::unchecked_key (iterator->first) == key_a; +} + +void rai::mdb_store::unchecked_del (rai::transaction const & transaction_a, rai::unchecked_key const & key_a) +{ + auto status (mdb_del (env.tx (transaction_a), unchecked, rai::mdb_val (key_a), nullptr)); release_assert (status == 0 || status == MDB_NOTFOUND); } diff --git a/rai/node/lmdb.hpp b/rai/node/lmdb.hpp index fe9ce365..93b7a25b 100644 --- a/rai/node/lmdb.hpp +++ b/rai/node/lmdb.hpp @@ -212,12 +212,14 @@ public: rai::store_iterator representation_end () override; void unchecked_clear (rai::transaction const &) override; + void unchecked_put (rai::transaction const &, rai::unchecked_key const &, std::shared_ptr const &) override; void unchecked_put (rai::transaction const &, rai::block_hash const &, std::shared_ptr const &) override; std::vector> unchecked_get (rai::transaction const &, rai::block_hash const &) override; - void unchecked_del (rai::transaction const &, rai::block_hash const &, std::shared_ptr) override; - rai::store_iterator> unchecked_begin (rai::transaction const &) override; - rai::store_iterator> unchecked_begin (rai::transaction const &, rai::block_hash const &) override; - rai::store_iterator> unchecked_end () override; + bool unchecked_exists (rai::transaction const &, rai::unchecked_key const &) override; + void unchecked_del (rai::transaction const &, rai::unchecked_key const &) override; + rai::store_iterator> unchecked_begin (rai::transaction const &) override; + rai::store_iterator> unchecked_begin (rai::transaction const &, rai::unchecked_key const &) override; + rai::store_iterator> unchecked_end () override; size_t unchecked_count (rai::transaction const &) override; void checksum_put (rai::transaction const &, uint64_t, uint8_t, rai::checksum const &) override; diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 1ffd2897..97bd15f4 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -1585,7 +1585,7 @@ void rai::block_processor::queue_unchecked (rai::transaction const & transaction auto cached (node.store.unchecked_get (transaction_a, hash_a)); for (auto i (cached.begin ()), n (cached.end ()); i != n; ++i) { - node.store.unchecked_del (transaction_a, hash_a, *i); + node.store.unchecked_del (transaction_a, rai::unchecked_key (hash_a, (*i)->hash ())); add (*i, std::chrono::steady_clock::time_point ()); } std::lock_guard lock (node.gap_cache.mutex); diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 099e4af2..0832248e 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -3036,13 +3036,13 @@ void rai::rpc_handler::unchecked_keys () { boost::property_tree::ptree unchecked; auto transaction (node.store.tx_begin_read ()); - for (auto i (node.store.unchecked_begin (transaction, key)), n (node.store.unchecked_end ()); i != n && unchecked.size () < count; ++i) + for (auto i (node.store.unchecked_begin (transaction, rai::unchecked_key (key, 0))), n (node.store.unchecked_end ()); i != n && unchecked.size () < count; ++i) { boost::property_tree::ptree entry; auto block (i->second); std::string contents; block->serialize_json (contents); - entry.put ("key", rai::block_hash (i->first).to_string ()); + entry.put ("key", rai::block_hash (i->first.key ()).to_string ()); entry.put ("hash", block->hash ().to_string ()); entry.put ("contents", contents); unchecked.push_back (std::make_pair ("", entry)); diff --git a/rai/secure/blockstore.hpp b/rai/secure/blockstore.hpp index 9fb87966..03697086 100644 --- a/rai/secure/blockstore.hpp +++ b/rai/secure/blockstore.hpp @@ -254,12 +254,14 @@ public: virtual rai::store_iterator representation_end () = 0; virtual void unchecked_clear (rai::transaction const &) = 0; + virtual void unchecked_put (rai::transaction const &, rai::unchecked_key const &, std::shared_ptr const &) = 0; virtual void unchecked_put (rai::transaction const &, rai::block_hash const &, std::shared_ptr const &) = 0; virtual std::vector> unchecked_get (rai::transaction const &, rai::block_hash const &) = 0; - virtual void unchecked_del (rai::transaction const &, rai::block_hash const &, std::shared_ptr) = 0; - virtual rai::store_iterator> unchecked_begin (rai::transaction const &) = 0; - virtual rai::store_iterator> unchecked_begin (rai::transaction const &, rai::block_hash const &) = 0; - virtual rai::store_iterator> unchecked_end () = 0; + virtual bool unchecked_exists (rai::transaction const &, rai::unchecked_key const &) = 0; + virtual void unchecked_del (rai::transaction const &, rai::unchecked_key const &) = 0; + virtual rai::store_iterator> unchecked_begin (rai::transaction const &) = 0; + virtual rai::store_iterator> unchecked_begin (rai::transaction const &, rai::unchecked_key const &) = 0; + virtual rai::store_iterator> unchecked_end () = 0; virtual size_t unchecked_count (rai::transaction const &) = 0; virtual void checksum_put (rai::transaction const &, uint64_t, uint8_t, rai::checksum const &) = 0; diff --git a/rai/secure/common.cpp b/rai/secure/common.cpp index e8b1c541..1b97eb24 100644 --- a/rai/secure/common.cpp +++ b/rai/secure/common.cpp @@ -299,6 +299,11 @@ bool rai::pending_key::operator== (rai::pending_key const & other_a) const return account == other_a.account && hash == other_a.hash; } +rai::block_hash rai::pending_key::key () const +{ + return account; +} + rai::block_info::block_info () : account (0), balance (0) diff --git a/rai/secure/common.hpp b/rai/secure/common.hpp index 7d37a85f..185c673e 100644 --- a/rai/secure/common.hpp +++ b/rai/secure/common.hpp @@ -110,7 +110,11 @@ public: bool operator== (rai::pending_key const &) const; rai::account account; rai::block_hash hash; + rai::block_hash key () const; }; +// Internally unchecked_key is equal to pending_key (2x uint256_union) +using unchecked_key = pending_key; + class block_info { public: