Slightly refactor/fix IS (#1153)
* slightly refactor IS: - the only place where logic is changed: `ProcessTxLockVote()` - it should first try to find mn and fail if none was found and only then try to call `GetMasternodeRank()` (which is heavy) - fixed few `cs_main` - slightly optimized number of `tx.GetHash()` calls - lots of `const` (fixed few related functions in main.cpp) - few smaller fixes: iterators, log output, comments, etc - use thread safe methods of mnodeman - safety check in GetAverageUnknownVoteTime
This commit is contained in:
parent
9162c56419
commit
785adad57e
134
src/instantx.cpp
134
src/instantx.cpp
@ -36,12 +36,12 @@ std::map<uint256, int64_t> mapUnknownVotes; //track votes with no tx for DOS
|
|||||||
|
|
||||||
CCriticalSection cs_instantsend;
|
CCriticalSection cs_instantsend;
|
||||||
|
|
||||||
//txlock - Locks transaction
|
// Transaction Locks
|
||||||
//
|
//
|
||||||
//step 1.) Broadcast intention to lock transaction inputs, "txlreg", CTransaction
|
// step 1) Some node announces intention to lock transaction inputs via "txlreg" message
|
||||||
//step 2.) Top INSTANTSEND_SIGNATURES_TOTAL masternodes, open connect to top 1 masternode.
|
// step 2) Top INSTANTSEND_SIGNATURES_TOTAL masternodes push "txvote" message
|
||||||
// Send "txvote", CTransaction, Signature, Approve
|
// step 3) Once there are INSTANTSEND_SIGNATURES_REQUIRED valid "txvote" messages
|
||||||
//step 3.) Top 1 masternode, waits for INSTANTSEND_SIGNATURES_REQUIRED messages. Upon success, sends "txlock'
|
// for a corresponding "txlreg" message, all inputs from that tx are treated as locked
|
||||||
|
|
||||||
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||||
{
|
{
|
||||||
@ -218,11 +218,11 @@ bool IsInstantSendTxValid(const CTransaction& txCandidate)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t CreateTxLockCandidate(CTransaction tx)
|
int64_t CreateTxLockCandidate(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
|
// Find the age of the first input but all inputs must be old enough too
|
||||||
int64_t nTxAge = 0;
|
int64_t nTxAge = 0;
|
||||||
BOOST_REVERSE_FOREACH(CTxIn txin, tx.vin) {
|
BOOST_REVERSE_FOREACH(const CTxIn& txin, tx.vin) {
|
||||||
nTxAge = GetInputAge(txin);
|
nTxAge = GetInputAge(txin);
|
||||||
if(nTxAge < 5) { //1 less than the "send IX" gui requires, incase of a block propagating the network at the time
|
if(nTxAge < 5) { //1 less than the "send IX" gui requires, incase of a block propagating the network at the time
|
||||||
LogPrintf("CreateTxLockCandidate -- Transaction not found / too new: nTxAge=%d, txid=%s\n", nTxAge, tx.GetHash().ToString());
|
LogPrintf("CreateTxLockCandidate -- Transaction not found / too new: nTxAge=%d, txid=%s\n", nTxAge, tx.GetHash().ToString());
|
||||||
@ -235,38 +235,37 @@ int64_t CreateTxLockCandidate(CTransaction tx)
|
|||||||
This prevents attackers from using transaction mallibility to predict which masternodes
|
This prevents attackers from using transaction mallibility to predict which masternodes
|
||||||
they'll use.
|
they'll use.
|
||||||
*/
|
*/
|
||||||
int nBlockHeight = 0;
|
int nCurrentHeight = 0;
|
||||||
|
int nLockInputHeight = 0;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
CBlockIndex* tip = chainActive.Tip();
|
if(!chainActive.Tip()) return 0;
|
||||||
if(tip)
|
nCurrentHeight = chainActive.Height();
|
||||||
nBlockHeight = tip->nHeight - nTxAge + 4;
|
nLockInputHeight = nCurrentHeight - nTxAge + 4;
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mapTxLockCandidates.count(tx.GetHash())) {
|
uint256 txHash = tx.GetHash();
|
||||||
LogPrintf("CreateTxLockCandidate -- New Transaction Lock Candidate! txid=%s\n", tx.GetHash().ToString());
|
|
||||||
|
if(!mapTxLockCandidates.count(txHash)) {
|
||||||
|
LogPrintf("CreateTxLockCandidate -- New Transaction Lock Candidate! txid=%s\n", txHash.ToString());
|
||||||
|
|
||||||
CTxLockCandidate txLockCandidate;
|
CTxLockCandidate txLockCandidate;
|
||||||
txLockCandidate.nBlockHeight = nBlockHeight;
|
txLockCandidate.nBlockHeight = nLockInputHeight;
|
||||||
//locks expire after nInstantSendKeepLock confirmations
|
//locks expire after nInstantSendKeepLock confirmations
|
||||||
txLockCandidate.nExpirationBlock = chainActive.Height() + Params().GetConsensus().nInstantSendKeepLock;
|
txLockCandidate.nExpirationBlock = nCurrentHeight + Params().GetConsensus().nInstantSendKeepLock;
|
||||||
txLockCandidate.nTimeout = GetTime()+(60*5);
|
txLockCandidate.nTimeout = GetTime()+(60*5);
|
||||||
txLockCandidate.txHash = tx.GetHash();
|
txLockCandidate.txHash = txHash;
|
||||||
mapTxLockCandidates.insert(std::make_pair(tx.GetHash(), txLockCandidate));
|
mapTxLockCandidates.insert(std::make_pair(txHash, txLockCandidate));
|
||||||
} else {
|
} else {
|
||||||
mapTxLockCandidates[tx.GetHash()].nBlockHeight = nBlockHeight;
|
mapTxLockCandidates[txHash].nBlockHeight = nLockInputHeight;
|
||||||
LogPrint("instantsend", "CreateTxLockCandidate -- Transaction Lock Candidate exists! txid=%s\n", tx.GetHash().ToString());
|
LogPrint("instantsend", "CreateTxLockCandidate -- Transaction Lock Candidate exists! txid=%s\n", txHash.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nLockInputHeight;
|
||||||
|
|
||||||
return nBlockHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we need to vote on this transaction
|
// check if we need to vote on this transaction
|
||||||
void CreateTxLockVote(CTransaction& tx, int64_t nBlockHeight)
|
void CreateTxLockVote(const CTransaction& tx, int nBlockHeight)
|
||||||
{
|
{
|
||||||
if(!fMasterNode) return;
|
if(!fMasterNode) return;
|
||||||
|
|
||||||
@ -312,22 +311,26 @@ void CreateTxLockVote(CTransaction& tx, int64_t nBlockHeight)
|
|||||||
//received a consensus vote
|
//received a consensus vote
|
||||||
bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
||||||
{
|
{
|
||||||
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
|
||||||
|
|
||||||
CMasternode* pmn = mnodeman.Find(vote.vinMasternode);
|
LogPrint("instantsend", "ProcessTxLockVote -- Transaction Lock Vote, txid=%s\n", vote.txHash.ToString());
|
||||||
if(pmn != NULL)
|
|
||||||
LogPrint("instantsend", "ProcessTxLockVote -- Masternode addr=%s, rank: %d\n", pmn->addr.ToString(), n);
|
if(!mnodeman.Has(vote.vinMasternode)) {
|
||||||
|
LogPrint("instantsend", "ProcessTxLockVote -- Unknown masternode %s\n", vote.vinMasternode.prevout.ToStringShort());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
||||||
|
|
||||||
if(n == -1) {
|
if(n == -1) {
|
||||||
//can be caused by past versions trying to vote with an invalid protocol
|
//can be caused by past versions trying to vote with an invalid protocol
|
||||||
LogPrint("instantsend", "ProcessTxLockVote -- Unknown Masternode: txin=%s\n", vote.vinMasternode.ToString());
|
LogPrint("instantsend", "ProcessTxLockVote -- Outdated masternode %s\n", vote.vinMasternode.prevout.ToStringShort());
|
||||||
mnodeman.AskForMN(pnode, vote.vinMasternode);
|
mnodeman.AskForMN(pnode, vote.vinMasternode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LogPrint("instantsend", "ProcessTxLockVote -- Masternode %s, rank=%d\n", vote.vinMasternode.prevout.ToStringShort(), n);
|
LogPrint("instantsend", "ProcessTxLockVote -- Masternode %s, rank=%d\n", vote.vinMasternode.prevout.ToStringShort(), n);
|
||||||
|
|
||||||
if(n > INSTANTSEND_SIGNATURES_TOTAL) {
|
if(n > INSTANTSEND_SIGNATURES_TOTAL) {
|
||||||
LogPrint("instantsend", "ProcessTxLockVote -- Masternode %s is not in the top %d (%d), vote hash %s\n",
|
LogPrint("instantsend", "ProcessTxLockVote -- Masternode %s is not in the top %d (%d), vote hash=%s\n",
|
||||||
vote.vinMasternode.prevout.ToStringShort(), INSTANTSEND_SIGNATURES_TOTAL, n, vote.GetHash().ToString());
|
vote.vinMasternode.prevout.ToStringShort(), INSTANTSEND_SIGNATURES_TOTAL, n, vote.GetHash().ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -387,7 +390,7 @@ bool ProcessTxLockVote(CNode* pnode, CTxLockVote& vote)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification)
|
void UpdateLockedTransaction(const CTransaction& tx, bool fForceNotification)
|
||||||
{
|
{
|
||||||
// there should be no conflicting locks
|
// there should be no conflicting locks
|
||||||
if(FindConflictingLocks(tx)) return;
|
if(FindConflictingLocks(tx)) return;
|
||||||
@ -417,7 +420,7 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification)
|
|||||||
GetMainSignals().NotifyTransactionLock(tx);
|
GetMainSignals().NotifyTransactionLock(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockTransactionInputs(CTransaction& tx) {
|
void LockTransactionInputs(const CTransaction& tx) {
|
||||||
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)
|
||||||
@ -425,7 +428,7 @@ void LockTransactionInputs(CTransaction& tx) {
|
|||||||
mapLockedInputs.insert(std::make_pair(txin.prevout, tx.GetHash()));
|
mapLockedInputs.insert(std::make_pair(txin.prevout, tx.GetHash()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FindConflictingLocks(CTransaction& tx)
|
bool FindConflictingLocks(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
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.
|
||||||
@ -434,13 +437,14 @@ bool FindConflictingLocks(CTransaction& tx)
|
|||||||
Blocks could have been rejected during this time, which is OK. After they cancel out, the client will
|
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.
|
rescan the blocks and find they're acceptable and then take the chain with the most work.
|
||||||
*/
|
*/
|
||||||
|
uint256 txHash = tx.GetHash();
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||||
if(mapLockedInputs.count(txin.prevout)) {
|
if(mapLockedInputs.count(txin.prevout)) {
|
||||||
if(mapLockedInputs[txin.prevout] != tx.GetHash()) {
|
if(mapLockedInputs[txin.prevout] != txHash) {
|
||||||
LogPrintf("FindConflictingLocks -- found two complete conflicting Transaction Locks, removing both: txid=%s, txin=%s", tx.GetHash().ToString(), mapLockedInputs[txin.prevout].ToString());
|
LogPrintf("FindConflictingLocks -- found two complete conflicting Transaction Locks, removing both: txid=%s, txin=%s", txHash.ToString(), mapLockedInputs[txin.prevout].ToString());
|
||||||
|
|
||||||
if(mapTxLockCandidates.count(tx.GetHash()))
|
if(mapTxLockCandidates.count(txHash))
|
||||||
mapTxLockCandidates[tx.GetHash()].nExpirationBlock = -1;
|
mapTxLockCandidates[txHash].nExpirationBlock = -1;
|
||||||
|
|
||||||
if(mapTxLockCandidates.count(mapLockedInputs[txin.prevout]))
|
if(mapTxLockCandidates.count(mapLockedInputs[txin.prevout]))
|
||||||
mapTxLockCandidates[mapLockedInputs[txin.prevout]].nExpirationBlock = -1;
|
mapTxLockCandidates[mapLockedInputs[txin.prevout]].nExpirationBlock = -1;
|
||||||
@ -453,32 +457,34 @@ bool FindConflictingLocks(CTransaction& tx)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResolveConflicts(CTransaction& tx)
|
void ResolveConflicts(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
|
uint256 txHash = tx.GetHash();
|
||||||
// resolve conflicts
|
// resolve conflicts
|
||||||
if (IsLockedInstandSendTransaction(tx.GetHash()) && !FindConflictingLocks(tx)) { //?????
|
if (IsLockedInstandSendTransaction(txHash) && !FindConflictingLocks(tx)) { //?????
|
||||||
LogPrintf("ResolveConflicts -- Found existing complete Transaction Lock, resolving...\n");
|
LogPrintf("ResolveConflicts -- Found existing complete Transaction Lock, resolving...\n");
|
||||||
|
|
||||||
//reprocess the last nInstantSendReprocessBlocks blocks
|
//reprocess the last nInstantSendReprocessBlocks blocks
|
||||||
ReprocessBlocks(Params().GetConsensus().nInstantSendReprocessBlocks);
|
ReprocessBlocks(Params().GetConsensus().nInstantSendReprocessBlocks);
|
||||||
if(!mapLockRequestAccepted.count(tx.GetHash()))
|
if(!mapLockRequestAccepted.count(txHash))
|
||||||
mapLockRequestAccepted.insert(std::make_pair(tx.GetHash(), tx)); //?????
|
mapLockRequestAccepted.insert(std::make_pair(txHash, tx)); //?????
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t GetAverageUnknownVoteTime()
|
int64_t GetAverageUnknownVoteTime()
|
||||||
{
|
{
|
||||||
|
// should never actually call this function when mapUnknownVotes is empty
|
||||||
|
if(mapUnknownVotes.empty()) return 0;
|
||||||
|
|
||||||
std::map<uint256, int64_t>::iterator it = mapUnknownVotes.begin();
|
std::map<uint256, int64_t>::iterator it = mapUnknownVotes.begin();
|
||||||
int64_t total = 0;
|
int64_t total = 0;
|
||||||
int64_t count = 0;
|
|
||||||
|
|
||||||
while(it != mapUnknownVotes.end()) {
|
while(it != mapUnknownVotes.end()) {
|
||||||
total+= it->second;
|
total+= it->second;
|
||||||
count++;
|
++it;
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total / count;
|
return total / mapUnknownVotes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanTxLockCandidates()
|
void CleanTxLockCandidates()
|
||||||
@ -487,11 +493,16 @@ void CleanTxLockCandidates()
|
|||||||
|
|
||||||
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.begin();
|
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.begin();
|
||||||
|
|
||||||
int nHeight = chainActive.Height();
|
int nHeight;
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
nHeight = chainActive.Height();
|
||||||
|
}
|
||||||
|
|
||||||
while(it != mapTxLockCandidates.end()) {
|
while(it != mapTxLockCandidates.end()) {
|
||||||
CTxLockCandidate &txLockCandidate = it->second;
|
CTxLockCandidate &txLockCandidate = it->second;
|
||||||
if(nHeight > txLockCandidate.nExpirationBlock) {
|
if(nHeight > txLockCandidate.nExpirationBlock) {
|
||||||
LogPrintf("CleanTxLockCandidates -- Removing expired Transaction Lock Candidate for txid %s\n", txLockCandidate.txHash.ToString());
|
LogPrintf("CleanTxLockCandidates -- Removing expired Transaction Lock Candidate: txid=%s\n", txLockCandidate.txHash.ToString());
|
||||||
|
|
||||||
if(mapLockRequestAccepted.count(txLockCandidate.txHash)){
|
if(mapLockRequestAccepted.count(txLockCandidate.txHash)){
|
||||||
CTransaction& tx = mapLockRequestAccepted[txLockCandidate.txHash];
|
CTransaction& tx = mapLockRequestAccepted[txLockCandidate.txHash];
|
||||||
@ -509,21 +520,20 @@ void CleanTxLockCandidates()
|
|||||||
|
|
||||||
mapTxLockCandidates.erase(it++);
|
mapTxLockCandidates.erase(it++);
|
||||||
} else {
|
} else {
|
||||||
it++;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLockedInstandSendTransaction(uint256 txHash)
|
bool IsLockedInstandSendTransaction(const uint256 &txHash)
|
||||||
{
|
{
|
||||||
// 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
|
||||||
std::map<uint256, CTxLockCandidate>::iterator i = mapTxLockCandidates.find(txHash);
|
return GetTransactionLockSignatures(txHash) >= INSTANTSEND_SIGNATURES_REQUIRED;
|
||||||
return i != mapTxLockCandidates.end() && (*i).second.CountVotes() >= INSTANTSEND_SIGNATURES_REQUIRED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetTransactionLockSignatures(uint256 txHash)
|
int GetTransactionLockSignatures(const uint256 &txHash)
|
||||||
{
|
{
|
||||||
if(!fEnableInstantSend) return -1;
|
if(!fEnableInstantSend) return -1;
|
||||||
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
|
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
|
||||||
@ -535,7 +545,7 @@ int GetTransactionLockSignatures(uint256 txHash)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTransactionLockTimedOut(uint256 txHash)
|
bool IsTransactionLockTimedOut(const uint256 &txHash)
|
||||||
{
|
{
|
||||||
if(!fEnableInstantSend) return 0;
|
if(!fEnableInstantSend) return 0;
|
||||||
|
|
||||||
@ -551,19 +561,19 @@ uint256 CTxLockVote::GetHash() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CTxLockVote::CheckSignature()
|
bool CTxLockVote::CheckSignature() const
|
||||||
{
|
{
|
||||||
std::string strError;
|
std::string strError;
|
||||||
std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight);
|
std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight);
|
||||||
|
|
||||||
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
masternode_info_t infoMn = mnodeman.GetMasternodeInfo(vinMasternode);
|
||||||
|
|
||||||
if(pmn == NULL) {
|
if(!infoMn.fInfoValid) {
|
||||||
LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: txin=%s\n", vinMasternode.ToString());
|
LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: txin=%s\n", vinMasternode.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!darkSendSigner.VerifyMessage(pmn->pubKeyMasternode, vchMasterNodeSignature, strMessage, strError)) {
|
if(!darkSendSigner.VerifyMessage(infoMn.pubKeyMasternode, vchMasterNodeSignature, strMessage, strError)) {
|
||||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -594,7 +604,7 @@ bool CTxLockVote::Sign()
|
|||||||
bool CTxLockCandidate::IsAllVotesValid()
|
bool CTxLockCandidate::IsAllVotesValid()
|
||||||
{
|
{
|
||||||
|
|
||||||
BOOST_FOREACH(CTxLockVote vote, vecTxLockVotes)
|
BOOST_FOREACH(const CTxLockVote& vote, vecTxLockVotes)
|
||||||
{
|
{
|
||||||
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
||||||
|
|
||||||
@ -617,7 +627,7 @@ bool CTxLockCandidate::IsAllVotesValid()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxLockCandidate::AddVote(CTxLockVote& vote)
|
void CTxLockCandidate::AddVote(const CTxLockVote& vote)
|
||||||
{
|
{
|
||||||
vecTxLockVotes.push_back(vote);
|
vecTxLockVotes.push_back(vote);
|
||||||
}
|
}
|
||||||
@ -632,7 +642,7 @@ int CTxLockCandidate::CountVotes()
|
|||||||
if(nBlockHeight == 0) return -1;
|
if(nBlockHeight == 0) return -1;
|
||||||
|
|
||||||
int nCount = 0;
|
int nCount = 0;
|
||||||
BOOST_FOREACH(CTxLockVote vote, vecTxLockVotes)
|
BOOST_FOREACH(const CTxLockVote& vote, vecTxLockVotes)
|
||||||
if(vote.nBlockHeight == nBlockHeight)
|
if(vote.nBlockHeight == nBlockHeight)
|
||||||
nCount++;
|
nCount++;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ static const int INSTANTSEND_SIGNATURES_TOTAL = 10;
|
|||||||
static const int DEFAULT_INSTANTSEND_DEPTH = 5;
|
static const int DEFAULT_INSTANTSEND_DEPTH = 5;
|
||||||
|
|
||||||
static const int MIN_INSTANTSEND_PROTO_VERSION = 70202;
|
static const int MIN_INSTANTSEND_PROTO_VERSION = 70202;
|
||||||
static const CAmount INSTANTSEND_MIN_FEE = 0.1 * CENT;
|
static const CAmount INSTANTSEND_MIN_FEE = 0.001 * COIN;
|
||||||
|
|
||||||
extern bool fEnableInstantSend;
|
extern bool fEnableInstantSend;
|
||||||
extern int nInstantSendDepth;
|
extern int nInstantSendDepth;
|
||||||
@ -41,40 +41,40 @@ extern std::map<uint256, CTxLockVote> mapTxLockVotes;
|
|||||||
extern std::map<COutPoint, uint256> mapLockedInputs;
|
extern std::map<COutPoint, uint256> mapLockedInputs;
|
||||||
|
|
||||||
|
|
||||||
int64_t CreateTxLockCandidate(CTransaction tx);
|
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||||
|
|
||||||
bool IsInstantSendTxValid(const CTransaction& txCandidate);
|
bool IsInstantSendTxValid(const CTransaction& txCandidate);
|
||||||
|
|
||||||
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
int64_t CreateTxLockCandidate(const CTransaction &tx);
|
||||||
|
|
||||||
//check if we need to vote on this transaction
|
//check if we need to vote on this transaction
|
||||||
void CreateTxLockVote(CTransaction& tx, int64_t nBlockHeight);
|
void CreateTxLockVote(const CTransaction& tx, int nBlockHeight);
|
||||||
|
|
||||||
//process consensus vote message
|
//process consensus vote message
|
||||||
bool ProcessTxLockVote(CNode *pnode, CTxLockVote& vote);
|
bool ProcessTxLockVote(CNode *pnode, CTxLockVote& vote);
|
||||||
|
|
||||||
//update UI and notify external script if any
|
//update UI and notify external script if any
|
||||||
void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification = false);
|
void UpdateLockedTransaction(const CTransaction& tx, bool fForceNotification = false);
|
||||||
|
|
||||||
void LockTransactionInputs(CTransaction& tx);
|
void LockTransactionInputs(const CTransaction& tx);
|
||||||
|
|
||||||
// if two conflicting locks are approved by the network, they will cancel out
|
// if two conflicting locks are approved by the network, they will cancel out
|
||||||
bool FindConflictingLocks(CTransaction& tx);
|
bool FindConflictingLocks(const CTransaction& tx);
|
||||||
|
|
||||||
//try to resolve conflicting locks
|
//try to resolve conflicting locks
|
||||||
void ResolveConflicts(CTransaction& tx);
|
void ResolveConflicts(const CTransaction& tx);
|
||||||
|
|
||||||
// keep transaction locks in memory for an hour
|
// keep transaction locks in memory for an hour
|
||||||
void CleanTxLockCandidates();
|
void CleanTxLockCandidates();
|
||||||
|
|
||||||
// verify if transaction is currently locked
|
// verify if transaction is currently locked
|
||||||
bool IsLockedInstandSendTransaction(uint256 txHash);
|
bool IsLockedInstandSendTransaction(const uint256 &txHash);
|
||||||
|
|
||||||
// get the actual uber og accepted lock signatures
|
// get the actual uber og accepted lock signatures
|
||||||
int GetTransactionLockSignatures(uint256 txHash);
|
int GetTransactionLockSignatures(const uint256 &txHash);
|
||||||
|
|
||||||
// verify if transaction lock timed out
|
// verify if transaction lock timed out
|
||||||
bool IsTransactionLockTimedOut(uint256 txHash);
|
bool IsTransactionLockTimedOut(const uint256 &txHash);
|
||||||
|
|
||||||
int64_t GetAverageUnknownVoteTime();
|
int64_t GetAverageUnknownVoteTime();
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ public:
|
|||||||
uint256 GetHash() const;
|
uint256 GetHash() const;
|
||||||
|
|
||||||
bool Sign();
|
bool Sign();
|
||||||
bool CheckSignature();
|
bool CheckSignature() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CTxLockCandidate
|
class CTxLockCandidate
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
uint256 GetHash() const { return txHash; }
|
uint256 GetHash() const { return txHash; }
|
||||||
|
|
||||||
bool IsAllVotesValid();
|
bool IsAllVotesValid();
|
||||||
void AddVote(CTxLockVote& vote);
|
void AddVote(const CTxLockVote& vote);
|
||||||
int CountVotes();
|
int CountVotes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -940,7 +940,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
|
|||||||
return nSigOps;
|
return nSigOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetInputAge(CTxIn& txin)
|
int GetInputAge(const CTxIn &txin)
|
||||||
{
|
{
|
||||||
CCoinsView viewDummy;
|
CCoinsView viewDummy;
|
||||||
CCoinsViewCache view(&viewDummy);
|
CCoinsViewCache view(&viewDummy);
|
||||||
@ -960,7 +960,7 @@ int GetInputAge(CTxIn& txin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetInputAgeIX(uint256 nTXHash, CTxIn& txin)
|
int GetInputAgeIX(const uint256 &nTXHash, const CTxIn &txin)
|
||||||
{
|
{
|
||||||
int nResult = GetInputAge(txin);
|
int nResult = GetInputAge(txin);
|
||||||
if(nResult < 0) return -1;
|
if(nResult < 0) return -1;
|
||||||
@ -971,7 +971,7 @@ int GetInputAgeIX(uint256 nTXHash, CTxIn& txin)
|
|||||||
return nResult;
|
return nResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetIXConfirmations(uint256 nTXHash)
|
int GetIXConfirmations(const uint256 &nTXHash)
|
||||||
{
|
{
|
||||||
if (IsLockedInstandSendTransaction(nTXHash))
|
if (IsLockedInstandSendTransaction(nTXHash))
|
||||||
return nInstantSendDepth;
|
return nInstantSendDepth;
|
||||||
|
@ -292,9 +292,9 @@ void PruneAndFlush();
|
|||||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||||
bool* pfMissingInputs, bool fOverrideMempoolLimit=false, bool fRejectAbsurdFee=false, bool fDryRun=false);
|
bool* pfMissingInputs, bool fOverrideMempoolLimit=false, bool fRejectAbsurdFee=false, bool fDryRun=false);
|
||||||
|
|
||||||
int GetInputAge(CTxIn& txin);
|
int GetInputAge(const CTxIn &txin);
|
||||||
int GetInputAgeIX(uint256 nTXHash, CTxIn& txin);
|
int GetInputAgeIX(const uint256 &nTXHash, const CTxIn &txin);
|
||||||
int GetIXConfirmations(uint256 nTXHash);
|
int GetIXConfirmations(const uint256 &nTXHash);
|
||||||
|
|
||||||
/** Convert CValidationState to a human-readable message for logging */
|
/** Convert CValidationState to a human-readable message for logging */
|
||||||
std::string FormatStateMessage(const CValidationState &state);
|
std::string FormatStateMessage(const CValidationState &state);
|
||||||
|
Loading…
Reference in New Issue
Block a user