Merge downstream 0.11.1

This commit is contained in:
vertoe 2015-02-03 19:35:56 +01:00
commit 4cdb18fa4f
17 changed files with 260 additions and 157 deletions

View File

@ -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])

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
)
};

View File

@ -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);

View File

@ -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*);

View File

@ -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;
}

View File

@ -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);
)
};

View File

@ -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;
}

View File

@ -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)

View File

@ -50,6 +50,7 @@ private:
qint64 currentUnconfirmedBalance;
qint64 currentImmatureBalance;
qint64 currentAnonymizedBalance;
qint64 cachedTxLocks;
qint64 lastNewBlock;
int showingDarkSendMessage;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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)
{