Skip to content

Commit cb111dd

Browse files
committed
Implement lambdas in GetBeaconChainletRoot to improve readability
Also make a few other improvements, such as verification that the previous beacon to the original activated beacon has a status of pending.
1 parent 4f09656 commit cb111dd

File tree

1 file changed

+71
-115
lines changed

1 file changed

+71
-115
lines changed

src/gridcoin/beacon.cpp

Lines changed: 71 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -800,127 +800,100 @@ int BeaconRegistry::GetDBHeight()
800800
Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon,
801801
std::shared_ptr<std::vector<std::pair<uint256, int64_t>>> beacon_chain_out)
802802
{
803-
Cpid cpid = beacon->m_cpid;
804-
805-
// The chain head itself.
806-
auto beacon_iter = m_beacon_db.find(beacon->m_hash);
807-
808-
if (beacon_iter == m_beacon_db.end()) {
809-
// Beacon chainlet chainhead cannot be found. This is fatal.
810-
811-
error("%s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s,"
812-
"prev_beacon_ctx_hash = %s, status = %s: not found in the registry.",
803+
const auto ChainletErrorHandle = [this](unsigned int i, Beacon_ptr beacon, std::string error_message) {
804+
error("%s: Beacon chainlet is corrupted at link %u for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s,"
805+
"prev_beacon_ctx_hash = %s, status = %s: %s.",
813806
__func__,
807+
i,
814808
beacon->m_cpid.ToString(),
815809
beacon->m_timestamp,
816810
beacon->m_hash.GetHex(),
817811
beacon->m_previous_hash.GetHex(),
818-
beacon->StatusToString());
812+
beacon->StatusToString(),
813+
error_message);
819814

820-
std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at chainhead for cpid %s: timestamp = %s"
821-
PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: not found "
822-
"in the registry.",
815+
std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at link %u for cpid %s: timestamp = %s"
816+
PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: %s.",
823817
__func__,
818+
i,
824819
beacon->m_cpid.ToString(),
825820
beacon->m_timestamp,
826821
beacon->m_hash.GetHex(),
827822
beacon->m_previous_hash.GetHex(),
828-
beacon->StatusToString());
823+
beacon->StatusToString(),
824+
error_message);
829825

830826
Reset();
831827

832828
uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR);
833829

834-
throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."});
835-
}
836-
837-
// Given that we have had rare situations where somehow circularity has occurred in the beacon chainlet, which either
838-
// results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing
839-
// back to a beacon in a circular manner, this vector is used to detect the circularity.
840-
std::vector<uint256> encountered_hashes { beacon->m_hash };
830+
throw std::runtime_error(std::string {"The beacon registry is corrupted and will be rebuilt on the next start. "
831+
"Please restart."});
832+
};
841833

842-
if (beacon_chain_out != nullptr) {
843-
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: chainlet head beacon for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s,"
834+
const auto ChainletLinkLog = [&beacon_chain_out](unsigned int i, Beacon_ptr beacon) {
835+
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon chainlet link %u for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s,"
844836
" prev_beacon_ctx_hash = %s, status = %s.",
845837
__func__,
838+
i,
846839
beacon->m_cpid.ToString(),
847840
beacon->m_timestamp,
848841
beacon->m_hash.GetHex(),
849842
beacon->m_previous_hash.GetHex(),
850843
beacon->StatusToString());
851844

845+
if (beacon_chain_out == nullptr) {
846+
return;
847+
}
848+
852849
beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp));
850+
};
851+
852+
unsigned int i = 0;
853+
854+
// Given that we have had rare situations where somehow circularity has occurred in the beacon chainlet, which either
855+
// results in the current hash and previous hash being the same, or even suspected previous hash of another entry pointing
856+
// back to a beacon in a circular manner, this vector is used to detect the circularity.
857+
std::vector<uint256> encountered_hashes;
858+
859+
// The chain head itself. (This uses a scope to separate beacon_iter.)
860+
{
861+
auto beacon_iter = m_beacon_db.find(beacon->m_hash);
862+
863+
if (beacon_iter == m_beacon_db.end()) {
864+
// Beacon chainlet chainhead cannot be found. This is fatal.
865+
ChainletErrorHandle(i, beacon, "not found in the registry");
866+
}
867+
868+
// Make sure status is renewed or active.
869+
if (beacon_iter->second->m_status != BeaconStatusForStorage::ACTIVE
870+
&& beacon_iter->second->m_status != BeaconStatusForStorage::RENEWAL) {
871+
ChainletErrorHandle(i, beacon, "beacon status is not active or renewal");
872+
}
873+
874+
encountered_hashes.push_back(beacon->m_hash);
875+
876+
ChainletLinkLog(i, beacon);
877+
878+
++i;
853879
}
854880

855881
// Walk back the entries in the historical beacon map linked by renewal prev tx hash until the first
856882
// beacon in the renewal chain is found (the original advertisement). The accrual starts no earlier
857883
// than here.
858-
unsigned int i = 0;
859-
860884
while (beacon->Renewed())
861885
{
862886
// Select previous beacon in chainlet
863887
auto beacon_iter = m_beacon_db.find(beacon->m_previous_hash);
864888

865889
if (beacon_iter == m_beacon_db.end()) {
866-
// Linked beacon in chainlet cannot be found. This is fatal.
867-
868-
error("%s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s" PRId64 ", ctx_hash = %s,"
869-
"prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found in the registry.",
870-
__func__,
871-
i + 1,
872-
beacon->m_cpid.ToString(),
873-
beacon->m_timestamp,
874-
beacon->m_hash.GetHex(),
875-
beacon->m_previous_hash.GetHex(),
876-
beacon->StatusToString());
877-
878-
std::string str_error = strprintf("ERROR: %s: Beacon chainlet is corrupted at %u links back for cpid %s: timestamp = %s"
879-
PRId64 ", ctx_hash = %s, prev_beacon_ctx_hash = %s, status = %s: prev_beacon not found "
880-
"in the registry.",
881-
__func__,
882-
i + 1,
883-
beacon->m_cpid.ToString(),
884-
beacon->m_timestamp,
885-
beacon->m_hash.GetHex(),
886-
beacon->m_previous_hash.GetHex(),
887-
beacon->StatusToString());
888-
889-
Reset();
890-
891-
uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR);
892-
893-
throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."});
890+
ChainletErrorHandle(i, beacon, "previous beacon not found in the registry");
894891
}
895892

