Skip to content
Open
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