diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 3d76e3158f..b719cc80c1 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -384,7 +384,7 @@ bool BeaconRegistry::TryRenewal(Beacon_ptr& current_beacon_ptr, int& height, con // Place a smart shared pointer to the renewed beacon in the active beacons map. Note that the // subscript form of the insert with the same key replaces the current beacon entry with the //renewal. - m_beacons[payload.m_cpid] = std::make_shared(renewal_iter->second); + m_beacons[payload.m_cpid] = renewal_iter->second; return true; } @@ -446,7 +446,7 @@ void BeaconRegistry::Add(const ContractContext& ctx) historical.GetAddress().ToString(), historical.m_hash.GetHex()); } - m_beacons[payload.m_cpid] = std::make_shared(m_beacon_db[ctx.m_tx.GetHash()]); + m_beacons[payload.m_cpid] = m_beacon_db.find(ctx.m_tx.GetHash())->second; return; } @@ -480,7 +480,7 @@ void BeaconRegistry::Add(const ContractContext& ctx) } // Insert a pointer to the entry in the m_pending map. - m_pending[pending.GetId()] = std::make_shared(m_beacon_db[ctx.m_tx.GetHash()]); + m_pending[pending.GetId()] = m_beacon_db.find(ctx.m_tx.GetHash())->second; } void BeaconRegistry::Delete(const ContractContext& ctx) @@ -652,11 +652,11 @@ void BeaconRegistry::Revert(const ContractContext& ctx) if (resurrect_iter != m_beacon_db.end()) { // This is an element to the desired entry in the historical table. - Beacon& resurrected_beacon = resurrect_iter->second; + Beacon_ptr& resurrected_beacon = resurrect_iter->second; // Resurrect the prior beacon. // ------------- cpid -------------- smart shared pointer to element in historical map. - m_beacons[cpid] = std::make_shared(resurrected_beacon); + m_beacons[cpid] = resurrected_beacon; } // Erase the renewal record in the db that was reverted. No reason to keep it. @@ -688,12 +688,12 @@ void BeaconRegistry::Revert(const ContractContext& ctx) if (deleted_beacon_record != m_beacon_db.end()) { - auto record_to_restore = m_beacon_db.find(deleted_beacon_record->second.m_prev_beacon_hash); + auto record_to_restore = m_beacon_db.find(deleted_beacon_record->second->m_prev_beacon_hash); if (record_to_restore != m_beacon_db.end()) { // Get a smart shared pointer to the beacon to restore - Beacon_ptr beacon_to_restore_ptr = std::make_shared(record_to_restore->second); + Beacon_ptr beacon_to_restore_ptr = record_to_restore->second; // Check the beacon's status. If it was ACTIVE or RENEWAL, put it back in the m_beacons map // under the cpid. @@ -866,8 +866,7 @@ void BeaconRegistry::ActivatePending( // This is the subscript form of insert. Important here because an activated beacon should // overwrite any existing entry in the m_beacons map. - m_beacons[activated_beacon.m_cpid] = - std::make_shared(m_beacon_db[activated_beacon.m_hash]); + m_beacons[activated_beacon.m_cpid] = m_beacon_db.find(activated_beacon.m_hash)->second; // Remove the pending beacon entry from the pending map. (Note this entry still exists in the historical // table and the db. @@ -940,8 +939,8 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) } // Resurrect the pending record prior to the activation. This points to the pending record still in the db. - m_pending[static_cast(pending_beacon_entry->second).GetId()] = - std::make_shared(pending_beacon_entry->second); + m_pending[static_cast(*pending_beacon_entry->second).GetId()] = + pending_beacon_entry->second; // Erase the entry from the active beacons map. This also increments the iterator. iter = m_beacons.erase(iter); @@ -964,22 +963,22 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) while (iter != m_beacon_db.end()) { // The cpid in the historical beacon record to be matched. - Cpid cpid = iter->second.m_cpid; + Cpid cpid = iter->second->m_cpid; uint256 match_hash = Hash(superblock_hash.begin(), superblock_hash.end(), - iter->second.m_prev_beacon_hash.begin(), - iter->second.m_prev_beacon_hash.end()); + iter->second->m_prev_beacon_hash.begin(), + iter->second->m_prev_beacon_hash.end()); // If the calculated match_hash matches the key (hash) of the historical beacon record, then // restore the previous record pointed to by the historical beacon record to the pending map. if (match_hash == iter->first) { - uint256 resurrect_pending_hash = iter->second.m_prev_beacon_hash; + uint256 resurrect_pending_hash = iter->second->m_prev_beacon_hash; if (!resurrect_pending_hash.IsNull()) { - Beacon_ptr resurrected_pending = std::make_shared(m_beacon_db.find(resurrect_pending_hash)->second); + Beacon_ptr resurrected_pending = m_beacon_db.find(resurrect_pending_hash)->second; // Check that the status of the beacon to resurrect is PENDING. If it is not log an error but continue // anyway. @@ -1137,6 +1136,7 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& } uint64_t recnum_high_watermark = 0; + uint64_t number_passivated = 0; // Replay the storage map. The iterator is ordered by record number, which ensures that the correct // elements end up in m_beacons and m_pending. Storage entries that are "mark deletions" are also inserted @@ -1162,8 +1162,15 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& // Insert the entry into the historical map. This includes ctx's where the beacon is marked deleted. // --------------- hash ---------- does NOT include the Cpid. - m_historical[iter.second.m_hash] = beacon; - Beacon& historical_beacon = m_historical[iter.second.m_hash]; + m_historical[iter.second.m_hash] = std::make_shared(beacon); + Beacon_ptr& historical_beacon_ptr = m_historical[iter.second.m_hash]; + + BeaconRegistry::HistoricalBeaconMap::iterator prev_historical_iter = m_historical.end(); + + if (!historical_beacon_ptr->m_prev_beacon_hash.IsNull()) + { + prev_historical_iter = m_historical.find(historical_beacon_ptr->m_prev_beacon_hash); + } if (beacon.m_status == BeaconStatusForStorage::PENDING) { @@ -1180,7 +1187,7 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& ); // Insert the pending beacon in the pending map. - m_pending[beacon.GetId()] = std::make_shared(historical_beacon); + m_pending[beacon.GetId()] = historical_beacon_ptr; } if (beacon.m_status == BeaconStatusForStorage::ACTIVE || beacon.m_status == BeaconStatusForStorage::RENEWAL) @@ -1198,7 +1205,7 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& ); // Insert or replace the existing map entry for the cpid with the latest active or renewed for that CPID. - m_beacons[beacon.m_cpid] = std::make_shared(historical_beacon); + m_beacons[beacon.m_cpid] = historical_beacon_ptr; // Delete any entry in the pending map with THE SAME public key. auto pending_to_delete = m_pending.find(beacon.GetId()); @@ -1256,11 +1263,28 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& m_beacons.erase(beacon.m_cpid); m_pending.erase(beacon.m_public_key.GetID()); } + + if (prev_historical_iter != m_historical.end()) + { + // Note that passivation is not expected to be successful for every call. See the comments + // in the passivate() function. + std::pair passivation_result + = passivate(prev_historical_iter); + + number_passivated += passivation_result.second; + } } + LogPrint(LogFlags::BEACON, "INFO: %s: number of historical records passivated: %" PRId64 ".", + __func__, + number_passivated); + // Set the in-memory record number stored variable to the highest recnum encountered during the replay above. m_recnum_stored = recnum_high_watermark; + // Set the needs passivation flag to true, because the one-by-one passivation done above may not catch everything. + m_needs_passivation = true; + return height; } @@ -1271,6 +1295,26 @@ void BeaconRegistry::ResetInMemoryOnly() m_beacon_db.clear_in_memory_only(); } +uint64_t BeaconRegistry::PassivateDB() +{ + return m_beacon_db.passivate_db(); +} + +// This is static and called by the scheduler. +void BeaconRegistry::RunBeaconDBPassivation() +{ + TRY_LOCK(cs_main, locked_main); + + if (!locked_main) + { + return; + } + + BeaconRegistry& beacons = GetBeaconRegistry(); + + beacons.PassivateDB(); +} + // Required to make the linker happy. constexpr uint32_t BeaconRegistry::BeaconDB::CURRENT_VERSION; @@ -1280,6 +1324,7 @@ void BeaconRegistry::BeaconDB::clear_in_memory_only() m_database_init = false; m_height_stored = 0; m_recnum_stored = 0; + m_needs_passivation = false; } bool BeaconRegistry::BeaconDB::clear_leveldb() @@ -1305,11 +1350,41 @@ bool BeaconRegistry::BeaconDB::clear_leveldb() m_height_stored = 0; m_recnum_stored = 0; m_database_init = false; + m_needs_passivation = false; m_needs_IsContract_correction = false; return status; } +uint64_t BeaconRegistry::BeaconDB::passivate_db() +{ + uint64_t number_passivated = 0; + + // Don't bother to go through the historical beacon map unless the needs passivation flag is set. This makes + // this function extremely light for most calls from the periodic schedule. + if (m_needs_passivation) + { + for (auto iter = m_historical.begin(); iter != m_historical.end(); /*no-op*/) + { + // The passivate function increments the iterator. + std::pair result = passivate(iter); + + iter = result.first; + number_passivated += result.second; + + } + } + + LogPrint(BCLog::LogFlags::BEACON, "INFO %s: Passivated %" PRId64 " elements from beacon db.", + __func__, + number_passivated); + + // Set needs passivation flag to false after passivating the db. + m_needs_passivation = false; + + return number_passivated; +} + bool BeaconRegistry::BeaconDB::clear() { clear_in_memory_only(); @@ -1403,17 +1478,21 @@ bool BeaconRegistry::BeaconDB::insert(const uint256 &hash, const int& height, co beacon.m_status.Raw() // status ); - m_historical.insert(std::make_pair(hash, beacon)); + m_historical.insert(std::make_pair(hash, std::make_shared(beacon))); status = Store(hash, static_cast(beacon)); if (height) status &= StoreDBHeight(height); + // Set needs passivation flag to true to allow the scheduled passivation to remove unnecessary records from + // memory. + m_needs_passivation = true; + return status; } } -bool BeaconRegistry::BeaconDB::erase(uint256 hash) +bool BeaconRegistry::BeaconDB::erase(const uint256& hash) { auto iter = m_historical.find(hash); @@ -1425,6 +1504,42 @@ bool BeaconRegistry::BeaconDB::erase(uint256 hash) return Delete(hash); } +// Note that this function uses the shared pointer use_count() to determine whether an element in +// m_historical is referenced by either the m_beacons or m_pending map and if not, erases it, leaving the backing +// state in leveldb untouched. Note that the use of use_count() in multithreaded environments must be carefully +// considered because it is only approximate. In this case it is exact. Access to the entire BeaconRegistry class +// and everything in it is protected by the cs_main lock and is therefore single threaded. This method of passivating +// is MUCH faster than searching through m_beacons and m_pending for each element, because they are not keyed by hash. +// +// Note that this function acts very similarly to the map erase function with an iterator argument, but with a standard +// pair returned. The first part of the pair a boolean as to whether the element was passivated, and the +// second is is an iterator to the next element. This is designed to be traversed in a for loop just like map erase. +std::pair + BeaconRegistry::BeaconDB::passivate(BeaconRegistry::HistoricalBeaconMap::iterator& iter) +{ + // m-historical itself holds one reference, additional references can be held by m_beacons and m_pending. + // If there is only one reference then remove the shared_pointer from m_historical, which will implicitly destroy + // the shared_pointer object. + if (iter->second.use_count() == 1) + { + iter = m_historical.erase(iter); + return std::make_pair(iter, true); + } + else + { + LogPrint(BCLog::LogFlags::BEACON, "INFO: %s: Passivate called for historical beacon record with hash %s that " + "has existing reference count %li. This is expected under certain situations, " + "such as a forced (re)advertisement, where the new pending beacon is allowed " + "to expire, while the original is still active.", + __func__, + iter->second->m_hash.GetHex(), + iter->second.use_count()); + + ++iter; + return std::make_pair(iter, false); + } +} + BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::begin() { return m_historical.begin(); @@ -1435,7 +1550,7 @@ BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::end() return m_historical.end(); } -BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::find(uint256& hash) +BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::find(const uint256& hash) { // See if beacon from that ctx_hash is already in the historical map. If so, get iterator. auto iter = m_historical.find(hash); @@ -1448,7 +1563,10 @@ BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::find(uin // If the load from leveldb is successful, insert into the historical map and return the iterator. if (Load(hash, beacon)) { - iter = m_historical.insert(std::make_pair(hash, static_cast(beacon))).first; + iter = m_historical.insert(std::make_pair(hash, std::make_shared(static_cast(beacon)))).first; + + // Set the needs passivation flag to true + m_needs_passivation = true; } } @@ -1463,11 +1581,6 @@ BeaconRegistry::HistoricalBeaconMap::iterator BeaconRegistry::BeaconDB::advance( return ++iter; } -Beacon& BeaconRegistry::BeaconDB::operator[](const uint256& hash) -{ - return m_historical[hash]; -} - bool BeaconRegistry::BeaconDB::Store(const uint256& hash, const StorageBeacon& beacon) { CTxDB txdb("rw"); @@ -1479,7 +1592,7 @@ bool BeaconRegistry::BeaconDB::Store(const uint256& hash, const StorageBeacon& b return txdb.WriteGenericSerializable(key, std::make_pair(m_recnum_stored, beacon)); } -bool BeaconRegistry::BeaconDB::Load(uint256& hash, StorageBeacon& beacon) +bool BeaconRegistry::BeaconDB::Load(const uint256& hash, StorageBeacon& beacon) { CTxDB txdb("r"); @@ -1494,7 +1607,7 @@ bool BeaconRegistry::BeaconDB::Load(uint256& hash, StorageBeacon& beacon) return status; } -bool BeaconRegistry::BeaconDB::Delete(uint256& hash) +bool BeaconRegistry::BeaconDB::Delete(const uint256& hash) { CTxDB txdb("rw"); diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index b7143eb3f9..1117a38ad8 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -514,25 +514,23 @@ class BeaconRegistry : public IContractHandler public: //! //! \brief The type that associates beacons with CPIDs in the registry. This - //! is done via smart pointers to save memory, since the actual beacon elements - //! are actually stored in the HistoricalBeaconMap. + //! is done via smart pointers to save memory. //! typedef std::unordered_map BeaconMap; //! //! \brief Associates pending beacons with the hash of the beacon public - //! keys. This is done via smart pointers to save memory, since the actual beacon - //! elements are actually stored in the HistoricalBeaconMap. - //! + //! keys. This is done via smart pointers to save memory. typedef std::map PendingBeaconMap; //! - //! \brief The type that associates historical beacons with a SHA256 hash. Note that - //! most of the time this is the hash of the beacon contract, but in the case of - //! beacon activations in the superblock, this is a hash of the superblock hash - //! and the cpid to make the records unique. + //! \brief The type that associates historical beacons with a SHA256 hash. This is done + //! with smart pointers to save memeory. Note that most of the time this is the hash of + //! the beacon contract, but in the case of beacon activations in the superblock, this + //! is a hash of the superblock hash and the pending beacon that is being activated's hash + //! to make the records unique. //! - typedef std::map HistoricalBeaconMap; + typedef std::map HistoricalBeaconMap; //! //! \brief Get the collection of registered beacons. @@ -697,6 +695,16 @@ class BeaconRegistry : public IContractHandler //! void ResetInMemoryOnly(); + //! + //! \brief Passivates the elements in the beacon db, which means remove from memory elements in the + //! historical map that are not referenced by either the m_beacons or m_pending. The backing store of + //! the element removed from memory is retained and will be transparently restored if find() + //! is called on the hash key for the element. + //! + //! \return The number of elements passivated. + //! + uint64_t PassivateDB(); + //! //! \brief Returns whether IsContract correction is needed in ReplayContracts during initialization //! \return @@ -710,6 +718,12 @@ class BeaconRegistry : public IContractHandler //! bool SetNeedsIsContractCorrection(bool flag); + //! + //! \brief A static function that is called by the scheduler to run the beacon database passivation. + //! + static void RunBeaconDBPassivation(); + + private: BeaconMap m_beacons; //!< Contains the active registered beacons. PendingBeaconMap m_pending; //!< Contains beacons awaiting verification. @@ -756,6 +770,12 @@ class BeaconRegistry : public IContractHandler //! bool clear_leveldb(); + //! + //! \brief Removes in memory elements for all historical records not in m_beacons or m_pending. + //! \return Number of elements passivated. + //! + uint64_t passivate_db(); + //! //! \brief Clear the historical map and leveldb beacon storage area. //! @@ -828,7 +848,18 @@ class BeaconRegistry : public IContractHandler //! //! \return Success or failure. //! - bool erase(uint256 hash); + bool erase(const uint256& hash); + + //! + //! \brief Remove an individual in memory element that is backed by leveldb that is not in m_beacons or m_pending. + //! + //! \param hash The hash that is the key to the element. + //! + //! \return A pair, the first part of which is an iterator to the next element, or map::end() if the last one, and + //! the second is success or failure of the passivation. + //! + std::pair + passivate(BeaconRegistry::HistoricalBeaconMap::iterator& iter); //! //! \brief Iterator to the beginning of the database records. @@ -854,7 +885,7 @@ class BeaconRegistry : public IContractHandler //! //! \return Iterator. //! - HistoricalBeaconMap::iterator find(uint256& hash); + HistoricalBeaconMap::iterator find(const uint256& hash); //! //! \brief Advances the iterator to the next element. @@ -863,14 +894,6 @@ class BeaconRegistry : public IContractHandler //! HistoricalBeaconMap::iterator advance(HistoricalBeaconMap::iterator iter); - //! - //! \brief Allows subscript style lookup of an element by hash in the beacon_db. Does not currently support - //! subscript style insert. - //! \param hash The hash of the element to retrieve. - //! \return Beacon - //! - Beacon& operator[](const uint256& hash); - private: //! //! \brief Type definition for the storage beacon map used in Initialize. Note that the uint64_t @@ -910,6 +933,13 @@ class BeaconRegistry : public IContractHandler //! uint64_t m_recnum_stored = 0; + //! + //! \brief The flag that indicates whether memory optimization can occur by passivating the database. This + //! flag is set true when find() retrieves a beacon element from leveldb to satisfy a hash search. + //! This would typically occur on a beacon renewal or reorganization (revert). + //! + bool m_needs_passivation = false; + //! //! \brief The flag that indicates whether IsContract correction is needed in ReplayContracts during initialization. //! @@ -933,7 +963,7 @@ class BeaconRegistry : public IContractHandler //! //! \return Success or failure. //! - bool Load(uint256& hash, StorageBeacon& beacon); + bool Load(const uint256 &hash, StorageBeacon& beacon); //! //! \brief Delete a beacon object from leveldb with the provided key value (if it exists). @@ -942,7 +972,7 @@ class BeaconRegistry : public IContractHandler //! //! \return Success or failure. //! - bool Delete(uint256& hash); + bool Delete(const uint256& hash); }; // BeaconDB diff --git a/src/gridcoin/gridcoin.cpp b/src/gridcoin/gridcoin.cpp index a88773babd..83a94e0892 100644 --- a/src/gridcoin/gridcoin.cpp +++ b/src/gridcoin/gridcoin.cpp @@ -364,6 +364,13 @@ void ScheduleUpdateChecks(CScheduler& scheduler) g_UpdateChecker->CheckForLatestUpdate(); }, 60 * 1000); } + +void ScheduleBeaconDBPassivation(CScheduler& scheduler) +{ + // Run beacon database passivation every 5 minutes. This is a very thin call most of the time. + // Please see the PassivateDB function and passivate_db. + scheduler.scheduleEvery(BeaconRegistry::RunBeaconDBPassivation, 5 * 60 * 1000); +} } // Anonymous namespace // ----------------------------------------------------------------------------- @@ -422,4 +429,5 @@ void GRC::ScheduleBackgroundJobs(CScheduler& scheduler) ScheduleBackups(scheduler); ScheduleUpdateChecks(scheduler); + ScheduleBeaconDBPassivation(scheduler); } diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index aa7434792a..0def673741 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -1055,7 +1055,7 @@ CAmount Tally::GetNewbieSuperblockAccrualCorrection(const Cpid& cpid, const Supe // than here. while (beacon_ptr->Renewed()) { - beacon_ptr = std::make_shared(beacons.GetBeaconDB().find(beacon_ptr->m_prev_beacon_hash)->second); + beacon_ptr = beacons.GetBeaconDB().find(beacon_ptr->m_prev_beacon_hash)->second; } const CBlockIndex* pindex_baseline = GRC::Tally::GetBaseline(); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index b7fe903c40..1fa7ca2a80 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -333,7 +333,7 @@ UniValue auditsnapshotaccrual(const UniValue& params, bool fHelp) { auto iter = beacons.GetBeaconDB().find(beacon_ptr->m_prev_beacon_hash); - beacon_ptr = std::make_shared(iter->second); + beacon_ptr = iter->second; LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: renewal %u beacon: timestamp = %" PRId64 ", ctx_hash = %s," " prev_beacon_ctx_hash = %s.", diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index af6dfe41ca..1c3148b530 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -105,6 +105,626 @@ struct TestKey return signature; } }; // TestKey + + +class BeaconRegistryTest +{ +public: + BeaconRegistryTest(CDataStream beacon_data + ,int64_t high_height_time + ,int low_height + ,int high_height + ,int num_blocks) : + m_high_height_time_check(high_height_time), + m_low_height_check(low_height), + m_high_height_check(high_height), + m_num_blocks_check(num_blocks) + { + GRC::BeaconRegistry& registry = GRC::GetBeaconRegistry(); + + // Make sure the registry is reset. + registry.Reset(); + + beacon_data >> m_high_height_time; + beacon_data >> m_low_height; + beacon_data >> m_high_height; + beacon_data >> m_num_blocks; + + // Import the blocks in the file and replay the relevant contracts. + for (int i = 0; i < m_num_blocks; ++i) + { + BOOST_TEST_CHECKPOINT("Processing block = " << i); + + GRC::ExportContractElement element; + + beacon_data >> element; + + uint256 block_hash = element.m_disk_block_index.GetBlockHash(); + + // Construct block index object. This comes from the guts of CtxDB::LoadBlockIndex() + CBlockIndex* pindex = GRC::MockBlockIndex::InsertBlockIndex(block_hash); + // Note the mock CBlockIndex objects created here are SPARSE; therefore the blocks + // pointed to by the pprev and pnext hashes will more than likely NOT be present here, + // and are not needed anyway for this test, so ensure set to nullptr. + pindex->pprev = nullptr; + pindex->pnext = nullptr; + pindex->nFile = element.m_disk_block_index.nFile; + pindex->nBlockPos = element.m_disk_block_index.nBlockPos; + pindex->nHeight = element.m_disk_block_index.nHeight; + pindex->nMoneySupply = element.m_disk_block_index.nMoneySupply; + pindex->nFlags = element.m_disk_block_index.nFlags; + pindex->nStakeModifier = element.m_disk_block_index.nStakeModifier; + pindex->hashProof = element.m_disk_block_index.hashProof; + pindex->nVersion = element.m_disk_block_index.nVersion; + pindex->hashMerkleRoot = element.m_disk_block_index.hashMerkleRoot; + pindex->nTime = element.m_disk_block_index.nTime; + pindex->nBits = element.m_disk_block_index.nBits; + pindex->nNonce = element.m_disk_block_index.nNonce; + pindex->m_researcher = element.m_disk_block_index.m_researcher; + + // Update hashBestChain to fixup global for BeaconRegistry::Initialize call. + hashBestChain = block_hash; + + // Import and apply all of the contracts from the file for the given block. + for (const auto& iter : element.m_ctx) + { + // ----------------------- contract ------- tx + GRC::ContractContext ctx({iter.first, iter.second, pindex}); + + // This is the "thin" version of g_dispatcher.Apply in GRC::ApplyContracts for beacons. + if (ctx->m_action == GRC::ContractAction::ADD) + { + registry.Add(ctx); + } + + if (ctx->m_action == GRC::ContractAction::REMOVE) + { + registry.Delete(ctx); + } + } + + // Activate the pending beacons that are now verified, and also mark expired pending beacons expired. + if (pindex->IsSuperblock()) + { + registry.ActivatePending(element.m_verified_beacons, + pindex->nTime, + block_hash, + pindex->nHeight); + } + } + + // Passivate the beacon db to remove unnecessary historical elements in memory. + registry.PassivateDB(); + + for (const auto& iter : registry.Beacons()) + { + m_beacons_init[iter.first] = *iter.second; + } + + m_init_number_beacons = m_beacons_init.size(); + + for (const auto& iter : registry.PendingBeacons()) + { + m_pending_beacons_init[iter.first] = *iter.second; + } + + m_init_number_pending_beacons = m_pending_beacons_init.size(); + + m_init_beacon_db_size = registry.GetBeaconDB().size(); + + auto& init_beacon_db = registry.GetBeaconDB(); + + auto init_beacon_db_iter = init_beacon_db.begin(); + while (init_beacon_db_iter != init_beacon_db.end()) + { + const uint256& hash = init_beacon_db_iter->first; + const GRC::Beacon_ptr& beacon_ptr = init_beacon_db_iter->second; + + // Create a copy of the referenced beacon object with a shared pointer to it and store. + m_local_historical_beacon_map_init[hash] = std::make_shared(*beacon_ptr); + + init_beacon_db_iter = init_beacon_db.advance(init_beacon_db_iter); + } + + // Reinitialize from leveldb to do comparison checks for reinit integrity. + + // Reset in memory structures only (which leaves leveldb undisturbed). + registry.ResetInMemoryOnly(); + + // Reinitialize from leveldb. + registry.Initialize(); + + // Passivate the beacon db to remove unnecessary historical elements in memory. + registry.PassivateDB(); + + for (const auto& iter : registry.Beacons()) + { + m_beacons_reinit[iter.first] = *iter.second; + } + + m_reinit_number_beacons = m_beacons_reinit.size(); + + for (const auto& iter : registry.PendingBeacons()) + { + m_pending_beacons_reinit[iter.first] = *iter.second; + } + + m_reinit_number_pending_beacons = m_pending_beacons_reinit.size(); + + m_reinit_beacon_db_size = registry.GetBeaconDB().size(); + + auto& reinit_beacon_db = registry.GetBeaconDB(); + + auto reinit_beacon_db_iter = reinit_beacon_db.begin(); + while (reinit_beacon_db_iter != reinit_beacon_db.end()) + { + const uint256& hash = reinit_beacon_db_iter->first; + const GRC::Beacon_ptr& beacon_ptr = reinit_beacon_db_iter->second; + + // Create a copy of the referenced beacon object with a shared pointer to it and store. + m_local_historical_beacon_map_reinit[hash] = std::make_shared(*beacon_ptr); + + reinit_beacon_db_iter = reinit_beacon_db.advance(reinit_beacon_db_iter); + } + }; + + void RunBasicChecks() + { + // These should be set to correspond to the dumpcontracts run used to create testnet_beacon.bin + BOOST_CHECK(m_high_height_time == m_high_height_time_check); + BOOST_CHECK(m_low_height == m_low_height_check); + BOOST_CHECK(m_high_height == m_high_height_check); + BOOST_CHECK(m_num_blocks == m_num_blocks_check); + + BOOST_TEST_CHECKPOINT("init_beacon_db_size = " << m_init_beacon_db_size << ", " + << "reinit_beacon_db_size = " << m_reinit_beacon_db_size); + + BOOST_CHECK_EQUAL(m_init_beacon_db_size, m_reinit_beacon_db_size); + }; + + void BeaconDatabaseComparisonChecks_m_historical() + { + // m_historical checks + + BOOST_CHECK_EQUAL(m_local_historical_beacon_map_init.size(), m_local_historical_beacon_map_reinit.size()); + + bool historical_beacon_db_comparison_success = true; + + // left join with init on the left + for (const auto& left : m_local_historical_beacon_map_init) + { + uint256 hash = left.first; + GRC::Beacon_ptr left_beacon_ptr = left.second; + + auto right_beacon_iter = m_local_historical_beacon_map_reinit.find(hash); + + if (right_beacon_iter == m_local_historical_beacon_map_reinit.end()) + { + BOOST_TEST_CHECKPOINT("beacon in init beacon db not found in reinit beacon db for cpid " + << left_beacon_ptr->m_cpid.ToString()); + + historical_beacon_db_comparison_success = false; + + std::cout << "MISSING: Reinit record missing for init record: " + << "hash = " << hash.GetHex() + << ", cpid = " << left.second->m_cpid.ToString() + << ", public key = " << left.second->m_public_key.ToString() + << ", address = " << left.second->GetAddress().ToString() + << ", timestamp = " << left.second->m_timestamp + << ", hash = " << left.second->m_hash.GetHex() + << ", prev beacon hash = " << left.second->m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left.second->m_status.Raw()) + << std::endl; + + } + else if (*left_beacon_ptr != *right_beacon_iter->second) + { + BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" + " in reinit beacon db for cpid " + << left_beacon_ptr->m_cpid.ToString()); + + historical_beacon_db_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in reinit beacon db does not match corresponding beacon" + " in init beacon db for hash = " << hash.GetHex() << std::endl; + + std::cout << "cpid = " << left_beacon_ptr->m_cpid.ToString() << std::endl; + + std::cout << "init_beacon public key = " << left_beacon_ptr->m_public_key.ToString() + << ", reinit_beacon public key = " << right_beacon_iter->second->m_public_key.ToString() << std::endl; + + std::cout << "init_beacon address = " << left_beacon_ptr->GetAddress().ToString() + << ", reinit_beacon address = " << right_beacon_iter->second->GetAddress().ToString() << std::endl; + + std::cout << "init_beacon timestamp = " << left_beacon_ptr->m_timestamp + << ", reinit_beacon timestamp = " << right_beacon_iter->second->m_timestamp << std::endl; + + std::cout << "init_beacon hash = " << left_beacon_ptr->m_hash.GetHex() + << ", reinit_beacon hash = " << right_beacon_iter->second->m_hash.GetHex() << std::endl; + + std::cout << "init_beacon prev beacon hash = " << left_beacon_ptr->m_prev_beacon_hash.GetHex() + << ", reinit_beacon prev beacon hash = " << right_beacon_iter->second->m_prev_beacon_hash.GetHex() << std::endl; + + std::cout << "init_beacon status = " << std::to_string(left_beacon_ptr->m_status.Raw()) + << ", reinit_beacon status = " << std::to_string(right_beacon_iter->second->m_status.Raw()) << std::endl; + } + } + + // left join with reinit on the left + for (const auto& left : m_local_historical_beacon_map_reinit) + { + uint256 hash = left.first; + GRC::Beacon_ptr left_beacon_ptr = left.second; + + auto right_beacon_iter = m_local_historical_beacon_map_init.find(hash); + + if (right_beacon_iter == m_local_historical_beacon_map_init.end()) + { + BOOST_TEST_CHECKPOINT("beacon in reinit beacon db not found in init beacon db for cpid " + << left_beacon_ptr->m_cpid.ToString()); + + historical_beacon_db_comparison_success = false; + + std::cout << "MISSING: init record missing for reinit record: " + << "hash = " << hash.GetHex() + << ", cpid = " << left.second->m_cpid.ToString() + << ", public key = " << left.second->m_public_key.ToString() + << ", address = " << left.second->GetAddress().ToString() + << ", timestamp = " << left.second->m_timestamp + << ", hash = " << left.second->m_hash.GetHex() + << ", prev beacon hash = " << left.second->m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left.second->m_status.Raw()) + << std::endl; + + } + else if (*left_beacon_ptr != *right_beacon_iter->second) + { + BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" + " in reinit beacon db for cpid " + << left_beacon_ptr->m_cpid.ToString()); + + historical_beacon_db_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in init beacon db does not match corresponding beacon" + " in reinit beacon db for hash = " << hash.GetHex() << std::endl; + + std::cout << "cpid = " << left_beacon_ptr->m_cpid.ToString() << std::endl; + + std::cout << "reinit_beacon public key = " << left_beacon_ptr->m_public_key.ToString() + << ", init_beacon public key = " << right_beacon_iter->second->m_public_key.ToString() << std::endl; + + std::cout << "reinit_beacon address = " << left_beacon_ptr->GetAddress().ToString() + << ", init_beacon address = " << right_beacon_iter->second->GetAddress().ToString() << std::endl; + + std::cout << "reinit_beacon timestamp = " << left_beacon_ptr->m_timestamp + << ", init_beacon timestamp = " << right_beacon_iter->second->m_timestamp << std::endl; + + std::cout << "reinit_beacon hash = " << left_beacon_ptr->m_hash.GetHex() + << ", init_beacon hash = " << right_beacon_iter->second->m_hash.GetHex() << std::endl; + + std::cout << "reinit_beacon prev beacon hash = " << left_beacon_ptr->m_prev_beacon_hash.GetHex() + << ", init_beacon prev beacon hash = " << right_beacon_iter->second->m_prev_beacon_hash.GetHex() << std::endl; + + std::cout << "reinit_beacon status = " << std::to_string(left_beacon_ptr->m_status.Raw()) + << ", init_beacon status = " << std::to_string(right_beacon_iter->second->m_status.Raw()) << std::endl; + } + } + + BOOST_CHECK(historical_beacon_db_comparison_success); + }; + + void BeaconDatabaseComparisonChecks_m_beacons() + { + BOOST_TEST_CHECKPOINT("init_number_beacons = " << m_init_number_beacons << ", " + << "reinit_number_beacons = " << m_reinit_number_beacons); + + bool number_beacons_equal = (m_init_number_beacons == m_reinit_number_beacons); + + if (!number_beacons_equal) + { + for (const auto& iter : m_beacons_init) + { + const GRC::Cpid& cpid = iter.first; + const GRC::Beacon& beacon = iter.second; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "init_beacon cpid = " << cpid.ToString() + << ", public key = " << beacon.m_public_key.ToString() + << ", address = " << beacon.GetAddress().ToString() + << ", timestamp = " << beacon.m_timestamp + << ", hash = " << beacon.m_hash.GetHex() + << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(beacon.m_status.Raw()) + << std::endl; + } + + for (const auto& iter : m_beacons_reinit) + { + const GRC::Cpid& cpid = iter.first; + const GRC::Beacon& beacon = iter.second; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "reinit beacon cpid = " << cpid.ToString() + << ", public key = " << beacon.m_public_key.ToString() + << ", address = " << beacon.GetAddress().ToString() + << ", timestamp = " << beacon.m_timestamp + << ", hash = " << beacon.m_hash.GetHex() + << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(beacon.m_status.Raw()) + << std::endl; + } + } + + BOOST_CHECK_EQUAL(m_init_number_beacons, m_reinit_number_beacons); + + bool beacon_comparison_success = true; + + // left join with init on the left + for (const auto& left : m_beacons_init) + { + GRC::Beacon left_beacon = left.second; + auto right = m_beacons_reinit.find(left.first); + + if (right == m_beacons_reinit.end()) + { + BOOST_TEST_CHECKPOINT("MISSING: beacon in init not found in reinit for cpid " + << left.first.ToString()); + beacon_comparison_success = false; + + std::cout << "MISSING: reinit beacon record missing for init beacon record: " + << "hash = " << left.second.m_hash.GetHex() + << ", cpid = " << left.second.m_cpid.ToString() + << ", public key = " << left.second.m_public_key.ToString() + << ", address = " << left.second.GetAddress().ToString() + << ", timestamp = " << left.second.m_timestamp + << ", hash = " << left.second.m_hash.GetHex() + << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left.second.m_status.Raw()) + << std::endl; + } + else if (left_beacon != right->second) + { + BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for cpid " + << left.first.ToString()); + beacon_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " + << left_beacon.m_cpid.ToString() << std::endl; + + std::cout << "init_beacon public key = " << left_beacon.m_public_key.ToString() + << ", reinit_beacon public key = " << right->second.m_public_key.ToString() << std::endl; + + std::cout << "init_beacon timestamp = " << left_beacon.m_timestamp + << ", reinit_beacon timestamp = " << right->second.m_timestamp << std::endl; + + std::cout << "init_beacon hash = " << left_beacon.m_hash.GetHex() + << ", reinit_beacon hash = " << right->second.m_hash.GetHex() << std::endl; + + std::cout << "init_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() + << ", reinit_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; + + std::cout << "init_beacon status = " << std::to_string(left_beacon.m_status.Raw()) + << ", reinit_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; + } + } + + + // left join with reinit on the left + for (const auto& left : m_beacons_reinit) + { + GRC::Beacon left_beacon = left.second; + + auto right = m_beacons_init.find(left.first); + + if (right == m_beacons_reinit.end()) + { + BOOST_TEST_CHECKPOINT("MISSING: beacon in reinit not found in init for cpid " + << left.first.ToString()); + beacon_comparison_success = false; + + std::cout << "MISSING: init beacon record missing for reinit beacon record: " + << "hash = " << left.second.m_hash.GetHex() + << ", cpid = " << left.second.m_cpid.ToString() + << ", public key = " << left.second.m_public_key.ToString() + << ", address = " << left.second.GetAddress().ToString() + << ", timestamp = " << left.second.m_timestamp + << ", hash = " << left.second.m_hash.GetHex() + << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left.second.m_status.Raw()) + << std::endl; + + } + else if (left_beacon != right->second) + { + BOOST_TEST_CHECKPOINT("MISMATCH: beacon in init mismatches reinit for cpid " + << left.first.ToString()); + beacon_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " + << left_beacon.m_cpid.ToString() << std::endl; + + std::cout << "reinit_beacon public key = " << left_beacon.m_public_key.ToString() + << ", init_beacon public key = " << right->second.m_public_key.ToString() << std::endl; + + std::cout << "reinit_beacon timestamp = " << left_beacon.m_timestamp + << ", init_beacon timestamp = " << right->second.m_timestamp << std::endl; + + std::cout << "reinit_beacon hash = " << left_beacon.m_hash.GetHex() + << ", init_beacon hash = " << right->second.m_hash.GetHex() << std::endl; + + std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() + << ", init_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; + + std::cout << "reinit_beacon status = " << std::to_string(left_beacon.m_status.Raw()) + << ", init_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; + } + } + + BOOST_CHECK(beacon_comparison_success); + }; + + void BeaconDatabaseComparisonChecks_m_pending() + { + BOOST_TEST_CHECKPOINT("init_number_pending_beacons.size() = " << m_init_number_pending_beacons << ", " + << "reinit_number_pending_beacons.size() = " << m_reinit_number_pending_beacons); + + BOOST_CHECK_EQUAL(m_init_number_pending_beacons, m_reinit_number_pending_beacons); + + bool pending_beacon_comparison_success = true; + + // left join with init on the left + for (const auto& left : m_pending_beacons_init) + { + GRC::Beacon left_beacon = left.second; + auto right = m_pending_beacons_reinit.find(left.first); + + if (right == m_pending_beacons_reinit.end()) + { + BOOST_TEST_CHECKPOINT("MISSING: pending beacon in init not found in reinit for CKeyID " + << left.first.ToString()); + pending_beacon_comparison_success = false; + + std::cout << "MISSING: reinit pending beacon record missing for init pending beacon record: " + << "hash = " << left_beacon.m_hash.GetHex() + << ", cpid = " << left_beacon.m_cpid.ToString() + << ", public key = " << left_beacon.m_public_key.ToString() + << ", address = " << left_beacon.GetAddress().ToString() + << ", timestamp = " << left_beacon.m_timestamp + << ", hash = " << left_beacon.m_hash.GetHex() + << ", prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left_beacon.m_status.Raw()) + << std::endl; + } + else if (left_beacon != right->second) + { + BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " + << left.first.ToString()); + pending_beacon_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " + << left.first.ToString() << std::endl; + + std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() + << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; + + std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() + << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; + + std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp + << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; + + std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() + << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; + + std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() + << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() + << std::endl; + + std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) + << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; + } + } + + // left join with reinit on the left + for (const auto& left : m_pending_beacons_reinit) + { + GRC::Beacon left_beacon = left.second; + auto right = m_pending_beacons_init.find(left.first); + + if (right == m_pending_beacons_init.end()) + { + BOOST_TEST_CHECKPOINT("MISSING: pending beacon in reinit not found in init for CKeyID " + << left.first.ToString()); + pending_beacon_comparison_success = false; + + std::cout << "MISSING: init pending beacon record missing for reinit pending beacon record: " + << "hash = " << left.second.m_hash.GetHex() + << ", cpid = " << left.second.m_cpid.ToString() + << ", public key = " << left.second.m_public_key.ToString() + << ", address = " << left.second.GetAddress().ToString() + << ", timestamp = " << left.second.m_timestamp + << ", hash = " << left.second.m_hash.GetHex() + << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() + << ", status = " << std::to_string(left.second.m_status.Raw()) + << std::endl; + } + else if (left_beacon != right->second) + { + BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " + << left.first.ToString()); + pending_beacon_comparison_success = false; + + // This is for console output in case the test fails and you run test_gridcoin manually from the command line. + // You should be in the src directory for that, so the command would be ./test/test_gridcoin. + std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " + << left.first.ToString() << std::endl; + + std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() + << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; + + std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() + << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; + + std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp + << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; + + std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() + << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; + + std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() + << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() + << std::endl; + + std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) + << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; + } + } + + BOOST_CHECK(pending_beacon_comparison_success); + }; + + int64_t m_high_height_time = 0; + int m_low_height = 0; + int m_high_height = 0; + int m_num_blocks = 0; + + int64_t m_high_height_time_check = 0; + int m_low_height_check = 0; + int m_high_height_check = 0; + int m_num_blocks_check = 0; + + // Record the map of beacons and pending beacons after the contract replay. We have to have independent storage + // of these, not pointers, because the maps are going to get reset for the second run (reinit). + typedef std::unordered_map LocalBeaconMap; + typedef std::map LocalPendingBeaconMap; + + LocalBeaconMap m_beacons_init; + LocalPendingBeaconMap m_pending_beacons_init; + GRC::BeaconRegistry::HistoricalBeaconMap m_local_historical_beacon_map_init; + size_t m_init_number_beacons = 0; + size_t m_init_number_pending_beacons = 0; + size_t m_init_beacon_db_size = 0; + + LocalBeaconMap m_beacons_reinit; + LocalPendingBeaconMap m_pending_beacons_reinit; + GRC::BeaconRegistry::HistoricalBeaconMap m_local_historical_beacon_map_reinit; + size_t m_reinit_number_beacons = 0; + size_t m_reinit_number_pending_beacons = 0; + size_t m_reinit_beacon_db_size = 0; +}; + } // anonymous namespace // ----------------------------------------------------------------------------- @@ -461,1192 +1081,57 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream) BOOST_AUTO_TEST_CASE(beaconstorage_testnet_test) { - CDataStream data(SER_DISK, PROTOCOL_VERSION); - - data << testnet_beacon_bin; - - GRC::BeaconRegistry& registry = GRC::GetBeaconRegistry(); - - // Make sure the registry is reset. - registry.Reset(); - - int64_t high_height_time = 0; - int low_height = 0; - int high_height = 0; - int num_blocks = 0; - - data >> high_height_time; - data >> low_height; - data >> high_height; - data >> num_blocks; - // These should be set to correspond to the dumpcontracts run used to create testnet_beacon.bin - BOOST_CHECK(high_height_time == 1613880656); - BOOST_CHECK(low_height == 1301500); - BOOST_CHECK(high_height == 1497976); - BOOST_CHECK(num_blocks == 271); - - - // Import the blocks in the file and replay the relevant contracts. - for (int i = 0; i < num_blocks; ++i) - { - BOOST_TEST_CHECKPOINT("Processing block = " << i); - - GRC::ExportContractElement element; - - data >> element; - - uint256 block_hash = element.m_disk_block_index.GetBlockHash(); - - // Construct block index object. This comes from the guts of CtxDB::LoadBlockIndex() - CBlockIndex* pindex = GRC::MockBlockIndex::InsertBlockIndex(block_hash); - // Note the mock CBlockIndex objects created here are SPARSE; therefore the blocks - // pointed to by the pprev and pnext hashes will more than likely NOT be present here, - // and are not needed anyway for this test, so ensure set to nullptr. - pindex->pprev = nullptr; - pindex->pnext = nullptr; - pindex->nFile = element.m_disk_block_index.nFile; - pindex->nBlockPos = element.m_disk_block_index.nBlockPos; - pindex->nHeight = element.m_disk_block_index.nHeight; - pindex->nMoneySupply = element.m_disk_block_index.nMoneySupply; - pindex->nFlags = element.m_disk_block_index.nFlags; - pindex->nStakeModifier = element.m_disk_block_index.nStakeModifier; - pindex->hashProof = element.m_disk_block_index.hashProof; - pindex->nVersion = element.m_disk_block_index.nVersion; - pindex->hashMerkleRoot = element.m_disk_block_index.hashMerkleRoot; - pindex->nTime = element.m_disk_block_index.nTime; - pindex->nBits = element.m_disk_block_index.nBits; - pindex->nNonce = element.m_disk_block_index.nNonce; - pindex->m_researcher = element.m_disk_block_index.m_researcher; - - // Update hashBestChain to fixup global for BeaconRegistry::Initialize call. - hashBestChain = block_hash; - - // Import and apply all of the contracts from the file for the given block. - for (const auto& iter : element.m_ctx) - { - // ----------------------- contract ------- tx - GRC::ContractContext ctx({iter.first, iter.second, pindex}); - - // This is the "thin" version of g_dispatcher.Apply in GRC::ApplyContracts for beacons. - if (ctx->m_action == GRC::ContractAction::ADD) - { - registry.Add(ctx); - } - - if (ctx->m_action == GRC::ContractAction::REMOVE) - { - registry.Delete(ctx); - } - } - - // Activate the pending beacons that are now verified, and also mark expired pending beacons expired. - if (pindex->IsSuperblock()) - { - registry.ActivatePending(element.m_verified_beacons, - pindex->nTime, - block_hash, - pindex->nHeight); - } - } - - // Record the map of beacons and pending beacons after the contract replay. We have to have independent storage - // of these, not pointers, because the maps are going to get reset for the second run (reinit). - typedef std::unordered_map LocalBeaconMap; - typedef std::map LocalPendingBeaconMap; - - LocalBeaconMap beacons_init; - - for (const auto& iter : registry.Beacons()) - { - beacons_init[iter.first] = *iter.second; - } - - size_t init_number_beacons = beacons_init.size(); - - LocalPendingBeaconMap pending_beacons_init; - - for (const auto& iter : registry.PendingBeacons()) - { - pending_beacons_init[iter.first] = *iter.second; - } - - size_t init_number_pending_beacons = pending_beacons_init.size(); - + int64_t high_height_time = 1613880656; + int low_height = 1301500; + int high_height = 1497976; + int num_blocks = 271; - GRC::BeaconRegistry::HistoricalBeaconMap local_historical_beacon_map_init; - - size_t init_beacon_db_size = registry.GetBeaconDB().size(); - - auto& init_beacon_db = registry.GetBeaconDB(); - - auto init_beacon_db_iter = init_beacon_db.begin(); - while (init_beacon_db_iter != init_beacon_db.end()) - { - const uint256& hash = init_beacon_db_iter->first; - const GRC::Beacon& beacon = init_beacon_db_iter->second; - - local_historical_beacon_map_init[hash] = beacon; - - init_beacon_db_iter = init_beacon_db.advance(init_beacon_db_iter); - } - - // Reset in memory structures only (which leaves leveldb undisturbed). - registry.ResetInMemoryOnly(); - - - - // (Re)initialize the registry from leveldb. - registry.Initialize(); - - LocalBeaconMap beacons_reinit; - - for (const auto& iter : registry.Beacons()) - { - beacons_reinit[iter.first] = *iter.second; - } - - size_t reinit_number_beacons = beacons_reinit.size(); - - LocalPendingBeaconMap pending_beacons_reinit; - - for (const auto& iter : registry.PendingBeacons()) - { - pending_beacons_reinit[iter.first] = *iter.second; - } - - size_t reinit_number_pending_beacons = pending_beacons_reinit.size(); + CDataStream data(SER_DISK, PROTOCOL_VERSION); + data << testnet_beacon_bin; - GRC::BeaconRegistry::HistoricalBeaconMap local_historical_beacon_map_reinit; + BeaconRegistryTest beacon_registry_test(data, + high_height_time, + low_height, + high_height, + num_blocks); - size_t reinit_beacon_db_size = registry.GetBeaconDB().size(); + beacon_registry_test.RunBasicChecks(); - auto& reinit_beacon_db = registry.GetBeaconDB(); + beacon_registry_test.BeaconDatabaseComparisonChecks_m_historical(); - auto reinit_beacon_db_iter = reinit_beacon_db.begin(); - while (reinit_beacon_db_iter != reinit_beacon_db.end()) - { - const uint256& hash = reinit_beacon_db_iter->first; - const GRC::Beacon& beacon = reinit_beacon_db_iter->second; + beacon_registry_test.BeaconDatabaseComparisonChecks_m_beacons(); - local_historical_beacon_map_reinit[hash] = beacon; + beacon_registry_test.BeaconDatabaseComparisonChecks_m_pending(); +} - reinit_beacon_db_iter = reinit_beacon_db.advance(reinit_beacon_db_iter); - } +BOOST_AUTO_TEST_CASE(beaconstorage_mainnet_test) +{ + // These should be set to correspond to the dumpcontracts run used to create mainnet_beacon.bin + int64_t high_height_time = 1613904992; + int low_height = 2053000; + int high_height = 2177791; + int num_blocks = 2370; - BOOST_TEST_CHECKPOINT("init_beacon_db_size = " << init_beacon_db_size << ", " - << "reinit_beacon_db_size = " << reinit_beacon_db_size); + CDataStream data(SER_DISK, PROTOCOL_VERSION); - BOOST_CHECK_EQUAL(init_beacon_db_size, reinit_beacon_db_size); + data << mainnet_beacon_bin; + BeaconRegistryTest beacon_registry_test(data, + high_height_time, + low_height, + high_height, + num_blocks); - bool beacon_db_comparison_success = true; + beacon_registry_test.RunBasicChecks(); - // left join with init on the left - for (const auto& left : local_historical_beacon_map_init) - { - uint256 hash = left.first; - GRC::Beacon left_beacon = left.second; + beacon_registry_test.BeaconDatabaseComparisonChecks_m_historical(); - auto right = local_historical_beacon_map_reinit.find(hash); - - if (right == local_historical_beacon_map_reinit.end()) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db not found in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - std::cout << "MISSING: Reinit record missing for init record: " - << "hash = " << hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit beacon db does not match corresponding beacon" - " in init beacon db for hash = " << hash.GetHex() << std::endl; - - std::cout << "cpid = " << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "init_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_beacon address = " << left_beacon.GetAddress().ToString() - << ", reinit_beacon address = " << right->second.GetAddress().ToString() << std::endl; - - std::cout << "init_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "init_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - - // left join with reinit on the left - for (const auto& left : local_historical_beacon_map_reinit) - { - uint256 hash = left.first; - GRC::Beacon left_beacon = left.second; - - auto right = local_historical_beacon_map_init.find(hash); - - if (right == local_historical_beacon_map_init.end()) - { - BOOST_TEST_CHECKPOINT("beacon in reinit beacon db not found in init beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - std::cout << "MISSING: init record missing for reinit record: " - << "hash = " << hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for hash = " << hash.GetHex() << std::endl; - - std::cout << "cpid = " << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "reinit_beacon public key = " << left_beacon.m_public_key.ToString() - << ", init_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "reinit_beacon address = " << left_beacon.GetAddress().ToString() - << ", init_beacon address = " << right->second.GetAddress().ToString() << std::endl; - - std::cout << "reinit_beacon timestamp = " << left_beacon.m_timestamp - << ", init_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "reinit_beacon hash = " << left_beacon.m_hash.GetHex() - << ", init_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", init_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", init_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - BOOST_CHECK(beacon_db_comparison_success); - - BOOST_CHECK_EQUAL(local_historical_beacon_map_init.size(), local_historical_beacon_map_reinit.size()); - - - - - BOOST_TEST_CHECKPOINT("init_number_beacons = " << init_number_beacons << ", " - << "reinit_number_beacons = " << reinit_number_beacons); - - bool number_beacons_equal = (init_number_beacons == reinit_number_beacons); - - if (!number_beacons_equal) - { - for (const auto& iter : beacons_init) - { - const GRC::Cpid& cpid = iter.first; - const GRC::Beacon& beacon = iter.second; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "init_beacon cpid = " << cpid.ToString() - << ", public key = " << beacon.m_public_key.ToString() - << ", address = " << beacon.GetAddress().ToString() - << ", timestamp = " << beacon.m_timestamp - << ", hash = " << beacon.m_hash.GetHex() - << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(beacon.m_status.Raw()) - << std::endl; - } - - for (const auto& iter : beacons_reinit) - { - const GRC::Cpid& cpid = iter.first; - const GRC::Beacon& beacon = iter.second; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "reinit beacon cpid = " << cpid.ToString() - << ", public key = " << beacon.m_public_key.ToString() - << ", address = " << beacon.GetAddress().ToString() - << ", timestamp = " << beacon.m_timestamp - << ", hash = " << beacon.m_hash.GetHex() - << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(beacon.m_status.Raw()) - << std::endl; - } - } - - BOOST_CHECK_EQUAL(init_number_beacons, reinit_number_beacons); - - - - BOOST_TEST_CHECKPOINT("init_number_pending_beacons.size() = " << init_number_pending_beacons << ", " - << "reinit_number_pending_beacons.size() = " << reinit_number_pending_beacons); - - BOOST_CHECK_EQUAL(init_number_pending_beacons, reinit_number_pending_beacons); - - - - bool beacon_comparison_success = true; - - // left join with init on the left - for (const auto& left : beacons_init) - { - GRC::Beacon left_beacon = left.second; - auto right = beacons_reinit.find(left.first); - - if (right == beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: beacon in init not found in reinit for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - std::cout << "MISSING: reinit beacon record missing for init beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " - << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "init_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "init_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - - // left join with reinit on the left - for (const auto& left : beacons_reinit) - { - GRC::Beacon left_beacon = left.second; - - auto right = beacons_init.find(left.first); - - if (right == beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: beacon in reinit not found in init for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - std::cout << "MISSING: init beacon record missing for reinit beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in init mismatches reinit for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " - << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "reinit_beacon public key = " << left_beacon.m_public_key.ToString() - << ", init_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "reinit_beacon timestamp = " << left_beacon.m_timestamp - << ", init_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "reinit_beacon hash = " << left_beacon.m_hash.GetHex() - << ", init_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", init_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", init_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - BOOST_CHECK(beacon_comparison_success); - - - bool pending_beacon_comparison_success = true; - - // left join with init on the left - for (const auto& left : pending_beacons_init) - { - GRC::Beacon left_beacon = left.second; - auto right = pending_beacons_reinit.find(left.first); - - if (right == pending_beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: pending beacon in init not found in reinit for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - std::cout << "MISSING: reinit pending beacon record missing for init pending beacon record: " - << "hash = " << left_beacon.m_hash.GetHex() - << ", cpid = " << left_beacon.m_cpid.ToString() - << ", public key = " << left_beacon.m_public_key.ToString() - << ", address = " << left_beacon.GetAddress().ToString() - << ", timestamp = " << left_beacon.m_timestamp - << ", hash = " << left_beacon.m_hash.GetHex() - << ", prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left_beacon.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString() << std::endl; - - std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() - << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; - - std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() - << std::endl; - - std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - // left join with reinit on the left - for (const auto& left : pending_beacons_reinit) - { - GRC::Beacon left_beacon = left.second; - auto right = pending_beacons_init.find(left.first); - - if (right == pending_beacons_init.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: pending beacon in reinit not found in init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - std::cout << "MISSING: init pending beacon record missing for reinit pending beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString() << std::endl; - - std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() - << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; - - std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() - << std::endl; - - std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - BOOST_CHECK(pending_beacon_comparison_success); -} - - -BOOST_AUTO_TEST_CASE(beaconstorage_mainnet_test) -{ - CDataStream data(SER_DISK, PROTOCOL_VERSION); - - data << mainnet_beacon_bin; - - GRC::BeaconRegistry& registry = GRC::GetBeaconRegistry(); - - // Make sure the registry is reset. - registry.Reset(); - - int64_t high_height_time = 0; - int low_height = 0; - int high_height = 0; - int num_blocks = 0; - - data >> high_height_time; - data >> low_height; - data >> high_height; - data >> num_blocks; - - // These should be set to correspond to the dumpcontracts run used to create mainnet_beacon.bin - BOOST_CHECK(high_height_time == 1613904992); - BOOST_CHECK(low_height == 2053000); - BOOST_CHECK(high_height == 2177791); - BOOST_CHECK(num_blocks == 2370); - - // Import the blocks in the file and replay the relevant contracts. - for (int i = 0; i < num_blocks; ++i) - { - BOOST_TEST_CHECKPOINT("Processing block = " << i); - - GRC::ExportContractElement element; - - data >> element; - - uint256 block_hash = element.m_disk_block_index.GetBlockHash(); - - // Construct block index object. This comes from the guts of CtxDB::LoadBlockIndex() - CBlockIndex* pindex = GRC::MockBlockIndex::InsertBlockIndex(block_hash); - // Note the mock CBlockIndex objects created here are SPARSE; therefore the blocks - // pointed to by the pprev and pnext hashes will more than likely NOT be present here, - // and are not needed anyway for this test, so ensure set to nullptr. - pindex->pprev = nullptr; - pindex->pnext = nullptr; - pindex->nFile = element.m_disk_block_index.nFile; - pindex->nBlockPos = element.m_disk_block_index.nBlockPos; - pindex->nHeight = element.m_disk_block_index.nHeight; - pindex->nMoneySupply = element.m_disk_block_index.nMoneySupply; - pindex->nFlags = element.m_disk_block_index.nFlags; - pindex->nStakeModifier = element.m_disk_block_index.nStakeModifier; - pindex->hashProof = element.m_disk_block_index.hashProof; - pindex->nVersion = element.m_disk_block_index.nVersion; - pindex->hashMerkleRoot = element.m_disk_block_index.hashMerkleRoot; - pindex->nTime = element.m_disk_block_index.nTime; - pindex->nBits = element.m_disk_block_index.nBits; - pindex->nNonce = element.m_disk_block_index.nNonce; - pindex->m_researcher = element.m_disk_block_index.m_researcher; - - // Update hashBestChain to fixup global for BeaconRegistry::Initialize call. - hashBestChain = block_hash; - - // Import and apply all of the contracts from the file for the given block. - for (const auto& iter : element.m_ctx) - { - // ----------------------- contract ------- tx - GRC::ContractContext ctx({iter.first, iter.second, pindex}); - - // This is the "thin" version of g_dispatcher.Apply in GRC::ApplyContracts for beacons. - if (ctx->m_action == GRC::ContractAction::ADD) - { - registry.Add(ctx); - } - - if (ctx->m_action == GRC::ContractAction::REMOVE) - { - registry.Delete(ctx); - } - } - - // Activate the pending beacons that are now verified, and also mark expired pending beacons expired. - if (pindex->IsSuperblock()) - { - registry.ActivatePending(element.m_verified_beacons, - pindex->nTime, - block_hash, - pindex->nHeight); - } - } - - // Record the map of beacons and pending beacons after the contract replay. We have to have independent storage - // of these, not pointers, because the maps are going to get reset for the second run (reinit). - typedef std::unordered_map LocalBeaconMap; - typedef std::map LocalPendingBeaconMap; - - LocalBeaconMap beacons_init; - - for (const auto& iter : registry.Beacons()) - { - beacons_init[iter.first] = *iter.second; - } - - size_t init_number_beacons = beacons_init.size(); - - LocalPendingBeaconMap pending_beacons_init; - - for (const auto& iter : registry.PendingBeacons()) - { - pending_beacons_init[iter.first] = *iter.second; - } - - size_t init_number_pending_beacons = pending_beacons_init.size(); - - - GRC::BeaconRegistry::HistoricalBeaconMap local_historical_beacon_map_init; - - size_t init_beacon_db_size = registry.GetBeaconDB().size(); - - auto& init_beacon_db = registry.GetBeaconDB(); - - auto init_beacon_db_iter = init_beacon_db.begin(); - while (init_beacon_db_iter != init_beacon_db.end()) - { - const uint256& hash = init_beacon_db_iter->first; - const GRC::Beacon& beacon = init_beacon_db_iter->second; - - local_historical_beacon_map_init[hash] = beacon; - - init_beacon_db_iter = init_beacon_db.advance(init_beacon_db_iter); - } - - // Reset in memory structures only (which leaves leveldb undisturbed). - registry.ResetInMemoryOnly(); - - - - // (Re)initialize the registry from leveldb. - registry.Initialize(); - - LocalBeaconMap beacons_reinit; - - for (const auto& iter : registry.Beacons()) - { - beacons_reinit[iter.first] = *iter.second; - } - - size_t reinit_number_beacons = beacons_reinit.size(); - - LocalPendingBeaconMap pending_beacons_reinit; - - for (const auto& iter : registry.PendingBeacons()) - { - pending_beacons_reinit[iter.first] = *iter.second; - } - - size_t reinit_number_pending_beacons = pending_beacons_reinit.size(); - - - GRC::BeaconRegistry::HistoricalBeaconMap local_historical_beacon_map_reinit; - - size_t reinit_beacon_db_size = registry.GetBeaconDB().size(); - - auto& reinit_beacon_db = registry.GetBeaconDB(); - - auto reinit_beacon_db_iter = reinit_beacon_db.begin(); - while (reinit_beacon_db_iter != reinit_beacon_db.end()) - { - const uint256& hash = reinit_beacon_db_iter->first; - const GRC::Beacon& beacon = reinit_beacon_db_iter->second; - - local_historical_beacon_map_reinit[hash] = beacon; - - reinit_beacon_db_iter = reinit_beacon_db.advance(reinit_beacon_db_iter); - } - - - BOOST_TEST_CHECKPOINT("init_beacon_db_size = " << init_beacon_db_size << ", " - << "reinit_beacon_db_size = " << reinit_beacon_db_size); - - BOOST_CHECK_EQUAL(init_beacon_db_size, reinit_beacon_db_size); - - - bool beacon_db_comparison_success = true; - - // left join with init on the left - for (const auto& left : local_historical_beacon_map_init) - { - uint256 hash = left.first; - GRC::Beacon left_beacon = left.second; - - auto right = local_historical_beacon_map_reinit.find(hash); - - if (right == local_historical_beacon_map_reinit.end()) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db not found in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - std::cout << "MISSING: Reinit record missing for init record: " - << "hash = " << hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit beacon db does not match corresponding beacon" - " in init beacon db for hash = " << hash.GetHex() << std::endl; - - std::cout << "cpid = " << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "init_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_beacon address = " << left_beacon.GetAddress().ToString() - << ", reinit_beacon address = " << right->second.GetAddress().ToString() << std::endl; - - std::cout << "init_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "init_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - - // left join with reinit on the left - for (const auto& left : local_historical_beacon_map_reinit) - { - uint256 hash = left.first; - GRC::Beacon left_beacon = left.second; - - auto right = local_historical_beacon_map_init.find(hash); - - if (right == local_historical_beacon_map_init.end()) - { - BOOST_TEST_CHECKPOINT("beacon in reinit beacon db not found in init beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - std::cout << "MISSING: init record missing for reinit record: " - << "hash = " << hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for cpid " - << left_beacon.m_cpid.ToString()); - - beacon_db_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in init beacon db does not match corresponding beacon" - " in reinit beacon db for hash = " << hash.GetHex() << std::endl; - - std::cout << "cpid = " << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "reinit_beacon public key = " << left_beacon.m_public_key.ToString() - << ", init_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "reinit_beacon address = " << left_beacon.GetAddress().ToString() - << ", init_beacon address = " << right->second.GetAddress().ToString() << std::endl; - - std::cout << "reinit_beacon timestamp = " << left_beacon.m_timestamp - << ", init_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "reinit_beacon hash = " << left_beacon.m_hash.GetHex() - << ", init_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", init_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", init_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - BOOST_CHECK(beacon_db_comparison_success); - - BOOST_CHECK_EQUAL(local_historical_beacon_map_init.size(), local_historical_beacon_map_reinit.size()); - - - - - BOOST_TEST_CHECKPOINT("init_number_beacons = " << init_number_beacons << ", " - << "reinit_number_beacons = " << reinit_number_beacons); - - bool number_beacons_equal = (init_number_beacons == reinit_number_beacons); - - if (!number_beacons_equal) - { - for (const auto& iter : beacons_init) - { - const GRC::Cpid& cpid = iter.first; - const GRC::Beacon& beacon = iter.second; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "init_beacon cpid = " << cpid.ToString() - << ", public key = " << beacon.m_public_key.ToString() - << ", address = " << beacon.GetAddress().ToString() - << ", timestamp = " << beacon.m_timestamp - << ", hash = " << beacon.m_hash.GetHex() - << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(beacon.m_status.Raw()) - << std::endl; - } - - for (const auto& iter : beacons_reinit) - { - const GRC::Cpid& cpid = iter.first; - const GRC::Beacon& beacon = iter.second; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "reinit beacon cpid = " << cpid.ToString() - << ", public key = " << beacon.m_public_key.ToString() - << ", address = " << beacon.GetAddress().ToString() - << ", timestamp = " << beacon.m_timestamp - << ", hash = " << beacon.m_hash.GetHex() - << ", prev beacon hash = " << beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(beacon.m_status.Raw()) - << std::endl; - } - } - - BOOST_CHECK_EQUAL(init_number_beacons, reinit_number_beacons); - - - - BOOST_TEST_CHECKPOINT("init_number_pending_beacons.size() = " << init_number_pending_beacons << ", " - << "reinit_number_pending_beacons.size() = " << reinit_number_pending_beacons); - - BOOST_CHECK_EQUAL(init_number_pending_beacons, reinit_number_pending_beacons); - - - - bool beacon_comparison_success = true; - - // left join with init on the left - for (const auto& left : beacons_init) - { - GRC::Beacon left_beacon = left.second; - auto right = beacons_reinit.find(left.first); - - if (right == beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: beacon in init not found in reinit for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - std::cout << "MISSING: reinit beacon record missing for init beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " - << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "init_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "init_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - - // left join with reinit on the left - for (const auto& left : beacons_reinit) - { - GRC::Beacon left_beacon = left.second; - - auto right = beacons_init.find(left.first); - - if (right == beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: beacon in reinit not found in init for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - std::cout << "MISSING: init beacon record missing for reinit beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in init mismatches reinit for cpid " - << left.first.ToString()); - beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for cpid = " - << left_beacon.m_cpid.ToString() << std::endl; - - std::cout << "reinit_beacon public key = " << left_beacon.m_public_key.ToString() - << ", init_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "reinit_beacon timestamp = " << left_beacon.m_timestamp - << ", init_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "reinit_beacon hash = " << left_beacon.m_hash.GetHex() - << ", init_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", init_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() << std::endl; - - std::cout << "reinit_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", init_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - BOOST_CHECK(beacon_comparison_success); - - - bool pending_beacon_comparison_success = true; - - // left join with init on the left - for (const auto& left : pending_beacons_init) - { - GRC::Beacon left_beacon = left.second; - auto right = pending_beacons_reinit.find(left.first); - - if (right == pending_beacons_reinit.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: pending beacon in init not found in reinit for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - std::cout << "MISSING: reinit pending beacon record missing for init pending beacon record: " - << "hash = " << left_beacon.m_hash.GetHex() - << ", cpid = " << left_beacon.m_cpid.ToString() - << ", public key = " << left_beacon.m_public_key.ToString() - << ", address = " << left_beacon.GetAddress().ToString() - << ", timestamp = " << left_beacon.m_timestamp - << ", hash = " << left_beacon.m_hash.GetHex() - << ", prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left_beacon.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString() << std::endl; - - std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() - << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; - - std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() - << std::endl; - - std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } - - // left join with reinit on the left - for (const auto& left : pending_beacons_reinit) - { - GRC::Beacon left_beacon = left.second; - auto right = pending_beacons_init.find(left.first); - - if (right == pending_beacons_init.end()) - { - BOOST_TEST_CHECKPOINT("MISSING: pending beacon in reinit not found in init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - std::cout << "MISSING: init pending beacon record missing for reinit pending beacon record: " - << "hash = " << left.second.m_hash.GetHex() - << ", cpid = " << left.second.m_cpid.ToString() - << ", public key = " << left.second.m_public_key.ToString() - << ", address = " << left.second.GetAddress().ToString() - << ", timestamp = " << left.second.m_timestamp - << ", hash = " << left.second.m_hash.GetHex() - << ", prev beacon hash = " << left.second.m_prev_beacon_hash.GetHex() - << ", status = " << std::to_string(left.second.m_status.Raw()) - << std::endl; - } - else if (left_beacon != right->second) - { - BOOST_TEST_CHECKPOINT("MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString()); - pending_beacon_comparison_success = false; - - // This is for console output in case the test fails and you run test_gridcoin manually from the command line. - // You should be in the src directory for that, so the command would be ./test/test_gridcoin. - std::cout << "MISMATCH: beacon in reinit mismatches init for CKeyID " - << left.first.ToString() << std::endl; - - std::cout << "init_pending_beacon cpid = " << left_beacon.m_cpid.ToString() - << ", reinit_pending_beacon cpid = " << right->second.m_cpid.ToString() << std::endl; - - std::cout << "init_pending_beacon public key = " << left_beacon.m_public_key.ToString() - << ", reinit_pending_beacon public key = " << right->second.m_public_key.ToString() << std::endl; - - std::cout << "init_pending_beacon timestamp = " << left_beacon.m_timestamp - << ", reinit_pending_beacon timestamp = " << right->second.m_timestamp << std::endl; - - std::cout << "init_pending_beacon hash = " << left_beacon.m_hash.GetHex() - << ", reinit_pending_beacon hash = " << right->second.m_hash.GetHex() << std::endl; - - std::cout << "init_pending_beacon prev beacon hash = " << left_beacon.m_prev_beacon_hash.GetHex() - << ", reinit_pending_beacon prev beacon hash = " << right->second.m_prev_beacon_hash.GetHex() - << std::endl; - - std::cout << ", init_pending_beacon status = " << std::to_string(left_beacon.m_status.Raw()) - << ", reinit_pending_beacon status = " << std::to_string(right->second.m_status.Raw()) << std::endl; - } - } + beacon_registry_test.BeaconDatabaseComparisonChecks_m_beacons(); - BOOST_CHECK(pending_beacon_comparison_success); + beacon_registry_test.BeaconDatabaseComparisonChecks_m_pending(); } BOOST_AUTO_TEST_SUITE_END()