896893
if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) {
897894
// If circularity is found this is an indication of corruption of beacon state and is fatal.
898895
// Produce an error message, reset the beacon registry, and require a restart of the node.
899-
900-
error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, "
901-
"at %u linked entries back from the start, with offending hash %s.",
902-
__func__,
903-
cpid.ToString(),
904-
beacon->m_hash.GetHex(),
905-
i + 1,
906-
beacon->m_previous_hash.GetHex());
907-
908-
std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, "
909-
"starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n"
910-
"\n"
911-
"The client cannot continue and the beacon history has been reset and will be rebuilt "
912-
"on the next restart. Please restart Gridcoin.",
913-
__func__,
914-
cpid.ToString(),
915-
beacon->m_hash.GetHex(),
916-
i + 1,
917-
beacon->m_previous_hash.GetHex());
918-
919-
Reset();
920-
921-
uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR);
922-
923-
throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."});
896+
ChainletErrorHandle(i, beacon, "circularity encountered");
924897
}
925898

926899
// Reassign previous beacon to beacon.
@@ -929,51 +902,34 @@ Beacon_ptr BeaconRegistry::GetBeaconChainletRoot(Beacon_ptr beacon,
929902
encountered_hashes.push_back(beacon->m_hash);
930903

931904
if (beacon_chain_out != nullptr) {
932-
LogPrint(BCLog::LogFlags::ACCRUAL, "INFO %s: beacon %u links back for cpid %s: timestamp = %" PRId64 ", ctx_hash = %s,"
933-
" prev_beacon_ctx_hash = %s, status = %s.",
934-
__func__,
935-
i + 1,
936-
beacon->m_cpid.ToString(),
937-
beacon->m_timestamp,
938-
beacon->m_hash.GetHex(),
939-
beacon->m_previous_hash.GetHex(),
940-
beacon->StatusToString());
941-
942-
beacon_chain_out->push_back(std::make_pair(beacon->m_hash, beacon->m_timestamp));
905+
ChainletLinkLog(i, beacon);
943906
}
944907

945908
++i;
946909
}
947910

948-
// Check of initial advertised beacon's previous hash.
949-
if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) {
950-
// If circularity is found this is an indication of corruption of beacon state and is fatal.
951-
// Produce an error message, reset the beacon registry, and require a restart of the node.
911+
// Check of initial advertised beacon's previous hash. This should point to the pending beacon that was activated and not
912+
// anywhere else.
913+
{
914+
// Select previous beacon in chainlet
915+
auto beacon_iter = m_beacon_db.find(beacon->m_previous_hash);
952916

953-
error("%s: Circularity encountered in beacon ownership chain for beacon with CPID %s, starting at hash %s, "
954-
"at %u linked entries back from the start, with offending hash %s.",
955-
__func__,
956-
cpid.ToString(),
957-
beacon->m_hash.GetHex(),
958-
i + 1,
959-
beacon->m_previous_hash.GetHex());
960-
961-
std::string str_error = strprintf("ERROR: %s: Circularity encountered in beacon ownership chain for beacon with CPID %s, "
962-
"starting at hash %s, at %u linked entries back from the start, with offending hash %s.\n"
963-
"\n"
964-
"The client cannot continue and the beacon history has been reset and will be rebuilt "
965-
"on the next restart. Please restart Gridcoin.",
966-
__func__,
967-
cpid.ToString(),
968-
beacon->m_hash.GetHex(),
969-
i + 1,
970-
beacon->m_previous_hash.GetHex());
917+
if (beacon_iter == m_beacon_db.end()) {
918+
ChainletErrorHandle(i, beacon, "previous beacon not found in the registry");
919+
}
971920

972-
Reset();
921+
// Make sure status of previous beacon is pending.
922+
if (beacon_iter->second->m_status != BeaconStatusForStorage::PENDING) {
923+
ChainletErrorHandle(i, beacon, "previous beacon to the beacon marked active is not pending");
924+
}
973925

974-
uiInterface.ThreadSafeMessageBox(str_error, "Gridcoin", CClientUIInterface::MSG_ERROR);
926+
if (std::find(encountered_hashes.begin(), encountered_hashes.end(), beacon->m_previous_hash) != encountered_hashes.end()) {
927+
// If circularity is found this is an indication of corruption of beacon state and is fatal.
928+
// Produce an error message, reset the beacon registry, and require a restart of the node.
929+
ChainletErrorHandle(i, beacon, "circularity encountered");
930+
}
975931

976-
throw std::runtime_error(std::string {"The beacon registry is corrupted and Gridcoin cannot continue. Please restart."});
932+
// Note that we do not actually walk back to the pending beacon. The parameter beacon remains at the activated beacon.
977933
}
978934

979935
return beacon;

0 commit comments

Comments
 (0)