Merge #1267: Fix IS locking/crashes
This commit is contained in:
parent
f81ea67a08
commit
b5239b790e
@ -59,6 +59,7 @@ void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStrea
|
|||||||
CTxLockVote vote;
|
CTxLockVote vote;
|
||||||
vRecv >> vote;
|
vRecv >> vote;
|
||||||
|
|
||||||
|
LOCK2(cs_main, cs_instantsend);
|
||||||
if(mapTxLockVotes.count(vote.GetHash())) return;
|
if(mapTxLockVotes.count(vote.GetHash())) return;
|
||||||
mapTxLockVotes.insert(std::make_pair(vote.GetHash(), vote));
|
mapTxLockVotes.insert(std::make_pair(vote.GetHash(), vote));
|
||||||
|
|
||||||
@ -138,6 +139,7 @@ bool ProcessTxLockRequest(CNode* pfrom, const CTransaction &tx)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCK2(cs_main, cs_instantsend);
|
||||||
uint256 txHash = tx.GetHash();
|
uint256 txHash = tx.GetHash();
|
||||||
mapLockRequestAccepted.insert(std::make_pair(txHash, tx));
|
mapLockRequestAccepted.insert(std::make_pair(txHash, tx));
|
||||||
|
|
||||||
@ -187,6 +189,7 @@ int64_t CreateTxLockCandidate(const CTransaction& tx)
|
|||||||
|
|
||||||
uint256 txHash = tx.GetHash();
|
uint256 txHash = tx.GetHash();
|
||||||
|
|
||||||
|
LOCK(cs_instantsend);
|
||||||
if(!mapTxLockCandidates.count(txHash)) {
|
if(!mapTxLockCandidates.count(txHash)) {
|
||||||
LogPrintf("CreateTxLockCandidate -- New Transaction Lock Candidate! txid=%s\n", txHash.ToString());
|
LogPrintf("CreateTxLockCandidate -- New Transaction Lock Candidate! txid=%s\n", txHash.ToString());
|
||||||
|
|
||||||
@ -252,6 +255,7 @@ void CreateTxLockVote(const CTransaction& tx, int nBlockHeight)
|
|||||||
//received a consensus vote
|
//received a consensus vote
|
||||||
bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
// Masternodes will sometimes propagate votes before the transaction is known to the client,
|
// Masternodes will sometimes propagate votes before the transaction is known to the client,
|
||||||
// will actually process only after the lock request itself has arrived
|
// will actually process only after the lock request itself has arrived
|
||||||
if(!mapLockRequestAccepted.count(vote.txHash)) {
|
if(!mapLockRequestAccepted.count(vote.txHash)) {
|
||||||
@ -351,6 +355,7 @@ bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
|||||||
|
|
||||||
void ProcessOrphanTxLockVotes()
|
void ProcessOrphanTxLockVotes()
|
||||||
{
|
{
|
||||||
|
LOCK2(cs_main, cs_instantsend);
|
||||||
std::map<uint256, CTxLockVote>::iterator it = mapTxLockVotesOrphan.begin();
|
std::map<uint256, CTxLockVote>::iterator it = mapTxLockVotesOrphan.begin();
|
||||||
while(it != mapTxLockVotesOrphan.end()) {
|
while(it != mapTxLockVotesOrphan.end()) {
|
||||||
if(ProcessTxLockVote(NULL, it->second)) {
|
if(ProcessTxLockVote(NULL, it->second)) {
|
||||||
@ -363,6 +368,7 @@ void ProcessOrphanTxLockVotes()
|
|||||||
|
|
||||||
void UpdateLockedTransaction(const CTransaction& tx, bool fForceNotification)
|
void UpdateLockedTransaction(const CTransaction& tx, bool fForceNotification)
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
// there should be no conflicting locks
|
// there should be no conflicting locks
|
||||||
if(FindConflictingLocks(tx)) return;
|
if(FindConflictingLocks(tx)) return;
|
||||||
uint256 txHash = tx.GetHash();
|
uint256 txHash = tx.GetHash();
|
||||||
@ -392,6 +398,7 @@ void UpdateLockedTransaction(const CTransaction& tx, bool fForceNotification)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LockTransactionInputs(const CTransaction& tx) {
|
void LockTransactionInputs(const CTransaction& tx) {
|
||||||
|
LOCK(cs_instantsend);
|
||||||
if(!mapLockRequestAccepted.count(tx.GetHash())) return;
|
if(!mapLockRequestAccepted.count(tx.GetHash())) return;
|
||||||
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
@ -401,6 +408,7 @@ void LockTransactionInputs(const CTransaction& tx) {
|
|||||||
|
|
||||||
bool FindConflictingLocks(const CTransaction& tx)
|
bool FindConflictingLocks(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
/*
|
/*
|
||||||
It's possible (very unlikely though) to get 2 conflicting transaction locks approved by the network.
|
It's possible (very unlikely though) to get 2 conflicting transaction locks approved by the network.
|
||||||
In that case, they will cancel each other out.
|
In that case, they will cancel each other out.
|
||||||
@ -430,6 +438,7 @@ bool FindConflictingLocks(const CTransaction& tx)
|
|||||||
|
|
||||||
void ResolveConflicts(const CTransaction& tx)
|
void ResolveConflicts(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
uint256 txHash = tx.GetHash();
|
uint256 txHash = tx.GetHash();
|
||||||
// resolve conflicts
|
// resolve conflicts
|
||||||
if (IsLockedInstandSendTransaction(txHash) && !FindConflictingLocks(tx)) { //?????
|
if (IsLockedInstandSendTransaction(txHash) && !FindConflictingLocks(tx)) { //?????
|
||||||
@ -444,6 +453,7 @@ void ResolveConflicts(const CTransaction& tx)
|
|||||||
|
|
||||||
int64_t GetAverageMasternodeOrphanVoteTime()
|
int64_t GetAverageMasternodeOrphanVoteTime()
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
// NOTE: should never actually call this function when mapMasternodeOrphanVotes is empty
|
// NOTE: should never actually call this function when mapMasternodeOrphanVotes is empty
|
||||||
if(mapMasternodeOrphanVotes.empty()) return 0;
|
if(mapMasternodeOrphanVotes.empty()) return 0;
|
||||||
|
|
||||||
@ -520,6 +530,7 @@ void CleanTxLockCandidates()
|
|||||||
|
|
||||||
bool IsLockedInstandSendTransaction(const uint256 &txHash)
|
bool IsLockedInstandSendTransaction(const uint256 &txHash)
|
||||||
{
|
{
|
||||||
|
LOCK(cs_instantsend);
|
||||||
// there must be a successfully verified lock request...
|
// there must be a successfully verified lock request...
|
||||||
if (!mapLockRequestAccepted.count(txHash)) return false;
|
if (!mapLockRequestAccepted.count(txHash)) return false;
|
||||||
// ...and corresponding lock must have enough signatures
|
// ...and corresponding lock must have enough signatures
|
||||||
@ -532,6 +543,7 @@ int GetTransactionLockSignatures(const uint256 &txHash)
|
|||||||
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
|
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
|
||||||
if(!sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED)) return -3;
|
if(!sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED)) return -3;
|
||||||
|
|
||||||
|
LOCK(cs_instantsend);
|
||||||
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.find(txHash);
|
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.find(txHash);
|
||||||
if(it != mapTxLockCandidates.end()) return it->second.CountVotes();
|
if(it != mapTxLockCandidates.end()) return it->second.CountVotes();
|
||||||
|
|
||||||
@ -542,6 +554,7 @@ bool IsTransactionLockTimedOut(const uint256 &txHash)
|
|||||||
{
|
{
|
||||||
if(!fEnableInstantSend) return 0;
|
if(!fEnableInstantSend) return 0;
|
||||||
|
|
||||||
|
LOCK(cs_instantsend);
|
||||||
std::map<uint256, CTxLockCandidate>::iterator i = mapTxLockCandidates.find(txHash);
|
std::map<uint256, CTxLockCandidate>::iterator i = mapTxLockCandidates.find(txHash);
|
||||||
if (i != mapTxLockCandidates.end()) return GetTime() > (*i).second.nTimeout;
|
if (i != mapTxLockCandidates.end()) return GetTime() > (*i).second.nTimeout;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user