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

[Validation] [Masternode] [Test] SDMN (Shield Deterministic Masternodes) #2876

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
43 changes: 43 additions & 0 deletions src/activemasternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ void CActiveMasternode::GetKeys(CKey& _privKeyMasternode, CPubKey& _pubKeyMaster
_pubKeyMasternode = pubKeyMasternode;
}

// TODO: Remove after full transition to DMNs
bool GetActiveDMNKeys(CBLSSecretKey& key, CTxIn& vin)
{
if (activeMasternodeManager == nullptr) {
Expand All @@ -498,6 +499,7 @@ bool GetActiveDMNKeys(CBLSSecretKey& key, CTxIn& vin)
return true;
}

// TODO: Remove after full transition to DMNs
bool GetActiveMasternodeKeys(CTxIn& vin, Optional<CKey>& key, CBLSSecretKey& blsKey)
{
if (activeMasternodeManager != nullptr) {
Expand All @@ -520,3 +522,44 @@ bool GetActiveMasternodeKeys(CTxIn& vin, Optional<CKey>& key, CBLSSecretKey& bls
blsKey.Reset();
return true;
}

// Difference with the other function: here the vin returned is the one used for voting, i.e the outpoint is: (proRegTxHash; 0)
// WHICH IS OF COURSE (IN GENERAL) DIFFERENT FROM THE OUTPOINT OF THE COLLATERAL
bool GetActiveVotingDMNKeys(CBLSSecretKey& key, CTxIn& vin)
{
if (activeMasternodeManager == nullptr) {
return error("%s: Active Masternode not initialized", __func__);
}
CDeterministicMNCPtr dmn;
auto res = activeMasternodeManager->GetOperatorKey(key, dmn);
if (!res) {
return error("%s: %s", __func__, res.getError());
}
vin = CTxIn(COutPoint(dmn->proTxHash, 0));
return true;
}

// Difference with the other function: here the vin returned is the one used for voting, i.e the outpoint is: (proRegTxHash; 0)
// WHICH IS OF COURSE (IN GENERAL) DIFFERENT FROM THE OUTPOINT OF THE COLLATERAL
bool GetActiveMasternodeVotingKeys(CTxIn& vin, Optional<CKey>& key, CBLSSecretKey& blsKey)
{
if (activeMasternodeManager != nullptr) {
// deterministic mn
key = nullopt;
return GetActiveVotingDMNKeys(blsKey, vin);
}
// legacy mn
if (activeMasternode.vin == nullopt) {
return error("%s: Active Masternode not initialized", __func__);
}
if (activeMasternode.GetStatus() != ACTIVE_MASTERNODE_STARTED) {
return error("%s: MN not started (%s)", __func__, activeMasternode.GetStatusMessage());
}
vin = *activeMasternode.vin;
CKey sk;
CPubKey pk;
activeMasternode.GetKeys(sk, pk);
key = Optional<CKey>(sk);
blsKey.Reset();
return true;
}
11 changes: 9 additions & 2 deletions src/activemasternode.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,16 @@ class CActiveMasternode
void GetKeys(CKey& privKeyMasternode, CPubKey& pubKeyMasternode) const;
};

// Compatibility code: get vin and keys for either legacy or deterministic masternode
// Compatibility code: get vin OF THE COLLATERAL and keys for either legacy or deterministic masternode
// TODO: Remove after full transition to DMNs
bool GetActiveMasternodeKeys(CTxIn& vin, Optional<CKey>& key, CBLSSecretKey& blsKey);
// Get active masternode BLS operator keys for DMN
// Get active masternode BLS operator keys for DMN and vin OF THE COLLATERAL
// TODO: Remove after full transition to DMNs
bool GetActiveDMNKeys(CBLSSecretKey& key, CTxIn& vin);

// Compatibility code: get vin FOR VOTING and keys for either legacy or deterministic masternode
bool GetActiveMasternodeVotingKeys(CTxIn& vin, Optional<CKey>& key, CBLSSecretKey& blsKey);
// Get active masternode BLS operator keys for DMN and vin FOR VOTING
bool GetActiveVotingDMNKeys(CBLSSecretKey& key, CTxIn& vin);

#endif
26 changes: 19 additions & 7 deletions src/budget/budgetmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ void CBudgetManager::VoteOnFinalizedBudgets()
CTxIn mnVin;
Optional<CKey> mnKey{nullopt};
CBLSSecretKey blsKey;
if (!GetActiveMasternodeKeys(mnVin, mnKey, blsKey)) {
if (!GetActiveMasternodeVotingKeys(mnVin, mnKey, blsKey)) {
return;
}

Expand Down Expand Up @@ -885,8 +885,8 @@ void CBudgetManager::RemoveStaleVotesOnProposal(CBudgetProposal* prop)
auto it = prop->mapVotes.begin();
while (it != prop->mapVotes.end()) {
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMNByCollateral(it->first);
if (dmn) {
auto dmn = mnList.GetMN(it->first.hash);
if (dmn && it->first.n == 0) {
(*it).second.SetValid(!dmn->IsPoSeBanned());
} else {
// -- Legacy System (!TODO: remove after enforcement) --
Expand All @@ -909,8 +909,8 @@ void CBudgetManager::RemoveStaleVotesOnFinalBudget(CFinalizedBudget* fbud)
auto it = fbud->mapVotes.begin();
while (it != fbud->mapVotes.end()) {
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMNByCollateral(it->first);
if (dmn) {
auto dmn = mnList.GetMN(it->first.hash);
if (dmn && it->first.n == 0) {
(*it).second.SetValid(!dmn->IsPoSeBanned());
} else {
// -- Legacy System (!TODO: remove after enforcement) --
Expand Down Expand Up @@ -1101,10 +1101,16 @@ bool CBudgetManager::ProcessProposalVote(CBudgetVote& vote, CNode* pfrom, CValid

// See if this vote was signed with a deterministic masternode
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMNByCollateral(voteVin.prevout);
auto dmn = mnList.GetMN(voteVin.prevout.hash);
if (dmn) {
const std::string& mn_protx_id = dmn->proTxHash.ToString();

if (voteVin.prevout.n != 0) {
err = strprintf("masternode (%s) not valid prevout.n (0 != %d)", mn_protx_id, voteVin.prevout.n);
// TODO: ban the node in this case?
return state.DoS(0, false, REJECT_INVALID, "bad-prevout", false, err);
}

if (dmn->IsPoSeBanned()) {
err = strprintf("masternode (%s) not valid or PoSe banned", mn_protx_id);
return state.DoS(0, false, REJECT_INVALID, "bad-mvote", false, err);
Expand Down Expand Up @@ -1210,10 +1216,16 @@ bool CBudgetManager::ProcessFinalizedBudgetVote(CFinalizedBudgetVote& vote, CNod

// See if this vote was signed with a deterministic masternode
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMNByCollateral(voteVin.prevout);
auto dmn = mnList.GetMN(voteVin.prevout.hash);
if (dmn) {
const std::string& mn_protx_id = dmn->proTxHash.ToString();

if (voteVin.prevout.n != 0) {
err = strprintf("masternode (%s) not valid prevout.n (0 != %d)", mn_protx_id, voteVin.prevout.n);
// TODO: ban the node in this case?
return state.DoS(0, false, REJECT_INVALID, "bad-prevout", false, err);
}

if (dmn->IsPoSeBanned()) {
err = strprintf("masternode (%s) not valid or PoSe banned", mn_protx_id);
return state.DoS(0, false, REJECT_INVALID, "bad-fbvote", false, err);
Expand Down
32 changes: 15 additions & 17 deletions src/budget/budgetutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,18 @@ static UniValue packVoteReturnValue(const UniValue& details, int success, int fa
struct MnKeyData
{
std::string mnAlias;
const COutPoint* collateralOut;
const COutPoint collateralOut;

MnKeyData() = delete;
MnKeyData(const std::string& _mnAlias, const COutPoint* _collateralOut, const CKey& _key):
mnAlias(_mnAlias),
collateralOut(_collateralOut),
key(_key),
use_bls(false)
MnKeyData(const std::string& _mnAlias, const COutPoint _collateralOut, const CKey& _key) : mnAlias(_mnAlias),
collateralOut(_collateralOut),
key(_key),
use_bls(false)
{}
MnKeyData(const std::string& _mnAlias, const COutPoint* _collateralOut, const CBLSSecretKey& _key):
mnAlias(_mnAlias),
collateralOut(_collateralOut),
blsKey(_key),
use_bls(true)
MnKeyData(const std::string& _mnAlias, const COutPoint _collateralOut, const CBLSSecretKey& _key) : mnAlias(_mnAlias),
collateralOut(_collateralOut),
blsKey(_key),
use_bls(true)
{}

bool Sign(CSignedMessage* msg) const
Expand All @@ -75,7 +73,7 @@ static UniValue voteProposal(const uint256& propHash, const CBudgetVote::VoteDir
{
int success = 0;
for (const auto& k : mnKeys) {
CBudgetVote vote(CTxIn(*k.collateralOut), propHash, nVote);
CBudgetVote vote(CTxIn(k.collateralOut), propHash, nVote);
if (!k.Sign(&vote)) {
resultsObj.push_back(packErrorRetStatus(k.mnAlias, "Failure to sign."));
failed++;
Expand All @@ -99,7 +97,7 @@ static UniValue voteFinalBudget(const uint256& budgetHash,
{
int success = 0;
for (const auto& k : mnKeys) {
CFinalizedBudgetVote vote(CTxIn(*k.collateralOut), budgetHash);
CFinalizedBudgetVote vote(CTxIn(k.collateralOut), budgetHash);
if (!k.Sign(&vote)) {
resultsObj.push_back(packErrorRetStatus(k.mnAlias, "Failure to sign."));
failed++;
Expand Down Expand Up @@ -138,7 +136,7 @@ static mnKeyList getMNKeys(const Optional<std::string>& mnAliasFilter,
failed++;
continue;
}
mnKeys.emplace_back(mnAlias, &pmn->vin.prevout, mnKey);
mnKeys.emplace_back(mnAlias, pmn->vin.prevout, mnKey);
}
return mnKeys;
}
Expand All @@ -162,7 +160,7 @@ static mnKeyList getMNKeysForActiveMasternode(UniValue& resultsObj)
return mnKeyList();
}

return {MnKeyData("local", &pmn->vin.prevout, mnKey)};
return {MnKeyData("local", pmn->vin.prevout, mnKey)};
}

// Deterministic masternodes
Expand Down Expand Up @@ -198,7 +196,7 @@ static mnKeyList getDMNVotingKeys(CWallet* const pwallet, const Optional<std::st
LOCK(pwallet->cs_wallet);
CKey mnKey;
if (pwallet->GetKey(dmn->pdmnState->keyIDVoting, mnKey)) {
mnKeys.emplace_back(dmn->proTxHash.ToString(), &dmn->collateralOutpoint, mnKey);
mnKeys.emplace_back(dmn->proTxHash.ToString(), COutPoint(dmn->proTxHash, 0), mnKey);
} else if (filtered) {
resultsObj.push_back(packErrorRetStatus(*mnAliasFilter, strprintf(
"Private key for voting address %s not known by this wallet",
Expand Down Expand Up @@ -226,7 +224,7 @@ static mnKeyList getDMNKeysForActiveMasternode(UniValue& resultsObj)
return {};
}

return {MnKeyData("local", &dmn->collateralOutpoint, sk)};
return {MnKeyData("local", COutPoint(dmn->proTxHash, 0), sk)};
}

// vote on proposal (finalized budget, if fFinal=true) with all possible keys or a single mn (mnAliasFilter)
Expand Down
3 changes: 3 additions & 0 deletions src/budget/budgetvote.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class CBudgetVote : public CSignedMessage
uint256 nProposalHash;
VoteDirection nVote;
int64_t nTime;
// NOTE: SDMNs don't have a public collateral outpoint since they point to a shield note.
// Therefore from v6.0+ the prevout of the vin instead of being the masternode collateral outpoint will become the quantity Coutpoint(proRegTxHash, 0).
// Sadly to keep backward compatibility we cannot change this CTxIn to a more simple uint256.
CTxIn vin;

public:
Expand Down
3 changes: 3 additions & 0 deletions src/budget/finalizedbudgetvote.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class CFinalizedBudgetVote : public CSignedMessage
private:
bool fValid; //if the vote is currently valid / counted
bool fSynced; //if we've sent this to our peers
// NOTE: SDMNs don't have a public collateral outpoint since they point to a shield note.
// Therefore from v6.0+ the prevout of the vin instead of being the masternode collateral outpoint will become the quantity Coutpoint(proRegTxHash, 0).
// Sadly to keep backward compatibility we cannot change this CTxIn to a more simple uint256.
CTxIn vin;
uint256 nBudgetHash;
int64_t nTime;
Expand Down
Loading