Multiple speed optimizations for deterministic MN list handling (#2972)
* Generalize CBLSLazyWrapper so that it can be used of pubkeys and secret keys * Implement == and != operators for CBLSLazyWrapper * Implement cached hash for CBLSLazyWrapper * Use CBLSLazyPublicKey for CDeterministicMNState::pubKeyOperator * Speed up GetProjectedMNPayees by sorting the MN list by last paid Instead of updating a temporary list for each projected height and calling GetMNPayee() on it. * Cache intermediate lists in GetListForBlock This avoids re-loading and applying diffs again and again. * Only update masternode list UI max once every 3 seconds This avoids updating the UI on every block, which turned out to be very expensive. * Fix compilation * Drop time restrictions for mn list update in ClientModel They are fully handled by MasternodeList now.
This commit is contained in:
parent
11699f540f
commit
c1f756fd90
@ -424,33 +424,6 @@ bool CBLSSignature::Recover(const std::vector<CBLSSignature>& sigs, const std::v
|
||||
}
|
||||
|
||||
#ifndef BUILD_BITCOIN_INTERNAL
|
||||
void CBLSLazySignature::SetSig(const CBLSSignature& _sig)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
bufValid = false;
|
||||
sigInitialized = true;
|
||||
sig = _sig;
|
||||
}
|
||||
|
||||
const CBLSSignature& CBLSLazySignature::GetSig() const
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
static CBLSSignature invalidSig;
|
||||
if (!bufValid && !sigInitialized) {
|
||||
return invalidSig;
|
||||
}
|
||||
if (!sigInitialized) {
|
||||
sig.SetBuf(buf, sizeof(buf));
|
||||
if (!sig.CheckMalleable(buf, sizeof(buf))) {
|
||||
bufValid = false;
|
||||
sigInitialized = false;
|
||||
sig = invalidSig;
|
||||
} else {
|
||||
sigInitialized = true;
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
static std::once_flag init_flag;
|
||||
static mt_pooled_secure_allocator<uint8_t>* secure_allocator_instance;
|
||||
|
107
src/bls/bls.h
107
src/bls/bls.h
@ -310,29 +310,34 @@ protected:
|
||||
};
|
||||
|
||||
#ifndef BUILD_BITCOIN_INTERNAL
|
||||
class CBLSLazySignature
|
||||
template<typename BLSObject>
|
||||
class CBLSLazyWrapper
|
||||
{
|
||||
private:
|
||||
mutable std::mutex mutex;
|
||||
|
||||
mutable char buf[BLS_CURVE_SIG_SIZE];
|
||||
mutable char buf[BLSObject::SerSize];
|
||||
mutable bool bufValid{false};
|
||||
|
||||
mutable CBLSSignature sig;
|
||||
mutable bool sigInitialized{false};
|
||||
mutable BLSObject obj;
|
||||
mutable bool objInitialized{false};
|
||||
|
||||
mutable uint256 hash;
|
||||
|
||||
public:
|
||||
CBLSLazySignature()
|
||||
CBLSLazyWrapper()
|
||||
{
|
||||
memset(buf, 0, sizeof(buf));
|
||||
// the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid
|
||||
bufValid = true;
|
||||
}
|
||||
|
||||
CBLSLazySignature(const CBLSLazySignature& r)
|
||||
CBLSLazyWrapper(const CBLSLazyWrapper& r)
|
||||
{
|
||||
*this = r;
|
||||
}
|
||||
|
||||
CBLSLazySignature& operator=(const CBLSLazySignature& r)
|
||||
CBLSLazyWrapper& operator=(const CBLSLazyWrapper& r)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(r.mutex);
|
||||
bufValid = r.bufValid;
|
||||
@ -341,12 +346,13 @@ public:
|
||||
} else {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
}
|
||||
sigInitialized = r.sigInitialized;
|
||||
if (r.sigInitialized) {
|
||||
sig = r.sig;
|
||||
objInitialized = r.objInitialized;
|
||||
if (r.objInitialized) {
|
||||
obj = r.obj;
|
||||
} else {
|
||||
sig.Reset();
|
||||
obj.Reset();
|
||||
}
|
||||
hash = r.hash;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -354,12 +360,13 @@ public:
|
||||
inline void Serialize(Stream& s) const
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
if (!sigInitialized && !bufValid) {
|
||||
throw std::ios_base::failure("sig and buf not initialized");
|
||||
if (!objInitialized && !bufValid) {
|
||||
throw std::ios_base::failure("obj and buf not initialized");
|
||||
}
|
||||
if (!bufValid) {
|
||||
sig.GetBuf(buf, sizeof(buf));
|
||||
obj.GetBuf(buf, sizeof(buf));
|
||||
bufValid = true;
|
||||
hash = uint256();
|
||||
}
|
||||
s.write(buf, sizeof(buf));
|
||||
}
|
||||
@ -370,12 +377,78 @@ public:
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
s.read(buf, sizeof(buf));
|
||||
bufValid = true;
|
||||
sigInitialized = false;
|
||||
objInitialized = false;
|
||||
hash = uint256();
|
||||
}
|
||||
|
||||
void SetSig(const CBLSSignature& _sig);
|
||||
const CBLSSignature& GetSig() const;
|
||||
void Set(const BLSObject& _obj)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
bufValid = false;
|
||||
objInitialized = true;
|
||||
obj = _obj;
|
||||
hash = uint256();
|
||||
}
|
||||
const BLSObject& Get() const
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
static BLSObject invalidObj;
|
||||
if (!bufValid && !objInitialized) {
|
||||
return invalidObj;
|
||||
}
|
||||
if (!objInitialized) {
|
||||
obj.SetBuf(buf, sizeof(buf));
|
||||
if (!obj.CheckMalleable(buf, sizeof(buf))) {
|
||||
bufValid = false;
|
||||
objInitialized = false;
|
||||
obj = invalidObj;
|
||||
} else {
|
||||
objInitialized = true;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool operator==(const CBLSLazyWrapper& r) const
|
||||
{
|
||||
if (bufValid && r.bufValid) {
|
||||
return memcmp(buf, r.buf, sizeof(buf)) == 0;
|
||||
}
|
||||
if (objInitialized && r.objInitialized) {
|
||||
return obj == r.obj;
|
||||
}
|
||||
return Get() == r.Get();
|
||||
}
|
||||
|
||||
bool operator!=(const CBLSLazyWrapper& r) const
|
||||
{
|
||||
return !(*this == r);
|
||||
}
|
||||
|
||||
uint256 GetHash() const
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutex);
|
||||
if (!bufValid) {
|
||||
obj.GetBuf(buf, sizeof(buf));
|
||||
bufValid = true;
|
||||
hash = uint256();
|
||||
}
|
||||
if (hash.IsNull()) {
|
||||
UpdateHash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
private:
|
||||
void UpdateHash() const
|
||||
{
|
||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||
ss.write(buf, sizeof(buf));
|
||||
hash = ss.GetHash();
|
||||
}
|
||||
};
|
||||
typedef CBLSLazyWrapper<CBLSSignature> CBLSLazySignature;
|
||||
typedef CBLSLazyWrapper<CBLSPublicKey> CBLSLazyPublicKey;
|
||||
typedef CBLSLazyWrapper<CBLSSecretKey> CBLSLazySecretKey;
|
||||
#endif
|
||||
|
||||
typedef std::vector<CBLSId> BLSIdVector;
|
||||
|
@ -38,7 +38,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,
|
||||
CBitcoinAddress(keyIDOwner).ToString(), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress);
|
||||
CBitcoinAddress(keyIDOwner).ToString(), pubKeyOperator.Get().ToString(), CBitcoinAddress(keyIDVoting).ToString(), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress);
|
||||
}
|
||||
|
||||
void CDeterministicMNState::ToJson(UniValue& obj) const
|
||||
@ -60,7 +60,7 @@ void CDeterministicMNState::ToJson(UniValue& obj) const
|
||||
CBitcoinAddress payoutAddress(dest);
|
||||
obj.push_back(Pair("payoutAddress", payoutAddress.ToString()));
|
||||
}
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.Get().ToString()));
|
||||
if (ExtractDestination(scriptOperatorPayout, dest)) {
|
||||
CBitcoinAddress operatorPayoutAddress(dest);
|
||||
obj.push_back(Pair("operatorPayoutAddress", operatorPayoutAddress.ToString()));
|
||||
@ -147,7 +147,7 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMN(const uint256& proTxHash)
|
||||
CDeterministicMNCPtr CDeterministicMNList::GetMNByOperatorKey(const CBLSPublicKey& pubKey)
|
||||
{
|
||||
for (const auto& p : mnMap) {
|
||||
if (p.second->pdmnState->pubKeyOperator == pubKey) {
|
||||
if (p.second->pdmnState->pubKeyOperator.Get() == pubKey) {
|
||||
return p.second;
|
||||
}
|
||||
}
|
||||
@ -226,21 +226,21 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNPayee() const
|
||||
|
||||
std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(int nCount) const
|
||||
{
|
||||
if (nCount > GetValidMNsCount()) {
|
||||
nCount = GetValidMNsCount();
|
||||
}
|
||||
|
||||
std::vector<CDeterministicMNCPtr> result;
|
||||
result.reserve(nCount);
|
||||
|
||||
CDeterministicMNList tmpMNList = *this;
|
||||
for (int h = nHeight; h < nHeight + nCount; h++) {
|
||||
tmpMNList.SetHeight(h);
|
||||
ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
|
||||
result.emplace_back(dmn);
|
||||
});
|
||||
std::sort(result.begin(), result.end(), [&](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) {
|
||||
return CompareByLastPaid(a, b);
|
||||
});
|
||||
|
||||
CDeterministicMNCPtr payee = tmpMNList.GetMNPayee();
|
||||
// push the original MN object instead of the one from the temporary list
|
||||
result.push_back(GetMN(payee->proTxHash));
|
||||
|
||||
CDeterministicMNStatePtr newState = std::make_shared<CDeterministicMNState>(*payee->pdmnState);
|
||||
newState->nLastPaidHeight = h;
|
||||
tmpMNList.UpdateMN(payee->proTxHash, newState);
|
||||
}
|
||||
result.resize(nCount);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -429,7 +429,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn)
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->addr);
|
||||
}
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->keyIDOwner);
|
||||
if (dmn->pdmnState->pubKeyOperator.IsValid()) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get().IsValid()) {
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator);
|
||||
}
|
||||
}
|
||||
@ -457,7 +457,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->addr);
|
||||
}
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->keyIDOwner);
|
||||
if (dmn->pdmnState->pubKeyOperator.IsValid()) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get().IsValid()) {
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator);
|
||||
}
|
||||
mnMap = mnMap.erase(proTxHash);
|
||||
@ -701,7 +701,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
|
||||
|
||||
if (newState->nPoSeBanHeight != -1) {
|
||||
// only revive when all keys are set
|
||||
if (newState->pubKeyOperator.IsValid() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) {
|
||||
if (newState->pubKeyOperator.Get().IsValid() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) {
|
||||
newState->nPoSePenalty = 0;
|
||||
newState->nPoSeBanHeight = -1;
|
||||
newState->nPoSeRevivedHeight = nHeight;
|
||||
@ -729,12 +729,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
|
||||
return _state.DoS(100, false, REJECT_INVALID, "bad-protx-hash");
|
||||
}
|
||||
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
|
||||
if (newState->pubKeyOperator != proTx.pubKeyOperator) {
|
||||
if (newState->pubKeyOperator.Get() != proTx.pubKeyOperator) {
|
||||
// reset all operator related fields and put MN into PoSe-banned state in case the operator key changes
|
||||
newState->ResetOperatorFields();
|
||||
newState->BanIfNotBanned(nHeight);
|
||||
}
|
||||
newState->pubKeyOperator = proTx.pubKeyOperator;
|
||||
newState->pubKeyOperator.Set(proTx.pubKeyOperator);
|
||||
newState->keyIDVoting = proTx.keyIDVoting;
|
||||
newState->scriptPayout = proTx.scriptPayout;
|
||||
|
||||
@ -866,12 +866,14 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blo
|
||||
}
|
||||
|
||||
if (evoDb.Read(std::make_pair(DB_LIST_SNAPSHOT, blockHashTmp), snapshot)) {
|
||||
mnListsCache.emplace(blockHashTmp, snapshot);
|
||||
break;
|
||||
}
|
||||
|
||||
CDeterministicMNListDiff diff;
|
||||
if (!evoDb.Read(std::make_pair(DB_LIST_DIFF, blockHashTmp), diff)) {
|
||||
snapshot = CDeterministicMNList(blockHashTmp, -1);
|
||||
mnListsCache.emplace(blockHashTmp, snapshot);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -886,9 +888,10 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blo
|
||||
snapshot.SetBlockHash(diff.blockHash);
|
||||
snapshot.SetHeight(diff.nHeight);
|
||||
}
|
||||
|
||||
mnListsCache.emplace(diff.blockHash, snapshot);
|
||||
}
|
||||
|
||||
mnListsCache.emplace(blockHash, snapshot);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
uint256 confirmedHashWithProRegTxHash;
|
||||
|
||||
CKeyID keyIDOwner;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CBLSLazyPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
CService addr;
|
||||
CScript scriptPayout;
|
||||
@ -55,7 +55,7 @@ public:
|
||||
CDeterministicMNState(const CProRegTx& proTx)
|
||||
{
|
||||
keyIDOwner = proTx.keyIDOwner;
|
||||
pubKeyOperator = proTx.pubKeyOperator;
|
||||
pubKeyOperator.Set(proTx.pubKeyOperator);
|
||||
keyIDVoting = proTx.keyIDVoting;
|
||||
addr = proTx.addr;
|
||||
scriptPayout = proTx.scriptPayout;
|
||||
@ -89,7 +89,7 @@ public:
|
||||
|
||||
void ResetOperatorFields()
|
||||
{
|
||||
pubKeyOperator = CBLSPublicKey();
|
||||
pubKeyOperator.Set(CBLSPublicKey());
|
||||
addr = CService();
|
||||
scriptOperatorPayout = CScript();
|
||||
nRevocationReason = CProUpRevTx::REASON_NOT_SPECIFIED;
|
||||
|
@ -89,7 +89,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS
|
||||
signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->sentMNAuthChallenge, !pnode->fInbound));
|
||||
}
|
||||
|
||||
if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, signHash)) {
|
||||
if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) {
|
||||
LOCK(cs_main);
|
||||
// Same as above, MN seems to not know about his fate yet, so give him a chance to update. If this is a
|
||||
// malicious actor (DoSing us), we'll ban him soon.
|
||||
|
@ -257,7 +257,7 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
|
||||
if (!CheckInputsHash(tx, ptx, state)) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckHashSig(ptx, mn->pdmnState->pubKeyOperator, state)) {
|
||||
if (!CheckHashSig(ptx, mn->pdmnState->pubKeyOperator.Get(), state)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -376,7 +376,7 @@ bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
|
||||
|
||||
if (!CheckInputsHash(tx, ptx, state))
|
||||
return false;
|
||||
if (!CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator, state))
|
||||
if (!CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator.Get(), state))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ uint256 CSimplifiedMNListEntry::CalcHash() const
|
||||
std::string CSimplifiedMNListEntry::ToString() const
|
||||
{
|
||||
return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d)",
|
||||
proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid);
|
||||
proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.Get().ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid);
|
||||
}
|
||||
|
||||
void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
|
||||
@ -47,7 +47,7 @@ void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
|
||||
obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString()));
|
||||
obj.push_back(Pair("confirmedHash", confirmedHash.ToString()));
|
||||
obj.push_back(Pair("service", service.ToString(false)));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.Get().ToString()));
|
||||
obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString()));
|
||||
obj.push_back(Pair("isValid", isValid));
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
uint256 proRegTxHash;
|
||||
uint256 confirmedHash;
|
||||
CService service;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CBLSLazyPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
bool isValid;
|
||||
|
||||
|
@ -500,8 +500,8 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
|
||||
}
|
||||
|
||||
// Check that we have a valid MN signature
|
||||
if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.ToString();
|
||||
if (!CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.Get().ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const
|
||||
if (useVotingKey) {
|
||||
return CheckSignature(dmn->pdmnState->keyIDVoting);
|
||||
} else {
|
||||
return CheckSignature(dmn->pdmnState->pubKeyOperator);
|
||||
return CheckSignature(dmn->pdmnState->pubKeyOperator.Get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1123,7 @@ bool CTxLockVote::CheckSignature() const
|
||||
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchMasternodeSignature);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, hash)) {
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recove
|
||||
|
||||
clsig.nHeight = lastSignedHeight;
|
||||
clsig.blockHash = lastSignedMsgHash;
|
||||
clsig.sig = recoveredSig.sig.GetSig();
|
||||
clsig.sig = recoveredSig.sig.Get();
|
||||
}
|
||||
ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig));
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ bool CFinalCommitment::Verify(const std::vector<CDeterministicMNCPtr>& members,
|
||||
if (!signers[i]) {
|
||||
continue;
|
||||
}
|
||||
memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator);
|
||||
memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator.Get());
|
||||
}
|
||||
|
||||
if (!membersSig.VerifySecureAggregated(memberPubKeys, commitmentHash)) {
|
||||
|
@ -187,7 +187,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages)
|
||||
skContrib.MakeNewKey();
|
||||
}
|
||||
|
||||
if (!qc.contributions->Encrypt(i, m->dmn->pdmnState->pubKeyOperator, skContrib, PROTOCOL_VERSION)) {
|
||||
if (!qc.contributions->Encrypt(i, m->dmn->pdmnState->pubKeyOperator.Get(), skContrib, PROTOCOL_VERSION)) {
|
||||
logger.Batch("failed to encrypt contribution for %s", m->dmn->proTxHash.ToString());
|
||||
return;
|
||||
}
|
||||
@ -1219,7 +1219,7 @@ std::vector<CFinalCommitment> CDKGSession::FinalizeCommitments()
|
||||
|
||||
fqc.signers[signerIndex] = true;
|
||||
aggSigs.emplace_back(qc.sig);
|
||||
aggPks.emplace_back(m->dmn->pdmnState->pubKeyOperator);
|
||||
aggPks.emplace_back(m->dmn->pdmnState->pubKeyOperator.Get());
|
||||
|
||||
signerIds.emplace_back(m->id);
|
||||
thresholdSigs.emplace_back(qc.quorumSig);
|
||||
|
@ -313,7 +313,7 @@ std::set<NodeId> BatchVerifyMessageSigs(CDKGSession& session, const std::vector<
|
||||
break;
|
||||
}
|
||||
|
||||
pubKeys.emplace_back(member->dmn->pdmnState->pubKeyOperator);
|
||||
pubKeys.emplace_back(member->dmn->pdmnState->pubKeyOperator.Get());
|
||||
messageHashes.emplace_back(msgHash);
|
||||
}
|
||||
if (!revertToSingleVerification) {
|
||||
@ -353,7 +353,7 @@ std::set<NodeId> BatchVerifyMessageSigs(CDKGSession& session, const std::vector<
|
||||
|
||||
const auto& msg = *p.second;
|
||||
auto member = session.GetMember(msg.proTxHash);
|
||||
bool valid = msg.sig.VerifyInsecure(member->dmn->pdmnState->pubKeyOperator, msg.GetSignHash());
|
||||
bool valid = msg.sig.VerifyInsecure(member->dmn->pdmnState->pubKeyOperator.Get(), msg.GetSignHash());
|
||||
if (!valid) {
|
||||
ret.emplace(p.first);
|
||||
}
|
||||
|
@ -747,7 +747,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!islock.sig.GetSig().IsValid()) {
|
||||
if (!islock.sig.Get().IsValid()) {
|
||||
batchVerifier.badSources.emplace(nodeId);
|
||||
continue;
|
||||
}
|
||||
@ -765,7 +765,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks()
|
||||
return false;
|
||||
}
|
||||
uint256 signHash = CLLMQUtils::BuildSignHash(llmqType, quorum->qc.quorumHash, id, islock.txid);
|
||||
batchVerifier.PushMessage(nodeId, hash, signHash, islock.sig.GetSig(), quorum->qc.quorumPublicKey);
|
||||
batchVerifier.PushMessage(nodeId, hash, signHash, islock.sig.Get(), quorum->qc.quorumPublicKey);
|
||||
|
||||
// We can reconstruct the CRecoveredSig objects from the islock and pass it to the signing manager, which
|
||||
// avoids unnecessary double-verification of the signature. We however only do this when verification here
|
||||
|
@ -31,8 +31,8 @@ UniValue CRecoveredSig::ToJson() const
|
||||
ret.push_back(Pair("quorumHash", quorumHash.ToString()));
|
||||
ret.push_back(Pair("id", id.ToString()));
|
||||
ret.push_back(Pair("msgHash", msgHash.ToString()));
|
||||
ret.push_back(Pair("sig", sig.GetSig().ToString()));
|
||||
ret.push_back(Pair("hash", sig.GetSig().GetHash().ToString()));
|
||||
ret.push_back(Pair("sig", sig.Get().ToString()));
|
||||
ret.push_back(Pair("hash", sig.Get().GetHash().ToString()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -575,13 +575,13 @@ bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman)
|
||||
|
||||
for (auto& recSig : v) {
|
||||
// we didn't verify the lazy signature until now
|
||||
if (!recSig.sig.GetSig().IsValid()) {
|
||||
if (!recSig.sig.Get().IsValid()) {
|
||||
batchVerifier.badSources.emplace(nodeId);
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& quorum = quorums.at(std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.quorumHash));
|
||||
batchVerifier.PushMessage(nodeId, recSig.GetHash(), CLLMQUtils::BuildSignHash(recSig), recSig.sig.GetSig(), quorum->qc.quorumPublicKey);
|
||||
batchVerifier.PushMessage(nodeId, recSig.GetHash(), CLLMQUtils::BuildSignHash(recSig), recSig.sig.Get(), quorum->qc.quorumPublicKey);
|
||||
verifyCount++;
|
||||
}
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman)
|
||||
|
||||
// we didn't check this earlier because we use a lazy BLS signature and tried to avoid doing the expensive
|
||||
// deserialization in the message thread
|
||||
if (!sigShare.sigShare.GetSig().IsValid()) {
|
||||
if (!sigShare.sigShare.Get().IsValid()) {
|
||||
BanNode(nodeId);
|
||||
// don't process any additional shares from this node
|
||||
break;
|
||||
@ -605,7 +605,7 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare.GetSig(), pubKeyShare);
|
||||
batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare.Get(), pubKeyShare);
|
||||
verifyCount++;
|
||||
}
|
||||
}
|
||||
@ -735,7 +735,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256&
|
||||
idsForRecovery.reserve((size_t) quorum->params.threshold);
|
||||
for (auto it = sigShares->begin(); it != sigShares->end() && sigSharesForRecovery.size() < quorum->params.threshold; ++it) {
|
||||
auto& sigShare = it->second;
|
||||
sigSharesForRecovery.emplace_back(sigShare.sigShare.GetSig());
|
||||
sigSharesForRecovery.emplace_back(sigShare.sigShare.Get());
|
||||
idsForRecovery.emplace_back(CBLSId::FromHash(quorum->members[sigShare.quorumMember]->proTxHash));
|
||||
}
|
||||
|
||||
@ -762,7 +762,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256&
|
||||
rs.quorumHash = quorum->qc.quorumHash;
|
||||
rs.id = id;
|
||||
rs.msgHash = msgHash;
|
||||
rs.sig.SetSig(recoveredSig);
|
||||
rs.sig.Set(recoveredSig);
|
||||
rs.UpdateHash();
|
||||
|
||||
// There should actually be no need to verify the self-recovered signatures as it should always succeed. Let's
|
||||
@ -1422,8 +1422,8 @@ void CSigSharesManager::Sign(const CQuorumCPtr& quorum, const uint256& id, const
|
||||
sigShare.quorumMember = (uint16_t)memberIdx;
|
||||
uint256 signHash = CLLMQUtils::BuildSignHash(sigShare);
|
||||
|
||||
sigShare.sigShare.SetSig(skShare.Sign(signHash));
|
||||
if (!sigShare.sigShare.GetSig().IsValid()) {
|
||||
sigShare.sigShare.Set(skShare.Sign(signHash));
|
||||
if (!sigShare.sigShare.Get().IsValid()) {
|
||||
LogPrintf("CSigSharesManager::%s -- failed to sign sigShare. signHash=%s, id=%s, msgHash=%s, time=%s\n", __func__,
|
||||
signHash.ToString(), sigShare.id.ToString(), sigShare.msgHash.ToString(), t.count());
|
||||
return;
|
||||
|
@ -2174,7 +2174,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
// we have no idea about (e.g we were offline)? How to handle them?
|
||||
}
|
||||
|
||||
if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString());
|
||||
return false;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
if (!dmn) return;
|
||||
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->id, 10);
|
||||
return;
|
||||
|
@ -121,7 +121,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
if (!dmn) return;
|
||||
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) {
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->id, 10);
|
||||
return;
|
||||
|
@ -355,14 +355,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB
|
||||
|
||||
static void NotifyMasternodeListChanged(ClientModel *clientmodel, const CDeterministicMNList& newList)
|
||||
{
|
||||
static int64_t nLastMasternodeUpdateNotification = 0;
|
||||
int64_t now = GetTimeMillis();
|
||||
// if we are in-sync, update the UI regardless of last update time
|
||||
// no need to refresh masternode list/stats as often as blocks etc.
|
||||
if (masternodeSync.IsBlockchainSynced() || now - nLastMasternodeUpdateNotification > MODEL_UPDATE_DELAY*4*5) {
|
||||
clientmodel->setMasternodeList(newList);
|
||||
nLastMasternodeUpdateNotification = now;
|
||||
}
|
||||
clientmodel->setMasternodeList(newList);
|
||||
}
|
||||
|
||||
static void NotifyAdditionalDataSyncProgressChanged(ClientModel *clientmodel, double nSyncProgress)
|
||||
|
@ -35,7 +35,9 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
|
||||
clientModel(0),
|
||||
walletModel(0),
|
||||
fFilterUpdatedDIP3(true),
|
||||
nTimeFilterUpdatedDIP3(0)
|
||||
nTimeFilterUpdatedDIP3(0),
|
||||
nTimeUpdatedDIP3(0),
|
||||
mnListChanged(true)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -89,7 +91,7 @@ void MasternodeList::setClientModel(ClientModel* model)
|
||||
this->clientModel = model;
|
||||
if (model) {
|
||||
// try to update list when masternode count changes
|
||||
connect(clientModel, SIGNAL(masternodeListChanged()), this, SLOT(updateDIP3ListForced()));
|
||||
connect(clientModel, SIGNAL(masternodeListChanged()), this, SLOT(handleMasternodeListChanged()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,37 +106,48 @@ void MasternodeList::showContextMenuDIP3(const QPoint& point)
|
||||
if (item) contextMenuDIP3->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void MasternodeList::handleMasternodeListChanged()
|
||||
{
|
||||
LOCK(cs_dip3list);
|
||||
mnListChanged = true;
|
||||
}
|
||||
|
||||
void MasternodeList::updateDIP3ListScheduled()
|
||||
{
|
||||
updateDIP3List(false);
|
||||
TRY_LOCK(cs_dip3list, fLockAcquired);
|
||||
if (!fLockAcquired) return;
|
||||
|
||||
if (!clientModel || ShutdownRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// To prevent high cpu usage update only once in MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds
|
||||
// after filter was last changed unless we want to force the update.
|
||||
if (fFilterUpdatedDIP3) {
|
||||
int64_t nSecondsToWait = nTimeFilterUpdatedDIP3 - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS;
|
||||
ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
|
||||
|
||||
if (nSecondsToWait <= 0) {
|
||||
updateDIP3List();
|
||||
fFilterUpdatedDIP3 = false;
|
||||
}
|
||||
} else if (mnListChanged) {
|
||||
int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
|
||||
|
||||
if (nSecondsToWait <= 0) {
|
||||
updateDIP3List();
|
||||
mnListChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MasternodeList::updateDIP3ListForced()
|
||||
{
|
||||
updateDIP3List(true);
|
||||
}
|
||||
|
||||
void MasternodeList::updateDIP3List(bool fForce)
|
||||
void MasternodeList::updateDIP3List()
|
||||
{
|
||||
if (!clientModel || ShutdownRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRY_LOCK(cs_dip3list, fLockAcquired);
|
||||
if (!fLockAcquired) return;
|
||||
|
||||
// To prevent high cpu usage update only once in MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds
|
||||
// after filter was last changed unless we want to force the update.
|
||||
if (!fForce) {
|
||||
if (!fFilterUpdatedDIP3) return;
|
||||
|
||||
int64_t nSecondsToWait = nTimeFilterUpdatedDIP3 - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS;
|
||||
ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
|
||||
|
||||
if (nSecondsToWait > 0) return;
|
||||
}
|
||||
|
||||
fFilterUpdatedDIP3 = false;
|
||||
LOCK(cs_dip3list);
|
||||
|
||||
QString strToFilter;
|
||||
ui->countLabelDIP3->setText("Updating...");
|
||||
@ -143,6 +156,8 @@ void MasternodeList::updateDIP3List(bool fForce)
|
||||
ui->tableWidgetMasternodesDIP3->setRowCount(0);
|
||||
|
||||
auto mnList = clientModel->getMasternodeList();
|
||||
nTimeUpdatedDIP3 = GetTime();
|
||||
|
||||
auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount());
|
||||
std::map<uint256, int> nextPayments;
|
||||
for (size_t i = 0; i < projectedPayees.size(); i++) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#define MASTERNODELIST_UPDATE_SECONDS 15
|
||||
#define MASTERNODELIST_UPDATE_SECONDS 3
|
||||
#define MASTERNODELIST_FILTER_COOLDOWN_SECONDS 3
|
||||
|
||||
namespace Ui
|
||||
@ -42,6 +42,7 @@ public:
|
||||
private:
|
||||
QMenu* contextMenuDIP3;
|
||||
int64_t nTimeFilterUpdatedDIP3;
|
||||
int64_t nTimeUpdatedDIP3;
|
||||
bool fFilterUpdatedDIP3;
|
||||
|
||||
QTimer* timer;
|
||||
@ -54,9 +55,11 @@ private:
|
||||
|
||||
QString strCurrentFilterDIP3;
|
||||
|
||||
bool mnListChanged;
|
||||
|
||||
CDeterministicMNCPtr GetSelectedDIP3MN();
|
||||
|
||||
void updateDIP3List(bool fForce);
|
||||
void updateDIP3List();
|
||||
|
||||
Q_SIGNALS:
|
||||
void doubleClicked(const QModelIndex&);
|
||||
@ -70,7 +73,7 @@ private Q_SLOTS:
|
||||
void copyProTxHash_clicked();
|
||||
void copyCollateralOutpoint_clicked();
|
||||
|
||||
void handleMasternodeListChanged();
|
||||
void updateDIP3ListScheduled();
|
||||
void updateDIP3ListForced();
|
||||
};
|
||||
#endif // MASTERNODELIST_H
|
||||
|
@ -574,7 +574,7 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString() << " " <<
|
||||
CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString() << " " <<
|
||||
collateralAddressStr << " " <<
|
||||
dmn->pdmnState->pubKeyOperator.ToString();
|
||||
dmn->pdmnState->pubKeyOperator.Get().ToString();
|
||||
std::string strInfo = streamInfo.str();
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
@ -588,7 +588,7 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
objMN.push_back(Pair("owneraddress", CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString()));
|
||||
objMN.push_back(Pair("votingaddress", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
|
||||
objMN.push_back(Pair("collateraladdress", collateralAddressStr));
|
||||
objMN.push_back(Pair("pubkeyoperator", dmn->pdmnState->pubKeyOperator.ToString()));
|
||||
objMN.push_back(Pair("pubkeyoperator", dmn->pdmnState->pubKeyOperator.Get().ToString()));
|
||||
obj.push_back(Pair(strOutpoint, objMN));
|
||||
} else if (strMode == "lastpaidblock") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
@ -605,7 +605,7 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
obj.push_back(Pair(strOutpoint, CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString()));
|
||||
} else if (strMode == "pubkeyoperator") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.Get().ToString()));
|
||||
} else if (strMode == "status") {
|
||||
std::string strStatus = dmnToStatus(dmn);
|
||||
if (strFilter !="" && strStatus.find(strFilter) == std::string::npos &&
|
||||
|
@ -623,7 +623,7 @@ UniValue protx_update_service(const JSONRPCRequest& request)
|
||||
throw std::runtime_error(strprintf("masternode with proTxHash %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) {
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
|
||||
}
|
||||
|
||||
@ -713,7 +713,7 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
|
||||
if (!dmn) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator;
|
||||
ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator.Get();
|
||||
ptx.keyIDVoting = dmn->pdmnState->keyIDVoting;
|
||||
ptx.scriptPayout = dmn->pdmnState->scriptPayout;
|
||||
|
||||
@ -808,7 +808,7 @@ UniValue protx_revoke(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) {
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots)
|
||||
CBLSSecretKey sk;
|
||||
sk.SetBuf(skBuf, sizeof(skBuf));
|
||||
|
||||
smle.pubKeyOperator = sk.GetPublicKey();
|
||||
smle.pubKeyOperator.Set(sk.GetPublicKey());
|
||||
smle.keyIDVoting.SetHex(strprintf("%040x", i));
|
||||
smle.isValid = true;
|
||||
|
||||
|
@ -459,7 +459,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(proTx.proTxHash);
|
||||
assert(dmn);
|
||||
newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator);
|
||||
if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get() != proTx.pubKeyOperator) {
|
||||
newit->isKeyChangeProTx = true;
|
||||
}
|
||||
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
|
||||
@ -470,7 +470,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(proTx.proTxHash);
|
||||
assert(dmn);
|
||||
newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator);
|
||||
if (dmn->pdmnState->pubKeyOperator != CBLSPublicKey()) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) {
|
||||
newit->isKeyChangeProTx = true;
|
||||
}
|
||||
}
|
||||
@ -1294,7 +1294,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
|
||||
return true; // i.e. failed to find validated ProTx == conflict
|
||||
}
|
||||
// only allow one operator key change in the mempool
|
||||
if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get() != proTx.pubKeyOperator) {
|
||||
if (hasKeyChangeInMempool(proTx.proTxHash)) {
|
||||
return true;
|
||||
}
|
||||
@ -1316,7 +1316,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
|
||||
return true; // i.e. failed to find validated ProTx == conflict
|
||||
}
|
||||
// only allow one operator key change in the mempool
|
||||
if (dmn->pdmnState->pubKeyOperator != CBLSPublicKey()) {
|
||||
if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) {
|
||||
if (hasKeyChangeInMempool(proTx.proTxHash)) {
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user