Merge pull request #746 from UdjinM6/refactorixdstx

Refactor IX/DSTX messages handling
This commit is contained in:
evan82 2016-03-23 11:18:56 -07:00
commit dee72ad0cd
8 changed files with 125 additions and 165 deletions

View File

@ -51,13 +51,10 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
pfrom->AddInventoryKnown(inv);
if(mapTxLockReq.count(tx.GetHash()) || mapTxLockReqRejected.count(tx.GetHash())){
return;
}
if(!IsIXTXValid(tx)){
return;
}
// have we seen it already?
if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)) return;
// is it a valid one?
if(!IsIXTXValid(tx)) return;
BOOST_FOREACH(const CTxOut o, tx.vout){
// IX supports normal scripts and unspendable scripts (used in DS collateral and Budget collateral).
@ -110,18 +107,12 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
}
// resolve conflicts
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(tx.GetHash());
if (i != mapTxLocks.end()){
//we only care if we have a complete tx lock
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
if(!CheckForConflictingLocks(tx)){
LogPrintf("ProcessMessageInstantX::ix - Found Existing Complete IX Lock\n");
if (IsLockedIXTransaction(tx.GetHash()) && !CheckForConflictingLocks(tx)){
LogPrintf("ProcessMessageInstantX::ix - Found Existing Complete IX Lock\n");
//reprocess the last 15 blocks
ReprocessBlocks(15);
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
}
}
//reprocess the last 15 blocks
ReprocessBlocks(15);
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
}
return;
@ -173,7 +164,11 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
bool IsIXTXValid(const CTransaction& txCollateral){
if(txCollateral.vout.size() < 1) return false;
if(txCollateral.nLockTime != 0) return false;
if(!CheckFinalTx(txCollateral)) {
LogPrint("instantx", "IsIXTXValid - Transaction is not final - %s\n", txCollateral.ToString());
return false;
}
int64_t nValueIn = 0;
int64_t nValueOut = 0;
@ -360,17 +355,19 @@ bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx)
}
#endif
LogPrint("instantx", "InstantX::ProcessConsensusVote - Transaction Lock Votes %d - %s !\n", (*i).second.CountSignatures(), ctx.GetHash().ToString());
int nSignatures = (*i).second.CountSignatures();
LogPrint("instantx", "InstantX::ProcessConsensusVote - Transaction Lock Votes %d - %s !\n", nSignatures, ctx.GetHash().ToString());
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
LogPrint("instantx", "InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", (*i).second.GetHash().ToString());
if(nSignatures >= INSTANTX_SIGNATURES_REQUIRED){
LogPrint("instantx", "InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", ctx.txHash.ToString());
CTransaction& tx = mapTxLockReq[ctx.txHash];
if(!CheckForConflictingLocks(tx)){
#ifdef ENABLE_WALLET
if(pwalletMain){
if(pwalletMain->UpdatedTransaction((*i).second.txHash)){
if(pwalletMain->UpdatedTransaction(ctx.txHash)){
// bumping this to update UI
nCompleteTXLocks++;
}
}
@ -387,7 +384,7 @@ bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx)
// resolve conflicts
//if this tx lock was rejected, we need to remove the conflicting blocks
if(mapTxLockReqRejected.count((*i).second.txHash)){
if(mapTxLockReqRejected.count(ctx.txHash)){
//reprocess the last 15 blocks
ReprocessBlocks(15);
}
@ -466,6 +463,37 @@ void CleanTransactionLocksList()
}
}
bool IsLockedIXTransaction(uint256 txHash) {
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
return i != mapTxLocks.end() && (*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED;
}
int GetTransactionLockSignatures(uint256 txHash)
{
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
if(!IsSporkActive(SPORK_2_INSTANTX)) return -3;
if(!fEnableInstantX) return -1;
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
if (i != mapTxLocks.end()){
return (*i).second.CountSignatures();
}
return -1;
}
bool IsTransactionLockTimedOut(uint256 txHash)
{
if(!fEnableInstantX) return 0;
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
if (i != mapTxLocks.end()){
return GetTime() > (*i).second.nTimeout;
}
return false;
}
uint256 CConsensusVote::GetHash() const
{
return ArithToUint256(UintToArith256(vinMasternode.prevout.hash) + vinMasternode.prevout.n + UintToArith256(txHash));

View File

@ -37,7 +37,6 @@ static const int MIN_INSTANTX_PROTO_VERSION = 70103;
extern map<uint256, CTransaction> mapTxLockReq;
extern map<uint256, CTransaction> mapTxLockReqRejected;
extern map<uint256, CConsensusVote> mapTxLockVote;
extern map<uint256, CTransactionLock> mapTxLocks;
extern std::map<COutPoint, uint256> mapLockedInputs;
extern int nCompleteTXLocks;
@ -60,6 +59,15 @@ bool ProcessConsensusVote(CNode *pnode, CConsensusVote& ctx);
// keep transaction locks in memory for an hour
void CleanTransactionLocksList();
// verify if transaction is currently locked
bool IsLockedIXTransaction(uint256 txHash);
// get the actual uber og accepted lock signatures
int GetTransactionLockSignatures(uint256 txHash);
// verify if transaction lock timed out
bool IsTransactionLockTimedOut(uint256 txHash);
int64_t GetAverageVoteTime();
class CConsensusVote

View File

@ -769,35 +769,20 @@ int GetInputAge(CTxIn& vin)
}
int GetInputAgeIX(uint256 nTXHash, CTxIn& vin)
{
int sigs = 0;
{
int nResult = GetInputAge(vin);
if(nResult < 0) nResult = 0;
if(nResult < 0) return -1;
if (nResult < 6){
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()){
sigs = (*i).second.CountSignatures();
}
if(sigs >= INSTANTX_SIGNATURES_REQUIRED){
return nInstantXDepth+nResult;
}
}
if (nResult < 6 && IsLockedIXTransaction(nTXHash))
return nInstantXDepth + nResult;
return -1;
return nResult;
}
int GetIXConfirmations(uint256 nTXHash)
{
int sigs = 0;
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()){
sigs = (*i).second.CountSignatures();
}
if(sigs >= INSTANTX_SIGNATURES_REQUIRED){
{
if (IsLockedIXTransaction(nTXHash))
return nInstantXDepth;
}
return 0;
}
@ -4394,17 +4379,9 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
mapOrphanTransactions.count(inv.hash) ||
pcoinsTip->HaveCoins(inv.hash);
}
case MSG_DSTX:
return mapDarksendBroadcastTxes.count(inv.hash);
case MSG_BLOCK:
return mapBlockIndex.count(inv.hash);
case MSG_TXLOCK_REQUEST:
return mapTxLockReq.count(inv.hash) ||
mapTxLockReqRejected.count(inv.hash);
case MSG_TXLOCK_VOTE:
return mapTxLockVote.count(inv.hash);
case MSG_SPORK:
return mapSporks.count(inv.hash);
/*
Dash Related Inventory Messages
@ -4415,44 +4392,38 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
We're going to be asking many nodes upfront for the full inventory list, so we'll get duplicates of these.
We want to only update the time on new hits, so that we can time out appropriately if needed.
*/
case MSG_TXLOCK_REQUEST:
return mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash);
case MSG_TXLOCK_VOTE:
return mapTxLockVote.count(inv.hash);
case MSG_SPORK:
return mapSporks.count(inv.hash);
case MSG_MASTERNODE_WINNER:
if(mnpayments.mapMasternodePayeeVotes.count(inv.hash)) {
//masternodeSync.AddedMasternodeWinner(inv.hash);
return true;
}
return false;
return mnpayments.mapMasternodePayeeVotes.count(inv.hash);
case MSG_BUDGET_VOTE:
if(budget.mapSeenMasternodeBudgetVotes.count(inv.hash)) {
//masternodeSync.AddedBudgetItem(inv.hash);
return true;
}
return false;
return budget.mapSeenMasternodeBudgetVotes.count(inv.hash);
case MSG_BUDGET_PROPOSAL:
if(budget.mapSeenMasternodeBudgetProposals.count(inv.hash)) {
//masternodeSync.AddedBudgetItem(inv.hash);
return true;
}
return false;
case MSG_BUDGET_FINALIZED_VOTE:
if(budget.mapSeenFinalizedBudgetVotes.count(inv.hash)) {
//masternodeSync.AddedBudgetItem(inv.hash);
return true;
}
return false;
return budget.mapSeenMasternodeBudgetProposals.count(inv.hash);
case MSG_BUDGET_FINALIZED:
if(budget.mapSeenFinalizedBudgets.count(inv.hash)) {
//masternodeSync.AddedBudgetItem(inv.hash);
return true;
}
return false;
return budget.mapSeenFinalizedBudgets.count(inv.hash);
case MSG_BUDGET_FINALIZED_VOTE:
return budget.mapSeenFinalizedBudgetVotes.count(inv.hash);
case MSG_MASTERNODE_ANNOUNCE:
if(mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
//masternodeSync.AddedMasternodeList(inv.hash);
return true;
}
return false;
return mnodeman.mapSeenMasternodeBroadcast.count(inv.hash);
case MSG_MASTERNODE_PING:
return mnodeman.mapSeenMasternodePing.count(inv.hash);
case MSG_DSTX:
return mapDarksendBroadcastTxes.count(inv.hash);
}
// Don't know what it is, just say we already got one
return true;
@ -5319,11 +5290,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
if(strCommand == NetMsgType::DSTX){
CInv inv(MSG_DSTX, tx.GetHash());
RelayInv(inv);
}
int nDoS = 0;
if (state.IsInvalid(nDoS))
{

View File

@ -20,6 +20,7 @@
#include "scheduler.h"
#include "ui_interface.h"
#include "darksend.h"
#include "instantx.h"
#include "wallet/wallet.h"
#include "utilstrencodings.h"
@ -2075,7 +2076,9 @@ void RelayTransaction(const CTransaction& tx)
void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
{
CInv inv(MSG_TX, tx.GetHash());
int nInv = mapDarksendBroadcastTxes.count(tx.GetHash()) ? MSG_DSTX :
(mapTxLockReq.count(tx.GetHash()) ? MSG_TXLOCK_REQUEST : MSG_TX);
CInv inv(nInv, tx.GetHash());
{
LOCK(cs_mapRelay);
// Expire old relay messages
@ -2104,21 +2107,6 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
}
}
void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll)
{
CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
//broadcast the new lock
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if(!relayToAll && !pnode->fRelayTxes)
continue;
pnode->PushMessage(NetMsgType::IX, tx);
}
}
void RelayInv(CInv &inv, const int minProtoVersion) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)

