Skip to content

Commit

Permalink
Restore updatemasternode
Browse files Browse the repository at this point in the history
  • Loading branch information
Bushstar committed Jan 4, 2022
1 parent 89a07a4 commit e2eb658
Show file tree
Hide file tree
Showing 21 changed files with 908 additions and 559 deletions.
28 changes: 14 additions & 14 deletions src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,19 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
strprintf("%s: inputs missing/spent", __func__));
}

// check for tokens values
uint256 canSpend;
std::vector<unsigned char> dummy;
const auto txType = GuessCustomTxType(tx, dummy);

if (NotAllowedToFail(txType, nSpendHeight) || (nSpendHeight >= chainparams.GetConsensus().GreatWorldHeight && txType == CustomTxType::UpdateMasternode)) {
CCustomCSView discardCache(const_cast<CCustomCSView&>(*mnview));
auto res = ApplyCustomTx(discardCache, inputs, tx, chainparams.GetConsensus(), nSpendHeight, 0, &canSpend);
if (!res.ok && (res.code & CustomTxErrCodes::Fatal) && txType != CustomTxType::UpdateMasternode) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-customtx", res.msg);
}
}

TAmounts nValuesIn;
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
const COutPoint &prevout = tx.vin[i].prevout;
Expand All @@ -187,8 +200,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
}
/// @todo tokens: later match the range with TotalSupply

if (prevout.n == 1 && !mnview->CanSpend(prevout.hash, nSpendHeight)) {
if (canSpend != prevout.hash && prevout.n == 1 && !mnview->CanSpend(prevout.hash, nSpendHeight)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-collateral-locked",
strprintf("tried to spend locked collateral for %s", prevout.hash.ToString())); /// @todo may be somehow place the height of unlocking?
}
Expand All @@ -215,18 +227,6 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-tokens-in-old-version-tx");
}

// check for tokens values
std::vector<unsigned char> dummy;
const auto txType = GuessCustomTxType(tx, dummy);

if (NotAllowedToFail(txType, nSpendHeight)) {
CCustomCSView discardCache(const_cast<CCustomCSView&>(*mnview));
auto res = ApplyCustomTx(discardCache, inputs, tx, chainparams.GetConsensus(), nSpendHeight);
if (!res.ok && (res.code & CustomTxErrCodes::Fatal)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-customtx", res.msg);
}
}

