Skip to content

Commit

Permalink
fix: Resolve mainnet v19 fork issues (#5403)
Browse files Browse the repository at this point in the history
## Issue being fixed or feature implemented
same as  #5392, alternative solution

~based on #5402 atm, will rebase later~

## What was done?
pls see individual commits

## How Has This Been Tested?
reorg mainnet around forkpoint with a patched client (to allow low
difficulty), run tests

## Breaking Changes
Another evodb migration is required. Going back to an older version or
migrating after the fork requires reindexing.

## Checklist:
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation
- [x] I have assigned this pull request to a milestone _(for repository
code-owners and collaborators only)_
  • Loading branch information
UdjinM6 authored Jun 4, 2023
1 parent 86dc99f commit 54fb76f
Show file tree
Hide file tree
Showing 29 changed files with 519 additions and 148 deletions.
33 changes: 17 additions & 16 deletions src/bls/bls.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,7 @@ class CBLSLazyWrapper
CBLSLazyWrapper() :
vecBytes(BLSObject::SerSize, 0),
bufLegacyScheme(bls::bls_legacy_scheme.load())
{
// the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid
bufValid = true;
}
{}

explicit CBLSLazyWrapper(const CBLSLazyWrapper& r)
{
Expand Down Expand Up @@ -459,12 +456,8 @@ class CBLSLazyWrapper
{
std::unique_lock<std::mutex> l(mutex);
if (!objInitialized && !bufValid) {
// the all-zero buf is considered a valid buf
std::fill(vecBytes.begin(), vecBytes.end(), 0);
bufLegacyScheme = specificLegacyScheme;
bufValid = true;
}
if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) {
} else if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) {
vecBytes = obj.ToByteVector(specificLegacyScheme);
bufValid = true;
bufLegacyScheme = specificLegacyScheme;
Expand All @@ -476,7 +469,7 @@ class CBLSLazyWrapper
template<typename Stream>
inline void Serialize(Stream& s) const
{
Serialize(s, bls::bls_legacy_scheme.load());
Serialize(s, bufLegacyScheme);
}

template<typename Stream>
Expand All @@ -493,13 +486,14 @@ class CBLSLazyWrapper
template<typename Stream>
inline void Unserialize(Stream& s) const
{
Unserialize(s, bls::bls_legacy_scheme.load());
Unserialize(s, bufLegacyScheme);
}

void Set(const BLSObject& _obj)
void Set(const BLSObject& _obj, const bool specificLegacyScheme)
{
std::unique_lock<std::mutex> l(mutex);
bufValid = false;
bufLegacyScheme = specificLegacyScheme;
objInitialized = true;
obj = _obj;
hash.SetNull();
Expand Down Expand Up @@ -549,13 +543,15 @@ class CBLSLazyWrapper
return !(*this == r);
}

uint256 GetHash(const bool specificLegacyScheme = bls::bls_legacy_scheme.load()) const
uint256 GetHash() const
{
std::unique_lock<std::mutex> l(mutex);
if (!bufValid || bufLegacyScheme != specificLegacyScheme) {
vecBytes = obj.ToByteVector(specificLegacyScheme);
if (!objInitialized && !bufValid) {
std::fill(vecBytes.begin(), vecBytes.end(), 0);
hash.SetNull();
} else if (!bufValid) {
vecBytes = obj.ToByteVector(bufLegacyScheme);
bufValid = true;
bufLegacyScheme = specificLegacyScheme;
hash.SetNull();
}
if (hash.IsNull()) {
Expand All @@ -565,6 +561,11 @@ class CBLSLazyWrapper
}
return hash;
}

std::string ToString() const
{
return Get().ToString(bufLegacyScheme);
}
};
using CBLSLazySignature = CBLSLazyWrapper<CBLSSignature>;
using CBLSLazyPublicKey = CBLSLazyWrapper<CBLSPublicKey>;
Expand Down
191 changes: 129 additions & 62 deletions src/evo/deterministicmns.cpp

Large diffs are not rendered by default.

53 changes: 37 additions & 16 deletions src/evo/deterministicmns.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class CDeterministicMN
uint64_t internalId{std::numeric_limits<uint64_t>::max()};

public:
static constexpr uint16_t CURRENT_MN_FORMAT = 0;
static constexpr uint16_t MN_OLD_FORMAT = 0;
static constexpr uint16_t MN_TYPE_FORMAT = 1;
static constexpr uint16_t MN_VERSION_FORMAT = 2;
static constexpr uint16_t MN_CURRENT_FORMAT = MN_VERSION_FORMAT;

uint256 proTxHash;
COutPoint collateralOutpoint;
Expand Down Expand Up @@ -73,12 +75,16 @@ class CDeterministicMN
READWRITE(VARINT(internalId));
READWRITE(collateralOutpoint);
READWRITE(nOperatorReward);
// We need to read CDeterministicMNState using the old format only when called with CURRENT_MN_FORMAT on Unserialize()
// We need to read CDeterministicMNState using the old format only when called with MN_OLD_FORMAT or MN_TYPE_FORMAT on Unserialize()
// Serialisation (writing) will be done always using new format
if (ser_action.ForRead() && format_version == CURRENT_MN_FORMAT) {
if (ser_action.ForRead() && format_version == MN_OLD_FORMAT) {
CDeterministicMNState_Oldformat old_state;
READWRITE(old_state);
pdmnState = std::make_shared<const CDeterministicMNState>(old_state);
} else if (ser_action.ForRead() && format_version == MN_TYPE_FORMAT) {
CDeterministicMNState_mntype_format old_state;
READWRITE(old_state);
pdmnState = std::make_shared<const CDeterministicMNState>(old_state);
} else {
READWRITE(pdmnState);
}
Expand All @@ -97,11 +103,11 @@ class CDeterministicMN
template<typename Stream>
void Serialize(Stream& s) const
{
const_cast<CDeterministicMN*>(this)->SerializationOp(s, CSerActionSerialize(), MN_TYPE_FORMAT);
const_cast<CDeterministicMN*>(this)->SerializationOp(s, CSerActionSerialize(), MN_CURRENT_FORMAT);
}

template <typename Stream>
void Unserialize(Stream& s, const uint8_t format_version = MN_TYPE_FORMAT)
void Unserialize(Stream& s, const uint8_t format_version = MN_CURRENT_FORMAT)
{
SerializationOp(s, CSerActionUnserialize(), format_version);
}
Expand Down Expand Up @@ -203,14 +209,14 @@ class CDeterministicMNList
}

template<typename Stream>
void Unserialize(Stream& s, const uint8_t format_version = CDeterministicMN::MN_TYPE_FORMAT) {
void Unserialize(Stream& s, const uint8_t format_version = CDeterministicMN::MN_CURRENT_FORMAT) {
mnMap = MnMap();
mnUniquePropertyMap = MnUniquePropertyMap();
mnInternalIdMap = MnInternalIdMap();

SerializationOpBase(s, CSerActionUnserialize());

bool evodb_migration = (format_version == CDeterministicMN::CURRENT_MN_FORMAT);
bool evodb_migration = (format_version == CDeterministicMN::MN_OLD_FORMAT || format_version == CDeterministicMN::MN_TYPE_FORMAT);
size_t cnt = ReadCompactSize(s);
for (size_t i = 0; i < cnt; i++) {
if (evodb_migration) {
Expand Down Expand Up @@ -383,8 +389,6 @@ class CDeterministicMNList
[[nodiscard]] CDeterministicMNListDiff BuildDiff(const CDeterministicMNList& to) const;
[[nodiscard]] CDeterministicMNList ApplyDiff(const CBlockIndex* pindex, const CDeterministicMNListDiff& diff) const;

void RepopulateUniquePropertyMap();

void AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTotalCount = true);
void UpdateMN(const CDeterministicMN& oldDmn, const std::shared_ptr<const CDeterministicMNState>& pdmnState);
void UpdateMN(const uint256& proTxHash, const std::shared_ptr<const CDeterministicMNState>& pdmnState);
Expand All @@ -394,19 +398,27 @@ class CDeterministicMNList
template <typename T>
[[nodiscard]] bool HasUniqueProperty(const T& v) const
{
return mnUniquePropertyMap.count(::SerializeHash(v)) != 0;
return mnUniquePropertyMap.count(GetUniquePropertyHash(v)) != 0;
}
template <typename T>
[[nodiscard]] CDeterministicMNCPtr GetUniquePropertyMN(const T& v) const
{
auto p = mnUniquePropertyMap.find(::SerializeHash(v));
auto p = mnUniquePropertyMap.find(GetUniquePropertyHash(v));
if (!p) {
return nullptr;
}
return GetMN(p->first);
}

private:
template <typename T>
[[nodiscard]] uint256 GetUniquePropertyHash(const T& v) const
{
if constexpr (std::is_same<T, CBLSPublicKey>()) {
assert(false);
}
return ::SerializeHash(v);
}
template <typename T>
[[nodiscard]] bool AddUniqueProperty(const CDeterministicMN& dmn, const T& v)
{
Expand All @@ -415,7 +427,7 @@ class CDeterministicMNList
return false;
}

auto hash = ::SerializeHash(v);
auto hash = GetUniquePropertyHash(v);
auto oldEntry = mnUniquePropertyMap.find(hash);
if (oldEntry != nullptr && oldEntry->first != dmn.proTxHash) {
return false;
Expand All @@ -435,7 +447,7 @@ class CDeterministicMNList
return false;
}

auto oldHash = ::SerializeHash(oldValue);
auto oldHash = GetUniquePropertyHash(oldValue);
auto p = mnUniquePropertyMap.find(oldHash);
if (p == nullptr || p->first != dmn.proTxHash) {
return false;
Expand Down Expand Up @@ -464,6 +476,16 @@ class CDeterministicMNList
}
return true;
}

friend bool operator==(const CDeterministicMNList& a, const CDeterministicMNList& b)
{
return a.blockHash == b.blockHash &&
a.nHeight == b.nHeight &&
a.nTotalRegisteredCount == b.nTotalRegisteredCount &&
a.mnMap == b.mnMap &&
a.mnInternalIdMap == b.mnInternalIdMap &&
a.mnUniquePropertyMap == b.mnUniquePropertyMap;
}
};

class CDeterministicMNListDiff
Expand Down Expand Up @@ -492,7 +514,7 @@ class CDeterministicMNListDiff
}

template <typename Stream>
void Unserialize(Stream& s, const uint8_t format_version = CDeterministicMN::MN_TYPE_FORMAT)
void Unserialize(Stream& s, const uint8_t format_version = CDeterministicMN::MN_CURRENT_FORMAT)
{
updatedMNs.clear();
removedMns.clear();
Expand All @@ -502,8 +524,6 @@ class CDeterministicMNListDiff
tmp = ReadCompactSize(s);
for (size_t i = 0; i < tmp; i++) {
CDeterministicMN mn(0);
// Unserialise CDeterministicMN using CURRENT_MN_FORMAT and set it's type to the default value TYPE_REGULAR_MASTERNODE
// It will be later written with format MN_TYPE_FORMAT which includes the type field.
mn.Unserialize(s, format_version);
auto dmn = std::make_shared<CDeterministicMN>(mn);
addedMNs.push_back(dmn);
Expand Down Expand Up @@ -595,6 +615,7 @@ class CDeterministicMNManager
bool IsDIP3Enforced(int nHeight = -1) LOCKS_EXCLUDED(cs);

bool MigrateDBIfNeeded();
bool MigrateDBIfNeeded2();

void DoMaintenance() LOCKS_EXCLUDED(cs);

Expand Down
6 changes: 3 additions & 3 deletions src/evo/dmnstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ std::string CDeterministicMNState::ToString() const
return strprintf("CDeterministicMNState(nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, operatorPayoutAddress=%s)",
nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason,
EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.Get().ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress);
EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress);
}

void CDeterministicMNState::ToJson(UniValue& obj, MnType nType) const
Expand All @@ -55,7 +55,7 @@ void CDeterministicMNState::ToJson(UniValue& obj, MnType nType) const
if (ExtractDestination(scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
}
obj.pushKV("pubKeyOperator", pubKeyOperator.Get().ToString());
obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
if (ExtractDestination(scriptOperatorPayout, dest)) {
obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
}
Expand Down Expand Up @@ -108,7 +108,7 @@ void CDeterministicMNStateDiff::ToJson(UniValue& obj, MnType nType) const
}
}
if (fields & Field_pubKeyOperator) {
obj.pushKV("pubKeyOperator", state.pubKeyOperator.Get().ToString());
obj.pushKV("pubKeyOperator", state.pubKeyOperator.ToString());
}
if (nType == MnType::HighPerformance) {
if (fields & Field_platformNodeID) {
Expand Down
Loading

0 comments on commit 54fb76f

Please sign in to comment.