View File

@ -850,7 +850,6 @@ public:
class CTransaction;
void RelayTransaction(const CTransaction& tx);
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll=false);
void RelayInv(CInv &inv, const int minProtoVersion = MIN_PEER_PROTO_VERSION);
/** Access to the (IP) address database (peers.dat) */

View File

@ -34,7 +34,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
}
else
{
int signatures = wtx.GetTransactionLockSignatures();
int signatures = GetTransactionLockSignatures(wtx.GetHash());
QString strUsingIX = "";
if(signatures >= 0){
@ -49,7 +49,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
else
return tr("%1 confirmations (verified via instantx)").arg(nDepth);
} else {
if(!wtx.IsTransactionLockTimedOut()){
if(!IsTransactionLockTimedOut(wtx.GetHash())){
int nDepth = wtx.GetDepthInMainChain();
if (nDepth < 0)
return tr("conflicted");

View File

@ -1485,10 +1485,8 @@ bool CWalletTx::RelayWalletTransaction(std::string strCommand)
if(strCommand == NetMsgType::IX){
mapTxLockReq.insert(make_pair(hash, (CTransaction)*this));
CreateNewLock(((CTransaction)*this));
RelayTransactionLockReq((CTransaction)*this, true);
} else {
RelayTransaction((CTransaction)*this);
}
RelayTransaction((CTransaction)*this);
return true;
}
}
@ -2845,7 +2843,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// enough, that fee sniping isn't a problem yet, but by implementing a fix
// now we ensure code won't be written that makes assumptions about
// nLockTime that preclude a fix later.
txNew.nLockTime = chainActive.Height();
// FIXME: "compatibility mode" for 12.0 IX, make it "txNew.nLockTime = chainActive.Height();" again in 12.2
txNew.nLockTime = useIX ? 0 : chainActive.Height();
// Secondly occasionally randomly pick a nLockTime even further back, so
// that transactions that are delayed after signing for whatever reason,
@ -4055,34 +4055,34 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX) const
{
int nResult;
if (hashUnset())
return 0;
nResult = 0;
else {
AssertLockHeld(cs_main);
AssertLockHeld(cs_main);
// Find the block it claims to be in
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
nResult = 0;
else {
CBlockIndex* pindex = (*mi).second;
if (!pindex || !chainActive.Contains(pindex))
nResult = 0;
else {
pindexRet = pindex;
nResult = ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
// Find the block it claims to be in
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
if (!pindex || !chainActive.Contains(pindex))
return 0;
pindexRet = pindex;
int nResult = ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
if (nResult == 0 && !mempool.exists(GetHash()))
return -1; // Not in chain, not in mempool
if(enableIX){
if (nResult < 6){
int signatures = GetTransactionLockSignatures();
if(signatures >= INSTANTX_SIGNATURES_REQUIRED){
return nInstantXDepth+nResult;
if (nResult == 0 && !mempool.exists(GetHash()))
return -1; // Not in chain, not in mempool
}
}
}
if(enableIX && nResult < 6 && IsLockedIXTransaction(GetHash()))
return nInstantXDepth + nResult;
return nResult;
}
@ -4099,30 +4099,3 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
CValidationState state;
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, fRejectAbsurdFee);
}
int CMerkleTx::GetTransactionLockSignatures() const
{
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
if(!IsSporkActive(SPORK_2_INSTANTX)) return -3;
if(!fEnableInstantX) return -1;
//compile consessus vote
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(GetHash());
if (i != mapTxLocks.end()){
return (*i).second.CountSignatures();
}
return -1;
}
bool CMerkleTx::IsTransactionLockTimedOut() const
{
if(!fEnableInstantX) return 0;
//compile consessus vote
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(GetHash());
if (i != mapTxLocks.end()){
return GetTime() > (*i).second.nTimeout;
}
return false;
}

View File

@ -228,8 +228,6 @@ public:
int GetDepthInMainChain(bool enableIX = true) const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet, enableIX); }
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
int GetBlocksToMaturity() const;
int GetTransactionLockSignatures() const;
bool IsTransactionLockTimedOut() const;
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }