Merge downstream 0.11.1
This commit is contained in:
commit
4cdb18fa4f
@ -3,7 +3,7 @@ AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 11)
|
||||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_BUILD, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 4)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2015)
|
||||
AC_INIT([Darkcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@darkcoin.io],[darkcoin])
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 11
|
||||
#define CLIENT_VERSION_REVISION 1
|
||||
#define CLIENT_VERSION_BUILD 2
|
||||
#define CLIENT_VERSION_BUILD 4
|
||||
|
||||
|
||||
|
||||
|
@ -1323,7 +1323,8 @@ bool CDarkSendPool::GetLastValidBlockHash(uint256& hash, int mod, int nBlockHeig
|
||||
const CBlockIndex *BlockLastSolved = chainActive.Tip();
|
||||
const CBlockIndex *BlockReading = chainActive.Tip();
|
||||
|
||||
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0) { return false; }
|
||||
if (chainActive.Tip() == NULL) return false;
|
||||
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || chainActive.Tip()->nHeight+1 < nBlockHeight) return false;
|
||||
|
||||
int nBlocksAgo = 0;
|
||||
if(nBlockHeight > 0) nBlocksAgo = (chainActive.Tip()->nHeight+1)-nBlockHeight;
|
||||
|
@ -223,7 +223,7 @@ class CDarksendSession
|
||||
class CDarkSendPool
|
||||
{
|
||||
public:
|
||||
static const int MIN_PEER_PROTO_VERSION = 70055;
|
||||
static const int MIN_PEER_PROTO_VERSION = 70057;
|
||||
|
||||
// clients entries
|
||||
std::vector<CDarkSendEntry> myEntries;
|
||||
|
159
src/instantx.cpp
159
src/instantx.cpp
@ -22,6 +22,7 @@ std::map<uint256, CTransaction> mapTxLockReq;
|
||||
std::map<uint256, CTransaction> mapTxLockReqRejected;
|
||||
std::map<uint256, int> mapTxLockVote;
|
||||
std::map<uint256, CTransactionLock> mapTxLocks;
|
||||
std::map<uint256, int64_t> mapUnknownVotes; //track votes with no tx for DOS
|
||||
int nCompleteTXLocks;
|
||||
|
||||
//txlock - Locks transaction
|
||||
@ -44,7 +45,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
|
||||
if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)){
|
||||
if(mapTxLockReq.count(tx.GetHash()) || mapTxLockReqRejected.count(tx.GetHash())){
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,10 +71,10 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
|
||||
{
|
||||
RelayTransactionLockReq(tx, inv.hash);
|
||||
RelayTransactionLockReq(tx, tx.GetHash());
|
||||
DoConsensusVote(tx, true, nBlockHeight);
|
||||
|
||||
mapTxLockReq.insert(make_pair(inv.hash, tx));
|
||||
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
|
||||
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : accepted %s\n",
|
||||
pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
|
||||
@ -83,7 +84,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
return;
|
||||
|
||||
} else {
|
||||
mapTxLockReqRejected.insert(make_pair(inv.hash, tx));
|
||||
mapTxLockReqRejected.insert(make_pair(tx.GetHash(), tx));
|
||||
|
||||
// can we get the conflicting transaction as proof?
|
||||
|
||||
@ -95,6 +96,31 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
tx.GetHash().ToString().c_str()
|
||||
);
|
||||
|
||||
// resolve conflicts
|
||||
/*std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(tx.GetHash());
|
||||
if (i != mapTxLocks.end()){
|
||||
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Found IX lock\n");
|
||||
|
||||
uint256 txHash = (*i).second.txHash;
|
||||
CValidationState state;
|
||||
bool fMissingInputs = false;
|
||||
DisconnectBlockAndInputs(state, mapTxLockReqRejected[txHash]);
|
||||
|
||||
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
|
||||
{
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request : accepted (resolved) %s\n",
|
||||
pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(),
|
||||
tx.GetHash().ToString().c_str()
|
||||
);
|
||||
} else {
|
||||
LogPrintf("ERROR: InstantX::ProcessConsensusVote - Transaction Lock Request : rejected (failed to resolve) %s\n",
|
||||
tx.GetHash().ToString().c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//record prevout, increment the amount of times seen. Ban if over 100
|
||||
|
||||
return;
|
||||
@ -114,12 +140,39 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
mapTxLockVote.insert(make_pair(ctx.GetHash(), 1));
|
||||
|
||||
ProcessConsensusVote(ctx);
|
||||
if(ProcessConsensusVote(ctx)){
|
||||
//Spam/Dos protection
|
||||
/*
|
||||
Masternodes will sometimes propagate votes before the transaction is known to the client.
|
||||
This tracks those messages and allows it at the same rate of the rest of the network, if
|
||||
a peer violates it, it will simply be ignored
|
||||
*/
|
||||
if(!mapTxLockReq.count(ctx.txHash) && !mapTxLockReqRejected.count(ctx.txHash)){
|
||||
if(!mapUnknownVotes.count(ctx.vinMasternode.prevout.hash)){
|
||||
//TODO: Make an algorithm to calculate the average time per IX/MNCOUNT
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
}
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
pnode->PushMessage("txlvote", ctx);
|
||||
if(mapUnknownVotes[ctx.vinMasternode.prevout.hash] > GetTime() &&
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] - GetAverageVoteTime() > 60*10){
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - masternode is spamming transaction votes: %s %s : rejected %s\n",
|
||||
ctx.vinMasternode.ToString().c_str(),
|
||||
ctx.txHash.ToString().c_str()
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
}
|
||||
}
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
if(!pnode->fRelayTxes)
|
||||
continue;
|
||||
|
||||
pnode->PushMessage("txlvote", ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -133,8 +186,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight)
|
||||
|
||||
CConsensusVote ctx;
|
||||
ctx.vinMasternode = activeMasternode.vin;
|
||||
ctx.approved = approved;
|
||||
ctx.tx = tx;
|
||||
ctx.txHash = tx.GetHash();
|
||||
ctx.nBlockHeight = nBlockHeight;
|
||||
if(!ctx.Sign()){
|
||||
LogPrintf("InstantX::DoConsensusVote - Failed to sign consensus vote\n");
|
||||
@ -144,7 +196,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight)
|
||||
LogPrintf("InstantX::DoConsensusVote - Signature invalid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
@ -155,54 +207,93 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight)
|
||||
}
|
||||
|
||||
//received a consensus vote
|
||||
void ProcessConsensusVote(CConsensusVote& ctx)
|
||||
bool ProcessConsensusVote(CConsensusVote& ctx)
|
||||
{
|
||||
int n = GetMasternodeRank(ctx.vinMasternode, ctx.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Unknown Masternode\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(n > 10)
|
||||
{
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Masternode not in the top 10\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ctx.SignatureValid()) {
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Signature invalid\n");
|
||||
//don't ban, it could just be a non-synced masternode
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mapTxLocks.count(ctx.tx.GetHash())){
|
||||
LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", ctx.tx.GetHash().ToString().c_str());
|
||||
if (!mapTxLocks.count(ctx.txHash)){
|
||||
LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", ctx.txHash.ToString().c_str());
|
||||
|
||||
CTransactionLock newLock;
|
||||
newLock.nBlockHeight = ctx.nBlockHeight;
|
||||
newLock.nExpiration = GetTime()+(60*60);
|
||||
newLock.tx = ctx.tx;
|
||||
mapTxLocks.insert(make_pair(ctx.tx.GetHash(), newLock));
|
||||
newLock.txHash = ctx.txHash;
|
||||
mapTxLocks.insert(make_pair(ctx.txHash, newLock));
|
||||
} else {
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", ctx.tx.GetHash().ToString().c_str());
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", ctx.txHash.ToString().c_str());
|
||||
}
|
||||
|
||||
//compile consessus vote
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(ctx.tx.GetHash());
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(ctx.txHash);
|
||||
if (i != mapTxLocks.end()){
|
||||
(*i).second.AddSignature(ctx);
|
||||
if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", (*i).second.GetHash().ToString().c_str());
|
||||
pwalletMain->UpdatedTransaction((*i).second.tx.GetHash());
|
||||
nCompleteTXLocks++;
|
||||
|
||||
if(pwalletMain->UpdatedTransaction((*i).second.txHash)){
|
||||
nCompleteTXLocks++;
|
||||
}
|
||||
|
||||
// resolve conflicts
|
||||
/*
|
||||
//if this tx lock was rejected, we need to remove the conflicting blocks
|
||||
if(mapTxLockReqRejected.count((*i).second.txHash)){
|
||||
CValidationState state;
|
||||
bool fMissingInputs = false;
|
||||
DisconnectBlockAndInputs(state, mapTxLockReqRejected[(*i).second.txHash]);
|
||||
|
||||
if (AcceptToMemoryPool(mempool, state, mapTxLockReqRejected[(*i).second.txHash], true, &fMissingInputs))
|
||||
{
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request : accepted (resolved) %s\n",
|
||||
mapTxLockReqRejected[(*i).second.txHash].GetHash().ToString().c_str()
|
||||
);
|
||||
|
||||
} else {
|
||||
LogPrintf("ERROR: InstantX::ProcessConsensusVote - Transaction Lock Request : rejected (failed to resolve) %s\n",
|
||||
mapTxLockReqRejected[(*i).second.txHash].GetHash().ToString().c_str()
|
||||
);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int64_t GetAverageVoteTime()
|
||||
{
|
||||
std::map<uint256, int64_t>::iterator it = mapUnknownVotes.begin();
|
||||
int64_t total = 0;
|
||||
int64_t count = 0;
|
||||
|
||||
while(it != mapUnknownVotes.end()) {
|
||||
total+= it->second;
|
||||
count++;
|
||||
it++;
|
||||
}
|
||||
|
||||
return total / count;
|
||||
}
|
||||
|
||||
void CleanTransactionLocksList()
|
||||
@ -213,7 +304,7 @@ void CleanTransactionLocksList()
|
||||
|
||||
while(it != mapTxLocks.end()) {
|
||||
if(GetTime() > it->second.nExpiration){ //keep them for an hour
|
||||
LogPrintf("Removing old transaction lock %s\n", it->second.GetHash().ToString().c_str());
|
||||
LogPrintf("Removing old transaction lock %s\n", it->second.txHash.ToString().c_str());
|
||||
mapTxLocks.erase(it++);
|
||||
} else {
|
||||
it++;
|
||||
@ -224,14 +315,14 @@ void CleanTransactionLocksList()
|
||||
|
||||
uint256 CConsensusVote::GetHash() const
|
||||
{
|
||||
return vinMasternode.prevout.hash + tx.GetHash();
|
||||
return vinMasternode.prevout.hash + txHash;
|
||||
}
|
||||
|
||||
|
||||
bool CConsensusVote::SignatureValid()
|
||||
{
|
||||
std::string errorMessage;
|
||||
std::string strMessage = tx.GetHash().ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
|
||||
std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight);
|
||||
//LogPrintf("verify strMessage %s \n", strMessage.c_str());
|
||||
|
||||
int n = GetMasternodeByVin(vinMasternode);
|
||||
@ -267,7 +358,7 @@ bool CConsensusVote::Sign()
|
||||
|
||||
CKey key2;
|
||||
CPubKey pubkey2;
|
||||
std::string strMessage = tx.GetHash().ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight) + boost::lexical_cast<std::string>(approved);
|
||||
std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight);
|
||||
//LogPrintf("signing strMessage %s \n", strMessage.c_str());
|
||||
//LogPrintf("signing privkey %s \n", strMasterNodePrivKey.c_str());
|
||||
|
||||
@ -326,14 +417,6 @@ bool CTransactionLock::SignaturesValid()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTransactionLock::AllInFavor()
|
||||
{
|
||||
BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
|
||||
if(vote.approved == false) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTransactionLock::AddSignature(CConsensusVote cv)
|
||||
{
|
||||
vecConsensusVotes.push_back(cv);
|
||||
|
@ -23,7 +23,7 @@ class CConsensusVote;
|
||||
class CTransaction;
|
||||
class CTransactionLock;
|
||||
|
||||
static const int MIN_INSTANTX_PROTO_VERSION = 70055;
|
||||
static const int MIN_INSTANTX_PROTO_VERSION = 70057;
|
||||
|
||||
extern map<uint256, CTransaction> mapTxLockReq;
|
||||
extern map<uint256, CTransactionLock> mapTxLocks;
|
||||
@ -35,17 +35,18 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight);
|
||||
|
||||
//process consensus vote message
|
||||
void ProcessConsensusVote(CConsensusVote& ctx);
|
||||
bool ProcessConsensusVote(CConsensusVote& ctx);
|
||||
|
||||
// keep transaction locks in memory for an hour
|
||||
void CleanTransactionLocksList();
|
||||
|
||||
int64_t GetAverageVoteTime();
|
||||
|
||||
class CConsensusVote
|
||||
{
|
||||
public:
|
||||
CTxIn vinMasternode;
|
||||
bool approved;
|
||||
CTransaction tx;
|
||||
uint256 txHash;
|
||||
int nBlockHeight;
|
||||
std::vector<unsigned char> vchMasterNodeSignature;
|
||||
|
||||
@ -56,9 +57,8 @@ public:
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(tx);
|
||||
READWRITE(txHash);
|
||||
READWRITE(vinMasternode);
|
||||
READWRITE(approved);
|
||||
READWRITE(vchMasterNodeSignature);
|
||||
READWRITE(nBlockHeight);
|
||||
)
|
||||
@ -68,25 +68,18 @@ class CTransactionLock
|
||||
{
|
||||
public:
|
||||
int nBlockHeight;
|
||||
CTransaction tx;
|
||||
uint256 txHash;
|
||||
std::vector<CConsensusVote> vecConsensusVotes;
|
||||
int nExpiration;
|
||||
|
||||
bool SignaturesValid();
|
||||
int CountSignatures();
|
||||
bool AllInFavor();
|
||||
void AddSignature(CConsensusVote cv);
|
||||
|
||||
uint256 GetHash()
|
||||
{
|
||||
return tx.GetHash();
|
||||
return txHash;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(tx);
|
||||
READWRITE(nBlockHeight);
|
||||
READWRITE(vecConsensusVotes);
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
|
117
src/main.cpp
117
src/main.cpp
@ -26,6 +26,7 @@
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
@ -1196,7 +1197,7 @@ int CMerkleTx::GetBlocksToMaturity() const
|
||||
{
|
||||
if (!IsCoinBase())
|
||||
return 0;
|
||||
return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
|
||||
return max(0, COINBASE_MATURITY - GetDepthInMainChain());
|
||||
}
|
||||
|
||||
|
||||
@ -2115,7 +2116,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
*/
|
||||
bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
{
|
||||
/* // All modifications to the coin state will be done in this cache.
|
||||
/*
|
||||
// All modifications to the coin state will be done in this cache.
|
||||
// Only when all have succeeded, we push it to pcoinsTip.
|
||||
CCoinsViewCache view(*pcoinsTip, true);
|
||||
|
||||
@ -2126,7 +2128,9 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
bool foundConflictingTx = false;
|
||||
|
||||
//remove anything conflicting in the memory pool
|
||||
mempool.removeConflicts(txLock);
|
||||
list<CTransaction> txConflicted;
|
||||
mempool.removeConflicts(txLock, txConflicted);
|
||||
|
||||
|
||||
// List of what to disconnect (typically nothing)
|
||||
vector<CBlockIndex*> vDisconnect;
|
||||
@ -2136,7 +2140,7 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
pindexNew = BlockReading->pprev; //new best block
|
||||
|
||||
CBlock block;
|
||||
if (!block.ReadFromDisk(BlockReading))
|
||||
if (!ReadBlockFromDisk(block, BlockReading))
|
||||
return state.Abort(_("Failed to read block"));
|
||||
|
||||
// Queue memory transactions to resurrect.
|
||||
@ -2162,7 +2166,7 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
}
|
||||
|
||||
if (vDisconnect.size() > 0) {
|
||||
LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %"PRIszu" blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString().c_str());
|
||||
LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %lli blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString().c_str());
|
||||
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
|
||||
LogPrintf(" -- disconnect %s\n", pindex->GetBlockHash().ToString().c_str());
|
||||
}
|
||||
@ -2172,10 +2176,10 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
vector<CTransaction> vResurrect;
|
||||
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
|
||||
CBlock block;
|
||||
if (!block.ReadFromDisk(pindex))
|
||||
if (!ReadBlockFromDisk(block, pindex))
|
||||
return state.Abort(_("Failed to read block"));
|
||||
int64 nStart = GetTimeMicros();
|
||||
if (!block.DisconnectBlock(state, pindex, view))
|
||||
int64_t nStart = GetTimeMicros();
|
||||
if (!DisconnectBlock(block, state, pindex, view))
|
||||
return error("DisconnectBlockAndInputs/SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str());
|
||||
if (fBenchmark)
|
||||
LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
|
||||
@ -2197,21 +2201,7 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
|
||||
}
|
||||
|
||||
// Make sure it's successfully written to disk before changing memory structure
|
||||
bool fIsInitialDownload = IsInitialBlockDownload();
|
||||
if (!fIsInitialDownload || pcoinsTip->GetCacheSize() > nCoinCacheSize) {
|
||||
// Typical CCoins structures on disk are around 100 bytes in size.
|
||||
// Pushing a new one to the database can cause it to be written
|
||||
// twice (once in the log, and once in the tables). This is already
|
||||
// an overestimation, as most will delete an existing entry or
|
||||
// overwrite one. Still, use a conservative safety factor of 2.
|
||||
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
|
||||
return state.Error();
|
||||
FlushBlockFile();
|
||||
pblocktree->Sync();
|
||||
if (!pcoinsTip->Flush())
|
||||
return state.Abort(_("Failed to write to coin database"));
|
||||
}
|
||||
mempool.check(pcoinsTip);
|
||||
|
||||
// At this point, all changes have been done to the database.
|
||||
// Proceed by updating the memory structures.
|
||||
@ -2225,11 +2215,12 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
BOOST_FOREACH(CTransaction& tx, vResurrect) {
|
||||
// ignore validation errors in resurrected transactions
|
||||
CValidationState stateDummy;
|
||||
if (!tx.AcceptToMemoryPool(stateDummy, true, false))
|
||||
if (!tx.AcceptToMemoryPool(mempool, stateDummy, tx, true, false))
|
||||
mempool.remove(tx, true);
|
||||
}
|
||||
|
||||
// Update best block in wallet (so we can detect restored wallets)
|
||||
|
||||
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
|
||||
{
|
||||
const CBlockLocator locator(pindexNew);
|
||||
@ -2274,8 +2265,8 @@ bool DisconnectBlockAndInputs(CValidationState &state, CTransaction txLock)
|
||||
boost::replace_all(strCmd, "%s", hashBestChain.GetHex());
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
|
||||
*/ return true;
|
||||
}
|
||||
|
||||
void static FlushBlockFile(bool fFinalize = false)
|
||||
@ -4002,13 +3993,27 @@ void static ProcessGetData(CNode* pfrom)
|
||||
}
|
||||
}
|
||||
if (!pushed && inv.type == MSG_TX) {
|
||||
CTransaction tx;
|
||||
if (mempool.lookup(inv.hash, tx)) {
|
||||
|
||||
if(mapDarksendBroadcastTxes.count(inv.hash)){
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(1000);
|
||||
ss << tx;
|
||||
pfrom->PushMessage("tx", ss);
|
||||
ss <<
|
||||
mapDarksendBroadcastTxes[inv.hash].tx <<
|
||||
mapDarksendBroadcastTxes[inv.hash].vin <<
|
||||
mapDarksendBroadcastTxes[inv.hash].vchSig <<
|
||||
mapDarksendBroadcastTxes[inv.hash].sigTime;
|
||||
|
||||
pfrom->PushMessage("dstx", ss);
|
||||
pushed = true;
|
||||
} else {
|
||||
CTransaction tx;
|
||||
if (mempool.lookup(inv.hash, tx)) {
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(1000);
|
||||
ss << tx;
|
||||
pfrom->PushMessage("tx", ss);
|
||||
pushed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pushed) {
|
||||
@ -4381,12 +4386,58 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "tx")
|
||||
else if (strCommand == "tx"|| strCommand == "dstx")
|
||||
{
|
||||
vector<uint256> vWorkQueue;
|
||||
vector<uint256> vEraseQueue;
|
||||
CTransaction tx;
|
||||
vRecv >> tx;
|
||||
|
||||
//masternode signed transaction
|
||||
bool allowFree = false;
|
||||
CTxIn vin;
|
||||
vector<unsigned char> vchSig;
|
||||
int64_t sigTime;
|
||||
|
||||
if(strCommand == "tx") {
|
||||
vRecv >> tx;
|
||||
} else if (strCommand == "dstx") {
|
||||
//these allow masternodes to publish a limited amount of free transactions
|
||||
vRecv >> tx >> vin >> vchSig >> sigTime;
|
||||
|
||||
BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
|
||||
if(mn.vin == vin) {
|
||||
if(!mn.allowFreeTx){
|
||||
//multiple peers can send us a valid masternode transaction
|
||||
if(fDebug) LogPrintf("dstx: Masternode sending too many transactions %s\n", tx.GetHash().ToString().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast<std::string>(sigTime);
|
||||
|
||||
std::string errorMessage = "";
|
||||
if(!darkSendSigner.VerifyMessage(mn.pubkey2, vchSig, strMessage, errorMessage)){
|
||||
LogPrintf("dstx: Got bad masternode address signature %s \n", vin.ToString().c_str());
|
||||
//pfrom->Misbehaving(20);
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrintf("dstx: Got Masternode transaction %s\n", tx.GetHash().ToString().c_str());
|
||||
|
||||
allowFree = true;
|
||||
mn.allowFreeTx = false;
|
||||
|
||||
if(!mapDarksendBroadcastTxes.count(tx.GetHash())){
|
||||
CDarksendBroadcastTx dstx;
|
||||
dstx.tx = tx;
|
||||
dstx.vin = vin;
|
||||
dstx.vchSig = vchSig;
|
||||
dstx.sigTime = sigTime;
|
||||
|
||||
mapDarksendBroadcastTxes.insert(make_pair(tx.GetHash(), dstx));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CInv inv(MSG_TX, tx.GetHash());
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
@ -4395,7 +4446,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
bool fMissingInputs = false;
|
||||
CValidationState state;
|
||||
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
|
||||
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, allowFree))
|
||||
{
|
||||
mempool.check(pcoinsTip);
|
||||
RelayTransaction(tx, inv.hash);
|
||||
|
@ -1124,7 +1124,7 @@ protected:
|
||||
virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0;
|
||||
virtual void EraseFromWallet(const uint256 &hash) =0;
|
||||
virtual void SetBestChain(const CBlockLocator &locator) =0;
|
||||
virtual void UpdatedTransaction(const uint256 &hash) =0;
|
||||
virtual bool UpdatedTransaction(const uint256 &hash) =0;
|
||||
virtual void Inventory(const uint256 &hash) =0;
|
||||
virtual void ResendWalletTransactions() =0;
|
||||
friend void ::RegisterWallet(CWalletInterface*);
|
||||
|
@ -18,8 +18,6 @@ map<uint256, int> mapSeenMasternodeScanningErrors;
|
||||
std::map<CNetAddr, int64_t> askedForMasternodeList;
|
||||
// which masternodes we've asked for
|
||||
std::map<COutPoint, int64_t> askedForMasternodeListEntry;
|
||||
// which masternodes we've asked for
|
||||
std::map<int, CScript> cacheBlockPayee;
|
||||
|
||||
// manage the masternode connections
|
||||
void ProcessMasternodeConnections(){
|
||||
@ -68,6 +66,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
|
||||
}
|
||||
|
||||
bool isLocal = addr.IsRFC1918() || addr.IsLocal();
|
||||
if(RegTest()) isLocal = false;
|
||||
|
||||
std::string vchPubKey(pubkey.begin(), pubkey.end());
|
||||
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
|
||||
|
||||
@ -359,22 +359,6 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
|
||||
if(masternodePayments.AddWinningMasternode(winner)){
|
||||
masternodePayments.Relay(winner);
|
||||
}
|
||||
|
||||
if(chainActive.Tip()){
|
||||
//cache payments
|
||||
int success = 0;
|
||||
int fail = 0;
|
||||
for(int nBlockHeight = chainActive.Tip()->nHeight; nBlockHeight < chainActive.Tip()->nHeight+10; nBlockHeight++){
|
||||
CScript payee;
|
||||
if(masternodePayments.GetBlockPayee(nBlockHeight, payee)){
|
||||
success++;
|
||||
} else {
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
LogPrintf("mnw - cached block payees - success %d fail %d\n", success, fail);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,29 +645,10 @@ uint64_t CMasternodePayments::CalculateScore(uint256 blockHash, CTxIn& vin)
|
||||
|
||||
bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
||||
{
|
||||
|
||||
// if it's cached, use it
|
||||
if(cacheBlockPayee.count(nBlockHeight)){
|
||||
payee = cacheBlockPayee[nBlockHeight];
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
||||
if(winner.nBlockHeight == nBlockHeight) {
|
||||
|
||||
CTransaction tx;
|
||||
uint256 hash;
|
||||
if(GetTransaction(winner.vin.prevout.hash, tx, hash, true)){
|
||||
BOOST_FOREACH(CTxOut out, tx.vout){
|
||||
if(out.nValue == 1000*COIN){
|
||||
payee = out.scriptPubKey;
|
||||
cacheBlockPayee.insert(make_pair(nBlockHeight, payee));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
payee = winner.payee;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,6 +683,7 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
|
||||
if(winner.score < winnerIn.score){
|
||||
winner.score = winnerIn.score;
|
||||
winner.vin = winnerIn.vin;
|
||||
winner.payee = winnerIn.payee;
|
||||
winner.vchSig = winnerIn.vchSig;
|
||||
return true;
|
||||
}
|
||||
@ -749,20 +715,6 @@ void CMasternodePayments::CleanPaymentList()
|
||||
}
|
||||
}
|
||||
|
||||
int CMasternodePayments::LastPayment(CMasterNode& mn)
|
||||
{
|
||||
if(chainActive.Tip() == NULL) return 0;
|
||||
|
||||
int ret = mn.GetMasternodeInputAge();
|
||||
|
||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
||||
if(winner.vin == mn.vin && chainActive.Tip()->nHeight - winner.nBlockHeight < ret)
|
||||
ret = chainActive.Tip()->nHeight - winner.nBlockHeight;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
{
|
||||
if(!enabled) return false;
|
||||
@ -795,6 +747,8 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
winner.score = 0;
|
||||
winner.nBlockHeight = nBlockHeight;
|
||||
winner.vin = mn.vin;
|
||||
winner.payee.SetDestination(mn.pubkey.GetID());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,7 @@ class CMasternodePaymentWinner
|
||||
public:
|
||||
int nBlockHeight;
|
||||
CTxIn vin;
|
||||
CScript payee;
|
||||
std::vector<unsigned char> vchSig;
|
||||
uint64_t score;
|
||||
|
||||
@ -165,6 +166,7 @@ public:
|
||||
nBlockHeight = 0;
|
||||
score = 0;
|
||||
vin = CTxIn();
|
||||
payee = CScript();
|
||||
}
|
||||
|
||||
uint256 GetHash(){
|
||||
@ -176,8 +178,9 @@ public:
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
READWRITE(nBlockHeight);
|
||||
READWRITE(score);
|
||||
READWRITE(payee);
|
||||
READWRITE(vin);
|
||||
READWRITE(score);
|
||||
READWRITE(vchSig);
|
||||
)
|
||||
};
|
||||
|
13
src/net.cpp
13
src/net.cpp
@ -434,9 +434,16 @@ CNode* FindNode(std::string addrName)
|
||||
CNode* FindNode(const CService& addr)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if(pnode->addr == addr)
|
||||
return (pnode);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes){
|
||||
if(RegTest()){
|
||||
//if using regtest, just check the IP
|
||||
if((CNetAddr)pnode->addr == (CNetAddr)addr)
|
||||
return (pnode);
|
||||
} else {
|
||||
if(pnode->addr == addr)
|
||||
return (pnode);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,11 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64
|
||||
bool showImmature = immatureBalance != 0;
|
||||
ui->labelImmature->setVisible(showImmature);
|
||||
ui->labelImmatureText->setVisible(showImmature);
|
||||
|
||||
if(cachedTxLocks != nCompleteTXLocks){
|
||||
cachedTxLocks = nCompleteTXLocks;
|
||||
ui->listTransactions->update();
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewPage::setClientModel(ClientModel *model)
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
qint64 currentUnconfirmedBalance;
|
||||
qint64 currentImmatureBalance;
|
||||
qint64 currentAnonymizedBalance;
|
||||
qint64 cachedTxLocks;
|
||||
qint64 lastNewBlock;
|
||||
|
||||
int showingDarkSendMessage;
|
||||
|
@ -121,11 +121,11 @@ void WalletModel::pollBalanceChanged()
|
||||
// Balance and number of transactions might have changed
|
||||
cachedNumBlocks = chainActive.Height();
|
||||
cachedDarksendRounds = nDarksendRounds;
|
||||
cachedTxLocks = nCompleteTXLocks;
|
||||
|
||||
checkBalanceChanged();
|
||||
if(transactionTableModel)
|
||||
if(transactionTableModel){
|
||||
transactionTableModel->updateConfirmations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,12 +136,14 @@ void WalletModel::checkBalanceChanged()
|
||||
qint64 newImmatureBalance = getImmatureBalance();
|
||||
qint64 newAnonymizedBalance = getAnonymizedBalance();
|
||||
|
||||
if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance|| cachedAnonymizedBalance != newAnonymizedBalance)
|
||||
if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance|| cachedAnonymizedBalance != newAnonymizedBalance || cachedTxLocks != nCompleteTXLocks)
|
||||
{
|
||||
cachedBalance = newBalance;
|
||||
cachedUnconfirmedBalance = newUnconfirmedBalance;
|
||||
cachedImmatureBalance = newImmatureBalance;
|
||||
cachedAnonymizedBalance = newAnonymizedBalance;
|
||||
cachedTxLocks = nCompleteTXLocks;
|
||||
|
||||
emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, newAnonymizedBalance);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ extern const std::string CLIENT_DATE;
|
||||
// network protocol versioning
|
||||
//
|
||||
|
||||
static const int PROTOCOL_VERSION = 70055;
|
||||
static const int PROTOCOL_VERSION = 70057;
|
||||
|
||||
// intial proto version, to be increased after version/verack negotiation
|
||||
static const int INIT_PROTO_VERSION = 209;
|
||||
|
@ -1250,7 +1250,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
|
||||
continue;
|
||||
|
||||
int nDepth = pcoin->GetDepthInMainChain(false);
|
||||
if (nDepth < minimum_confirmations)
|
||||
if (nDepth <= minimum_confirmations)
|
||||
continue;
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
|
||||
@ -2736,15 +2736,18 @@ void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
||||
bool CWallet::UpdatedTransaction(const uint256 &hashTx)
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
// Only notify UI if this transaction is in this wallet
|
||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
|
||||
if (mi != mapWallet.end())
|
||||
if (mi != mapWallet.end()){
|
||||
NotifyTransactionChanged(this, hashTx, CT_UPDATED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWallet::LockCoin(COutPoint& output)
|
||||
|
@ -400,7 +400,7 @@ public:
|
||||
|
||||
bool DelAddressBook(const CTxDestination& address);
|
||||
|
||||
void UpdatedTransaction(const uint256 &hashTx);
|
||||
bool UpdatedTransaction(const uint256 &hashTx);
|
||||
|
||||
void Inventory(const uint256 &hash)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user