Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate masternode db records to V2 #826

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/flushablestorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static bool BytesToDbType(const TBytes& bytes, T& value) {
stream >> value;
// assert(stream.size() == 0); // will fail with partial key matching
}
catch (std::ios_base::failure&) {
catch (const std::ios_base::failure&) {
return false;
}
return true;
Expand Down Expand Up @@ -475,7 +475,11 @@ class CStorageView {
bool Read(const KeyType& key, ValueType& value) const {
auto vKey = DbTypeToBytes(key);
TBytes vValue;
return DB().Read(vKey, vValue) && BytesToDbType(vValue, value);
if (DB().Read(vKey, vValue)) {
BytesToDbType(vValue, value);
return true;
}
return false;
}
template<typename By, typename KeyType, typename ValueType>
bool ReadBy(const KeyType& key, ValueType& value) const {
Expand All @@ -484,7 +488,7 @@ class CStorageView {
// second type of 'ReadBy' (may be 'GetBy'?)
template<typename By, typename ResultType, typename KeyType>
std::optional<ResultType> ReadBy(KeyType const & id) const {
ResultType result;
ResultType result{};
if (ReadBy<By>(id, result))
return {result};
return {};
Expand Down
12 changes: 6 additions & 6 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2018,15 +2018,15 @@ bool AppInitMain(InitInterfaces& interfaces)
CTxDestination rewardDest;
auto optMasternodeID = pcustomcsview->GetMasternodeIdByOperator(operatorId);
if (optMasternodeID) {
auto nodePtr = pcustomcsview->GetMasternode(*optMasternodeID);
assert(nodePtr); // this should not happen if MN was found by operator's id
auto nodePtr = pcustomcsview->GetMasternodeV2(*optMasternodeID, chain_active_height);
assert(nodePtr);
ownerDest = nodePtr->ownerType == PKHashType ?
CTxDestination(PKHash(nodePtr->ownerAuthAddress)) :
CTxDestination(WitnessV0KeyHash(nodePtr->ownerAuthAddress));
CTxDestination(PKHash(nodePtr->ownerAuthAddress)) :
CTxDestination(WitnessV0KeyHash(nodePtr->ownerAuthAddress));
if (nodePtr->rewardAddressType != 0) {
rewardDest = nodePtr->rewardAddressType == PKHashType ?
CTxDestination(PKHash(nodePtr->rewardAddress)) :
CTxDestination(WitnessV0KeyHash(nodePtr->rewardAddress));
CTxDestination(PKHash(nodePtr->rewardAddress)) :
CTxDestination(WitnessV0KeyHash(nodePtr->rewardAddress));
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ class ChainImpl : public Chain
return pcustomcsview->CanSpend(nodeId, height);
}

std::optional<CMasternode> mnExists(const uint256 & nodeId) const override
bool mnExists(const uint256 & nodeId) const override
{
LOCK(cs_main);
return pcustomcsview->GetMasternode(nodeId);
return pcustomcsview->GetMasternode(nodeId).has_value();
}
std::unique_ptr<CToken> existTokenGuessId(const std::string & str, DCT_ID & id) const override
{
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ class Chain
//! populates the values.
virtual void findCoins(std::map<COutPoint, Coin>& coins) = 0;

virtual bool mnExists(const uint256 & nodeId) const = 0;
virtual bool mnCanSpend(const uint256 & nodeId, int height) const = 0;
virtual std::optional<CMasternode> mnExists(const uint256 & nodeId) const = 0;
virtual std::unique_ptr<CToken> existTokenGuessId(const std::string & str, DCT_ID & id) const = 0;

//! Estimate fraction of total transactions verified if blocks up to
Expand Down
136 changes: 89 additions & 47 deletions src/masternodes/masternodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,8 @@ CMasternode::CMasternode()
, ownerType(0)
, operatorAuthAddress()
, operatorType(0)
, rewardAddress()
, rewardAddressType(0)
, creationHeight(0)
, resignHeight(-1)
, version(-1)
, resignTx()
, banTx()
{
}

Expand Down Expand Up @@ -160,39 +155,45 @@ bool operator==(CMasternode const & a, CMasternode const & b)
a.ownerAuthAddress == b.ownerAuthAddress &&
a.operatorType == b.operatorType &&
a.operatorAuthAddress == b.operatorAuthAddress &&
a.rewardAddress == b.rewardAddress &&
a.rewardAddressType == b.rewardAddressType &&
a.creationHeight == b.creationHeight &&
a.resignHeight == b.resignHeight &&
a.version == b.version &&
a.resignTx == b.resignTx &&
a.banTx == b.banTx
);
a.resignHeight == b.resignHeight);
}

bool operator!=(CMasternode const & a, CMasternode const & b)
{
return !(a == b);
}

/*
* Check that given node is involved in anchor's subsystem for a given height (or smth like that)
*/
//bool IsAnchorInvolved(const uint256 & nodeId, int height) const
//{
// /// @todo to be implemented
// return false;
//}


bool operator==(CMasternodeV2 const & a, CMasternodeV2 const & b)
{
return static_cast<CMasternode const &>(a) == static_cast<CMasternode const &>(b) &&
a.resignTx == b.resignTx &&
a.rewardAddress == b.rewardAddress &&
a.rewardAddressType == b.rewardAddressType;
}

bool operator!=(CMasternodeV2 const & a, CMasternodeV2 const & b)
{
return !(a == b);
}

/*
* CMasternodesView
*/
std::optional<CMasternode> CMasternodesView::GetMasternode(const uint256 & id) const
std::optional<CMasternodeV1> CMasternodesView::GetMasternode(const uint256 & id) const
{
return ReadBy<ID, CMasternode>(id);
return ReadBy<ID, CMasternodeV1>(id);
}

std::optional<CMasternodeV2> CMasternodesView::GetMasternodeV2(const uint256 & id, int height) const
{
if (height >= Params().GetConsensus().GreatWorldHeight) {
return ReadBy<ID, CMasternodeV2>(id);
}
if (auto node = GetMasternode(id)) {
return ConvertMasternode(*node);
}
return {};
}

std::optional<uint256> CMasternodesView::GetMasternodeIdByOperator(const CKeyID & id) const
Expand All @@ -205,25 +206,69 @@ std::optional<uint256> CMasternodesView::GetMasternodeIdByOwner(const CKeyID & i
return ReadBy<Owner, uint256>(id);
}

void CMasternodesView::ForEachMasternode(std::function<bool (const uint256 &, CLazySerialize<CMasternode>)> callback, uint256 const & start)
void CMasternodesView::ForEachMasternode(std::function<bool (const uint256 &, CLazySerialize<CMasternodeV1>)> callback, uint256 const & start)
{
ForEach<ID, uint256, CMasternode>(callback, start);
ForEach<ID, uint256, CMasternodeV1>(callback, start);
}

void CMasternodesView::IncrementMintedBy(const uint256& nodeId)
void CMasternodesView::ForEachMasternodeV2(std::function<bool (const uint256 &, CLazySerialize<CMasternodeV2>)> callback, uint256 const & start)
{
auto node = GetMasternode(nodeId);
ForEach<ID, uint256, CMasternodeV2>(callback, start);
}

void CMasternodesView::RevertMasternodesToV1(int height)
{
std::vector<std::pair<uint256, CMasternodeV2>> nodes;
ForEachMasternodeV2([&](const uint256& nodeId, CMasternodeV2 node) {
nodes.emplace_back(nodeId, std::move(node));
return true;
});
for (auto it = nodes.begin(); it != nodes.end(); it = nodes.erase(it)) {
StoreMasternode(it->first, it->second, height);
}
}

void CMasternodesView::MigrateMasternodesToV2(int height)
{
std::vector<std::pair<uint256, CMasternodeV1>> nodes;
ForEachMasternode([&](const uint256& nodeId, CMasternodeV1 node) {
nodes.emplace_back(nodeId, std::move(node));
return true;
});
for (auto it = nodes.begin(); it != nodes.end(); it = nodes.erase(it)) {
StoreMasternode(it->first, ConvertMasternode(it->second), height);
}
}

void CMasternodesView::StoreMasternode(const uint256& nodeId, const CMasternodeV2& node, int height)
{
if (node.rewardAddressType == 0 && node.resignTx.IsNull()) {
// we can safety store cheaper structure
WriteBy<ID>(nodeId, static_cast<const CMasternode&>(node));
return;
}

if (height >= Params().GetConsensus().GreatWorldHeight) {
WriteBy<ID>(nodeId, node);
} else {
WriteBy<ID>(nodeId, ConvertMasternode(node));
}
}

void CMasternodesView::IncrementMintedBy(const uint256& nodeId, int height)
{
auto node = GetMasternodeV2(nodeId, height);
assert(node);
++node->mintedBlocks;
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);
}

void CMasternodesView::DecrementMintedBy(const uint256& nodeId)
void CMasternodesView::DecrementMintedBy(const uint256& nodeId, int height)
{
auto node = GetMasternode(nodeId);
auto node = GetMasternodeV2(nodeId, height);
assert(node);
--node->mintedBlocks;
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);
}

std::optional<std::pair<CKeyID, uint256> > CMasternodesView::AmIOperator() const
Expand Down Expand Up @@ -284,6 +329,7 @@ Res CMasternodesView::CreateMasternode(const uint256 & nodeId, const CMasternode
return Res::Err("bad owner and|or operator address (should be P2PKH or P2WPKH only) or node with those addresses exists");
}

// we can safety store cheaper structure
WriteBy<ID>(nodeId, node);
WriteBy<Owner>(node.ownerAuthAddress, nodeId);
WriteBy<Operator>(node.operatorAuthAddress, nodeId);
Expand All @@ -298,10 +344,11 @@ Res CMasternodesView::CreateMasternode(const uint256 & nodeId, const CMasternode
Res CMasternodesView::ResignMasternode(const uint256 & nodeId, const uint256 & txid, int height)
{
// auth already checked!
auto node = GetMasternode(nodeId);
auto node = GetMasternodeV2(nodeId, height);
if (!node) {
return Res::Err("node %s does not exists", nodeId.ToString());
}

auto state = node->GetState(height);
if (height >= Params().GetConsensus().EunosPayaHeight) {
if (state != CMasternode::ENABLED) {
Expand All @@ -318,14 +365,14 @@ Res CMasternodesView::ResignMasternode(const uint256 & nodeId, const uint256 & t

node->resignTx = txid;
node->resignHeight = height;
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);

return Res::Ok();
}

Res CMasternodesView::SetForcedRewardAddress(uint256 const & nodeId, const char rewardAddressType, CKeyID const & rewardAddress, int height)
{
auto node = GetMasternode(nodeId);
auto node = GetMasternodeV2(nodeId, height);
if (!node) {
return Res::Err("masternode %s does not exists", nodeId.ToString());
}
Expand All @@ -334,22 +381,17 @@ Res CMasternodesView::SetForcedRewardAddress(uint256 const & nodeId, const char
return Res::Err("masternode %s state is not 'PRE_ENABLED' or 'ENABLED'", nodeId.ToString());
}

// If old masternode update foor new serialisatioono
if (node->version < CMasternode::VERSION0) {
node->version = CMasternode::VERSION0;
}

// Set new reward address
node->rewardAddressType = rewardAddressType;
node->rewardAddress = rewardAddress;
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);

return Res::Ok();
}

Res CMasternodesView::RemForcedRewardAddress(uint256 const & nodeId, int height)
{
auto node = GetMasternode(nodeId);
auto node = GetMasternodeV2(nodeId, height);
if (!node) {
return Res::Err("masternode %s does not exists", nodeId.ToString());
}
Expand All @@ -360,14 +402,15 @@ Res CMasternodesView::RemForcedRewardAddress(uint256 const & nodeId, int height)

node->rewardAddressType = 0;
node->rewardAddress.SetNull();
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);

return Res::Ok();
}

Res CMasternodesView::UpdateMasternode(uint256 const & nodeId, char operatorType, const CKeyID& operatorAuthAddress, int height) {
Res CMasternodesView::UpdateMasternode(uint256 const & nodeId, char operatorType, const CKeyID& operatorAuthAddress, int height)
{
// auth already checked!
auto node = GetMasternode(nodeId);
auto node = GetMasternodeV2(nodeId, height);
if (!node) {
return Res::Err("node %s does not exists", nodeId.ToString());
}
Expand All @@ -387,8 +430,7 @@ Res CMasternodesView::UpdateMasternode(uint256 const & nodeId, char operatorType
node->operatorType = operatorType;
node->operatorAuthAddress = operatorAuthAddress;

// Overwrite and create new record
WriteBy<ID>(nodeId, *node);
StoreMasternode(nodeId, *node, height);
WriteBy<Operator>(node->operatorAuthAddress, nodeId);

return Res::Ok();
Expand Down
Loading