for (auto const & kv : non_minted_values_out) {
DCT_ID const & tokenId = kv.first;

Expand Down
2 changes: 1 addition & 1 deletion src/masternodes/anchors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ bool CAnchorAwaitingConfirms::Validate(CAnchorConfirmMessage const &confirmMessa
}

auto it = pcustomcsview->GetMasternodeIdByOperator(signer);
if (!it || !pcustomcsview->GetMasternode(*it)->IsActive(height)) {
if (!it || !pcustomcsview->GetMasternode(*it)->IsActive(height, *pcustomcsview)) {
LogPrint(BCLog::ANCHORING, "%s: Warning! Masternode with operator key %s does not exist or not active!\n", __func__, signer.ToString());
return false;
}
Expand Down
176 changes: 88 additions & 88 deletions src/masternodes/masternodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,28 @@ CMasternode::CMasternode()
, resignHeight(-1)
, version(-1)
, resignTx()
, banTx()
, collateralTx()
{
}

CMasternode::State CMasternode::GetState(int height) const
CMasternode::State CMasternode::GetState(int height, const CMasternodesView& mnview) const
{
int EunosPayaHeight = Params().GetConsensus().EunosPayaHeight;

if (height < creationHeight) {
return State::UNKNOWN;
}

if (!collateralTx.IsNull()) {
auto idHeight = mnview.GetNewCollateral(collateralTx);
assert(idHeight);
if (height < idHeight->blockHeight) {
return State::TRANSFERRING;
} else if (height < idHeight->blockHeight + GetMnActivationDelay(idHeight->blockHeight)) {
return State::PRE_ENABLED;
}
}

if (resignHeight == -1 || height < resignHeight) { // enabled or pre-enabled
// Special case for genesis block
int activationDelay = height < EunosPayaHeight ? GetMnActivationDelay(height) : GetMnActivationDelay(creationHeight);
Expand All @@ -113,9 +123,9 @@ CMasternode::State CMasternode::GetState(int height) const
return State::UNKNOWN;
}

bool CMasternode::IsActive(int height) const
bool CMasternode::IsActive(int height, const CMasternodesView& mnview) const
{
State state = GetState(height);
State state = GetState(height, mnview);
if (height >= Params().GetConsensus().EunosPayaHeight) {
return state == ENABLED;
}
Expand All @@ -133,6 +143,8 @@ std::string CMasternode::GetHumanReadableState(State state)
return "PRE_RESIGNED";
case RESIGNED:
return "RESIGNED";
case TRANSFERRING:
return "TRANSFERRING";
default:
return "UNKNOWN";
}
Expand Down Expand Up @@ -160,7 +172,7 @@ bool operator==(CMasternode const & a, CMasternode const & b)
a.resignHeight == b.resignHeight &&
a.version == b.version &&
a.resignTx == b.resignTx &&
a.banTx == b.banTx
a.collateralTx == b.collateralTx
);
}

Expand Down Expand Up @@ -289,14 +301,9 @@ Res CMasternodesView::CreateMasternode(const uint256 & nodeId, const CMasternode
return Res::Ok();
}

Res CMasternodesView::ResignMasternode(const uint256 & nodeId, const uint256 & txid, int height)
Res CMasternodesView::ResignMasternode(CMasternode& node, const uint256 & nodeId, const uint256 & txid, int height)
{
// auth already checked!
auto node = GetMasternode(nodeId);
if (!node) {
return Res::Err("node %s does not exists", nodeId.ToString());
}
auto state = node->GetState(height);
auto state = node.GetState(height, *this);
if (height >= Params().GetConsensus().EunosPayaHeight) {
if (state != CMasternode::ENABLED) {
return Res::Err("node %s state is not 'ENABLED'", nodeId.ToString());
Expand All @@ -305,96 +312,85 @@ Res CMasternodesView::ResignMasternode(const uint256 & nodeId, const uint256 & t
return Res::Err("node %s state is not 'PRE_ENABLED' or 'ENABLED'", nodeId.ToString());
}

const auto timelock = GetTimelock(nodeId, *node, height);
const auto timelock = GetTimelock(nodeId, node, height);
if (timelock) {
return Res::Err("Trying to resign masternode before timelock expiration.");
}

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

return Res::Ok();
}

Res CMasternodesView::SetForcedRewardAddress(uint256 const & nodeId, const char rewardAddressType, CKeyID const & rewardAddress, int height)
void CMasternodesView::SetForcedRewardAddress(uint256 const & nodeId, CMasternode& node, const char rewardAddressType, CKeyID const & rewardAddress, int height)
{
// Temporarily disabled for 2.2
return Res::Err("reward address change is disabled for Fort Canning");

auto node = GetMasternode(nodeId);
if (!node) {
return Res::Err("masternode %s does not exists", nodeId.ToString());
}
auto state = node->GetState(height);
if ((state != CMasternode::PRE_ENABLED && state != CMasternode::ENABLED)) {
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;
// If old masternode update for new serialisation
if (node.version < CMasternode::VERSION0) {
node.version = CMasternode::VERSION0;
}

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

return Res::Ok();
node.rewardAddressType = rewardAddressType;
node.rewardAddress = rewardAddress;
WriteBy<ID>(nodeId, node);
}

Res CMasternodesView::RemForcedRewardAddress(uint256 const & nodeId, int height)
void CMasternodesView::RemForcedRewardAddress(uint256 const & nodeId, CMasternode& node, int height)
{
// Temporarily disabled for 2.2
return Res::Err("reward address change is disabled for Fort Canning");
node.rewardAddressType = 0;
node.rewardAddress.SetNull();
WriteBy<ID>(nodeId, node);
}

auto node = GetMasternode(nodeId);
if (!node) {
return Res::Err("masternode %s does not exists", nodeId.ToString());
}
auto state = node->GetState(height);
if ((state != CMasternode::PRE_ENABLED && state != CMasternode::ENABLED)) {
return Res::Err("masternode %s state is not 'PRE_ENABLED' or 'ENABLED'", nodeId.ToString());
}
void CMasternodesView::UpdateMasternodeOperator(uint256 const & nodeId, CMasternode& node, const char operatorType, const CKeyID& operatorAuthAddress, int height)
{
// Remove old record
EraseBy<Operator>(node.operatorAuthAddress);

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

return Res::Ok();
// Overwrite and create new record
WriteBy<ID>(nodeId, node);
WriteBy<Operator>(node.operatorAuthAddress, nodeId);
}

Res CMasternodesView::UpdateMasternode(uint256 const & nodeId, char operatorType, const CKeyID& operatorAuthAddress, int height) {
// Temporarily disabled for 2.2
return Res::Err("updatemasternode is disabled for Fort Canning");
void CMasternodesView::UpdateMasternodeOwner(uint256 const & nodeId, CMasternode& node, const char ownerType, const CKeyID& ownerAuthAddress)
{
// Remove old record
EraseBy<Owner>(node.ownerAuthAddress);

// auth already checked!
auto node = GetMasternode(nodeId);
if (!node) {
return Res::Err("node %s does not exists", nodeId.ToString());
}
node.ownerType = ownerType;
node.ownerAuthAddress = ownerAuthAddress;

const auto state = node->GetState(height);
if (state != CMasternode::ENABLED) {
return Res::Err("node %s state is not 'ENABLED'", nodeId.ToString());
}
// Overwrite and create new record
WriteBy<ID>(nodeId, node);
WriteBy<Owner>(node.ownerAuthAddress, nodeId);
}

if (operatorType == node->operatorType && operatorAuthAddress == node->operatorAuthAddress) {
return Res::Err("The new operator is same as existing operator");
}
void CMasternodesView::UpdateMasternodeCollateral(uint256 const & nodeId, CMasternode& node, const uint256& newCollateralTx, const int height)
{
// Remove old record.
EraseBy<NewCollateral>(node.collateralTx);

// Remove old record
EraseBy<Operator>(node->operatorAuthAddress);
// Store new collateral. Used by HasCollateralAuth.
node.collateralTx = newCollateralTx;
WriteBy<ID>(nodeId, node);

node->operatorType = operatorType;
node->operatorAuthAddress = operatorAuthAddress;
// Prioritise fast lookup in CanSpend() and GetState()
WriteBy<NewCollateral>(newCollateralTx, MNNewOwnerHeightValue{static_cast<uint32_t>(height + GetMnResignDelay(height)), nodeId});
}

// Overwrite and create new record
WriteBy<ID>(nodeId, *node);
WriteBy<Operator>(node->operatorAuthAddress, nodeId);
std::optional<MNNewOwnerHeightValue> CMasternodesView::GetNewCollateral(const uint256& txid) const
{
return ReadBy<NewCollateral, MNNewOwnerHeightValue>(txid);
}

return Res::Ok();
void CMasternodesView::ForEachNewCollateral(std::function<bool(const uint256&, CLazySerialize<MNNewOwnerHeightValue>)> callback)
{
ForEach<NewCollateral, uint256, MNNewOwnerHeightValue>(callback);
}

void CMasternodesView::SetMasternodeLastBlockTime(const CKeyID & minter, const uint32_t &blockHeight, const int64_t& time)
Expand Down Expand Up @@ -499,16 +495,12 @@ Res CMasternodesView::UnCreateMasternode(const uint256 & nodeId)
return Res::Err("No such masternode %s", nodeId.GetHex());
}

Res CMasternodesView::UnResignMasternode(const uint256 & nodeId, const uint256 & resignTx)
Res CMasternodesView::UnResignMasternode(CMasternode& node, const uint256 & nodeId)
{
auto node = GetMasternode(nodeId);
if (node && node->resignTx == resignTx) {
node->resignHeight = -1;
node->resignTx = {};
WriteBy<ID>(nodeId, *node);
return Res::Ok();
}
return Res::Err("No such masternode %s, resignTx: %s", nodeId.GetHex(), resignTx.GetHex());
node.resignHeight = -1;
node.resignTx = {};
WriteBy<ID>(nodeId, node);
return Res::Ok();
}

uint16_t CMasternodesView::GetTimelock(const uint256& nodeId, const CMasternode& node, const uint64_t height) const
Expand Down Expand Up @@ -745,7 +737,7 @@ CTeamView::CTeam CCustomCSView::CalcNextTeam(int height, const uint256 & stakeMo

std::map<arith_uint256, CKeyID, std::less<arith_uint256>> priorityMN;
ForEachMasternode([&] (uint256 const & id, CMasternode node) {
if(!node.IsActive(height))
if(!node.IsActive(height, *this))
return true;

CDataStream ss{SER_GETHASH, PROTOCOL_VERSION};
Expand Down Expand Up @@ -785,7 +777,7 @@ void CCustomCSView::CalcAnchoringTeams(const uint256 & stakeModifier, const CBlo
std::map<arith_uint256, CKeyID, std::less<arith_uint256>> authMN;
std::map<arith_uint256, CKeyID, std::less<arith_uint256>> confirmMN;
ForEachMasternode([&] (uint256 const & id, CMasternode node) {
if(!node.IsActive(pindexNew->nHeight))
if(!node.IsActive(pindexNew->nHeight, *this))
return true;

// Not in our list of MNs from last week, skip.
Expand Down Expand Up @@ -862,9 +854,17 @@ bool CCustomCSView::CanSpend(const uint256 & txId, int height) const
auto node = GetMasternode(txId);
// check if it was mn collateral and mn was resigned or banned
if (node) {
auto state = node->GetState(height);
auto state = node->GetState(height, *this);
return state == CMasternode::RESIGNED;
}

if (auto mn = GetNewCollateral(txId)) {
auto node = GetMasternode(mn->masternodeID);
assert(node);
auto state = node->GetState(height, *this);
return state == CMasternode::RESIGNED;
}

// check if it was token collateral and token already destroyed
/// @todo token check for total supply/limit when implemented
auto pair = GetTokenByCreationTx(txId);
Expand Down Expand Up @@ -1071,7 +1071,7 @@ std::map<CKeyID, CKey> AmISignerNow(int height, CAnchorData::CTeam const & team)
continue;
}

if (node->IsActive(height) && team.find(mnId.first) != team.end()) {
if (node->IsActive(height, *pcustomcsview) && team.find(mnId.first) != team.end()) {
CKey masternodeKey;
std::vector<std::shared_ptr<CWallet>> wallets = GetWallets();
for (auto const & wallet : wallets) {
Expand Down
Loading

0 comments on commit e2eb658

Please sign in to comment.