cancel out conflicting locks

This commit is contained in:
Evan Duffield 2015-02-05 09:48:57 -07:00
parent c3b92a7103
commit 97d73a72b5
3 changed files with 53 additions and 28 deletions

View File

@ -104,11 +104,13 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
if (i != mapTxLocks.end()){
//we only care if we have a complete tx lock
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
LogPrintf("ProcessMessageInstantX::txlreq - Found Existing Complete IX Lock\n");
if(!CheckForConflictingLocks(tx)){
LogPrintf("ProcessMessageInstantX::txlreq - Found Existing Complete IX Lock\n");
CValidationState state;
DisconnectBlockAndInputs(state, tx);
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
CValidationState state;
DisconnectBlockAndInputs(state, tx);
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
}
}
}
@ -229,7 +231,7 @@ int64_t CreateNewLock(CTransaction tx)
CTransactionLock newLock;
newLock.nBlockHeight = nBlockHeight;
newLock.nExpiration = GetTime()+(60*60);
newLock.nExpiration = GetTime()+(60*15); //locks expire after 15 minutes (6 confirmations)
newLock.nTimeout = GetTime()+(60*5);
newLock.txHash = tx.GetHash();
mapTxLocks.insert(make_pair(tx.GetHash(), newLock));
@ -318,29 +320,32 @@ bool ProcessConsensusVote(CConsensusVote& ctx)
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
if(fDebug) LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", (*i).second.GetHash().ToString().c_str());
#ifdef ENABLE_WALLET
if(pwalletMain){
if(pwalletMain->UpdatedTransaction((*i).second.txHash)){
nCompleteTXLocks++;
}
}
#endif
CTransaction& tx = mapTxLockReq[ctx.txHash];
if(!CheckForConflictingLocks(tx)){
if(mapTxLockReq.count(ctx.txHash)){
CTransaction& tx = mapTxLockReq[ctx.txHash];
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(!mapLockedInputs.count(in.prevout)){
mapLockedInputs.insert(make_pair(in.prevout, ctx.txHash));
#ifdef ENABLE_WALLET
if(pwalletMain){
if(pwalletMain->UpdatedTransaction((*i).second.txHash)){
nCompleteTXLocks++;
}
}
}
#endif
// resolve conflicts
if(mapTxLockReq.count(ctx.txHash)){
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(!mapLockedInputs.count(in.prevout)){
mapLockedInputs.insert(make_pair(in.prevout, ctx.txHash));
}
}
}
//if this tx lock was rejected, we need to remove the conflicting blocks
if(mapTxLockReqRejected.count((*i).second.txHash)){
CValidationState state;
DisconnectBlockAndInputs(state, mapTxLockReqRejected[(*i).second.txHash]);
// resolve conflicts
//if this tx lock was rejected, we need to remove the conflicting blocks
if(mapTxLockReqRejected.count((*i).second.txHash)){
CValidationState state;
DisconnectBlockAndInputs(state, mapTxLockReqRejected[(*i).second.txHash]);
}
}
}
return true;
@ -350,6 +355,28 @@ bool ProcessConsensusVote(CConsensusVote& ctx)
return false;
}
bool CheckForConflictingLocks(CTransaction& tx)
{
/*
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.
Blocks could have been rejected during this time, which is OK. After they cancel out, the client will
rescan the blocks and find they're acceptable and then take the chain with the most work.
*/
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(mapLockedInputs.count(in.prevout)){
if(mapLockedInputs[in.prevout] != tx.GetHash()){
LogPrintf("InstantX::CheckForConflictingLocks - found two complete conflicting locks - removing both. %s %s", tx.GetHash().ToString().c_str(), mapLockedInputs[in.prevout].ToString().c_str());
if(mapTxLocks.count(tx.GetHash())) mapTxLocks[tx.GetHash()].nExpiration = GetTime();
if(mapTxLocks.count(mapLockedInputs[in.prevout])) mapTxLocks[mapLockedInputs[in.prevout]].nExpiration = GetTime();
return true;
}
}
}
return false;
}
int64_t GetAverageVoteTime()
{

View File

@ -35,6 +35,9 @@ int64_t CreateNewLock(CTransaction tx);
bool IsIXTXValid(const CTransaction& txCollateral);
// if two conflicting locks are approved by the network, they will cancel out
bool CheckForConflictingLocks(CTransaction& tx);
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
//check if we need to vote on this transaction

View File

@ -2823,11 +2823,6 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// ----------- instantX transaction scanning -----------
/*
block-level scanning is working below, but we need a blockchain
based management system for storing the active masternodes. Otherwise
small inconsistances can lead to forks.
*/
BOOST_FOREACH(const CTransaction& tx, block.vtx){
if (!tx.IsCoinBase()){