Auto merge of #5009 - LarryRuane:upstream-locking-0.14, r=str4d
Bitcoin 0.14 locking PRs These are locking changes from upstream (bitcoin core) release 0.14, oldest to newest (when merged to the master branch). Each commit also includes a reference both to the PR and the upstream commit. - bitcoin/bitcoin#8472 - bitcoin/bitcoin#8606 - Excludes a lock move because we don't have bitcoin/bitcoin#7840 which this move was partially-reverting. - bitcoin/bitcoin#9230 - Only first commit (we don't have `LogTimestampStr` anymore). - bitcoin/bitcoin#9243 - Only the sixth commit, excluding `IsArgSet` locking (we haven't pulled that function in yet). - bitcoin/bitcoin#9626 - The cherry-picked commit does not match the upstream at all, but the resulting lock is useful. - bitcoin/bitcoin#9679 - bitcoin/bitcoin#9227 - bitcoin/bitcoin#9698 - Excludes change to `CConnman::PushMessage` in second commit (which we don't have yet). - bitcoin/bitcoin#9708 - bitcoin/bitcoin#9771
This commit is contained in:
commit
80e66e7daa
|
@ -119,7 +119,7 @@ public:
|
|||
void Run()
|
||||
{
|
||||
ThreadCounter count(*this);
|
||||
while (running) {
|
||||
while (true) {
|
||||
std::unique_ptr<WorkItem> i;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(cs);
|
||||
|
|
65
src/main.cpp
65
src/main.cpp
|
@ -65,7 +65,7 @@ CCriticalSection cs_main;
|
|||
BlockMap mapBlockIndex;
|
||||
CChain chainActive;
|
||||
CBlockIndex *pindexBestHeader = NULL;
|
||||
static int64_t nTimeBestReceived = 0;
|
||||
static std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of when we last received a block
|
||||
CWaitableCriticalSection csBestBlock;
|
||||
CConditionVariable cvBlockChange;
|
||||
int nScriptCheckThreads = 0;
|
||||
|
@ -362,7 +362,7 @@ int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consens
|
|||
void InitializeNode(NodeId nodeid, const CNode *pnode) {
|
||||
LOCK(cs_main);
|
||||
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
|
||||
state.name = pnode->addrName;
|
||||
state.name = pnode->GetAddrName();
|
||||
state.address = pnode->addr;
|
||||
}
|
||||
|
||||
|
@ -5594,10 +5594,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|||
pfrom->PushMessage("block", block);
|
||||
else // MSG_FILTERED_BLOCK)
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter)
|
||||
bool send = false;
|
||||
CMerkleBlock merkleBlock;
|
||||
{
|
||||
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter) {
|
||||
send = true;
|
||||
merkleBlock = CMerkleBlock(block, *pfrom->pfilter);
|
||||
}
|
||||
}
|
||||
if (send) {
|
||||
pfrom->PushMessage("merkleblock", merkleBlock);
|
||||
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
|
||||
// This avoids hurting performance by pointlessly requiring a round-trip
|
||||
|
@ -5712,7 +5718,11 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
CAddress addrMe;
|
||||
CAddress addrFrom;
|
||||
uint64_t nNonce = 1;
|
||||
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
|
||||
std::string strSubVer;
|
||||
std::string cleanSubVer;
|
||||
uint64_t nServices;
|
||||
vRecv >> pfrom->nVersion >> nServices >> nTime >> addrMe;
|
||||
pfrom->nServices = nServices;
|
||||
if (pfrom->nVersion < MIN_PEER_PROTO_VERSION)
|
||||
{
|
||||
// disconnect from peers older than this proto version
|
||||
|
@ -5745,11 +5755,14 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
if (!vRecv.empty())
|
||||
vRecv >> addrFrom >> nNonce;
|
||||
if (!vRecv.empty()) {
|
||||
vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH);
|
||||
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer, SAFE_CHARS_SUBVERSION);
|
||||
vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
|
||||
cleanSubVer = SanitizeString(strSubVer, SAFE_CHARS_SUBVERSION);
|
||||
}
|
||||
if (!vRecv.empty()) {
|
||||
int nStartingHeight;
|
||||
vRecv >> nStartingHeight;
|
||||
pfrom->nStartingHeight = nStartingHeight;
|
||||
}
|
||||
if (!vRecv.empty())
|
||||
vRecv >> pfrom->nStartingHeight;
|
||||
if (!vRecv.empty())
|
||||
vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message
|
||||
else
|
||||
|
@ -5763,7 +5776,7 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
return true;
|
||||
}
|
||||
|
||||
pfrom->addrLocal = addrMe;
|
||||
pfrom->SetAddrLocal(addrMe);
|
||||
if (pfrom->fInbound && addrMe.IsRoutable())
|
||||
{
|
||||
SeenLocal(addrMe);
|
||||
|
@ -5773,6 +5786,11 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
if (pfrom->fInbound)
|
||||
pfrom->PushVersion();
|
||||
|
||||
{
|
||||
LOCK(pfrom->cs_SubVer);
|
||||
pfrom->strSubVer = strSubVer;
|
||||
pfrom->cleanSubVer = cleanSubVer;
|
||||
}
|
||||
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
|
||||
|
||||
// Potentially mark this peer as a preferred download peer.
|
||||
|
@ -5797,7 +5815,7 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
|
||||
pfrom->PushAddress(addr, insecure_rand);
|
||||
} else if (IsPeerAddrLocalGood(pfrom)) {
|
||||
addr.SetIP(pfrom->addrLocal);
|
||||
addr.SetIP(addrMe);
|
||||
LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
|
||||
pfrom->PushAddress(addr, insecure_rand);
|
||||
}
|
||||
|
@ -5832,7 +5850,7 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
|
||||
|
||||
LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
|
||||
pfrom->cleanSubVer, pfrom->nVersion,
|
||||
cleanSubVer, pfrom->nVersion,
|
||||
pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
|
||||
remoteAddr);
|
||||
|
||||
|
@ -6476,7 +6494,7 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
if (pingUsecTime > 0) {
|
||||
// Successful ping time measurement, replace previous
|
||||
pfrom->nPingUsecTime = pingUsecTime;
|
||||
pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime, pingUsecTime);
|
||||
pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime.load(), pingUsecTime);
|
||||
} else {
|
||||
// This should never happen
|
||||
sProblem = "Timing mishap";
|
||||
|
@ -6578,9 +6596,9 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
delete pfrom->pfilter;
|
||||
pfrom->pfilter = new CBloomFilter(filter);
|
||||
pfrom->pfilter->UpdateEmptyFull();
|
||||
}
|
||||
pfrom->fRelayTxes = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "filteradd")
|
||||
|
@ -6590,21 +6608,22 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
|||
|
||||
// Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
|
||||
// and thus, the maximum size any matched object can have) in a filteradd message
|
||||
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
bool bad = false;
|
||||
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
|
||||
bad = true;
|
||||
} else {
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter)
|
||||
if (pfrom->pfilter) {
|
||||
pfrom->pfilter->insert(vData);
|
||||
else
|
||||
{
|
||||
} else {
|
||||
bad = true;
|
||||
}
|
||||
}
|
||||
if (bad) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "filterclear")
|
||||
|
|
143
src/net.cpp
143
src/net.cpp
|
@ -192,8 +192,9 @@ int GetnScore(const CService& addr)
|
|||
// Is our peer's addrLocal potentially useful as an external IP source?
|
||||
bool IsPeerAddrLocalGood(CNode *pnode)
|
||||
{
|
||||
return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
|
||||
!IsLimited(pnode->addrLocal.GetNetwork());
|
||||
CService addrLocal = pnode->GetAddrLocal();
|
||||
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
|
||||
!IsLimited(addrLocal.GetNetwork());
|
||||
}
|
||||
|
||||
// pushes our own address to a peer
|
||||
|
@ -208,7 +209,7 @@ void AdvertizeLocal(CNode *pnode)
|
|||
if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
|
||||
GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
|
||||
{
|
||||
addrLocal.SetIP(pnode->addrLocal);
|
||||
addrLocal.SetIP(pnode->GetAddrLocal());
|
||||
}
|
||||
if (addrLocal.IsRoutable())
|
||||
{
|
||||
|
@ -350,9 +351,11 @@ CNode* FindNode(const CSubNet& subNet)
|
|||
CNode* FindNode(const std::string& addrName)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes)
|
||||
if (pnode->addrName == addrName)
|
||||
for (CNode* pnode : vNodes) {
|
||||
if (pnode->GetAddrName() == addrName) {
|
||||
return (pnode);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -372,6 +375,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
|||
return NULL;
|
||||
|
||||
// Look for an existing connection
|
||||
LOCK(cs_vNodes);
|
||||
CNode* pnode = FindNode((CService)addrConnect);
|
||||
if (pnode)
|
||||
{
|
||||
|
@ -408,8 +412,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
|||
vNodes.push_back(pnode);
|
||||
}
|
||||
|
||||
pnode->nTimeConnected = GetTime();
|
||||
|
||||
return pnode;
|
||||
} else if (!proxyConnectionFailed) {
|
||||
// If connecting to the node failed, and failure is not caused by a problem connecting to
|
||||
|
@ -443,11 +445,13 @@ static void DumpBanlist()
|
|||
void CNode::CloseSocketDisconnect()
|
||||
{
|
||||
fDisconnect = true;
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
{
|
||||
LOCK(cs_hSocket);
|
||||
if (hSocket != INVALID_SOCKET) {
|
||||
LogPrint("net", "disconnecting peer=%d\n", id);
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
}
|
||||
|
||||
// in case this fails, we'll empty the recv buffer when the CNode is deleted
|
||||
TRY_LOCK(cs_vRecvMsg, lockRecv);
|
||||
|
@ -636,22 +640,61 @@ void CNode::AddWhitelistedRange(const CSubNet &subnet) {
|
|||
vWhitelistedRange.push_back(subnet);
|
||||
}
|
||||
|
||||
|
||||
std::string CNode::GetAddrName() const {
|
||||
LOCK(cs_addrName);
|
||||
return addrName;
|
||||
}
|
||||
|
||||
void CNode::MaybeSetAddrName(const std::string& addrNameIn) {
|
||||
LOCK(cs_addrName);
|
||||
if (addrName.empty()) {
|
||||
addrName = addrNameIn;
|
||||
}
|
||||
}
|
||||
|
||||
CService CNode::GetAddrLocal() const {
|
||||
LOCK(cs_addrLocal);
|
||||
return addrLocal;
|
||||
}
|
||||
|
||||
void CNode::SetAddrLocal(const CService& addrLocalIn) {
|
||||
LOCK(cs_addrLocal);
|
||||
if (addrLocal.IsValid()) {
|
||||
error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToString(), addrLocalIn.ToString());
|
||||
} else {
|
||||
addrLocal = addrLocalIn;
|
||||
}
|
||||
}
|
||||
|
||||
void CNode::copyStats(CNodeStats &stats)
|
||||
{
|
||||
stats.nodeid = this->GetId();
|
||||
stats.nServices = nServices;
|
||||
{
|
||||
LOCK(cs_filter);
|
||||
stats.fRelayTxes = fRelayTxes;
|
||||
}
|
||||
stats.nLastSend = nLastSend;
|
||||
stats.nLastRecv = nLastRecv;
|
||||
stats.nTimeConnected = nTimeConnected;
|
||||
stats.nTimeOffset = nTimeOffset;
|
||||
stats.addrName = addrName;
|
||||
stats.addrName = GetAddrName();
|
||||
stats.nVersion = nVersion;
|
||||
{
|
||||
LOCK(cs_SubVer);
|
||||
stats.cleanSubVer = cleanSubVer;
|
||||
}
|
||||
stats.fInbound = fInbound;
|
||||
stats.nStartingHeight = nStartingHeight;
|
||||
{
|
||||
LOCK(cs_vSend);
|
||||
stats.nSendBytes = nSendBytes;
|
||||
}
|
||||
{
|
||||
LOCK(cs_vRecv);
|
||||
stats.nRecvBytes = nRecvBytes;
|
||||
}
|
||||
stats.fWhitelisted = fWhitelisted;
|
||||
|
||||
// It is common for nodes with good ping times to suddenly become lagged,
|
||||
|
@ -670,7 +713,8 @@ void CNode::copyStats(CNodeStats &stats)
|
|||
stats.dPingWait = (((double)nPingUsecWait) / 1e6);
|
||||
|
||||
// Leave string empty if addrLocal invalid (not filled in yet)
|
||||
stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
|
||||
CService addrLocalUnlocked = GetAddrLocal();
|
||||
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
|
||||
}
|
||||
|
||||
// requires LOCK(cs_vRecvMsg)
|
||||
|
@ -780,10 +824,19 @@ void SocketSendData(CNode *pnode)
|
|||
while (it != pnode->vSendMsg.end()) {
|
||||
const CSerializeData &data = *it;
|
||||
assert(data.size() > pnode->nSendOffset);
|
||||
int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
int nBytes = 0;
|
||||
{
|
||||
LOCK(pnode->cs_hSocket);
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
break;
|
||||
nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
}
|
||||
if (nBytes > 0) {
|
||||
pnode->nLastSend = GetTime();
|
||||
{
|
||||
LOCK(pnode->cs_vSend);
|
||||
pnode->nSendBytes += nBytes;
|
||||
}
|
||||
pnode->nSendOffset += nBytes;
|
||||
pnode->RecordBytesSent(nBytes);
|
||||
if (pnode->nSendOffset == data.size()) {
|
||||
|
@ -1142,12 +1195,6 @@ void ThreadSocketHandler()
|
|||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes)
|
||||
{
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
FD_SET(pnode->hSocket, &fdsetError);
|
||||
hSocketMax = max(hSocketMax, pnode->hSocket);
|
||||
have_fds = true;
|
||||
|
||||
// Implement the following logic:
|
||||
// * If there is data to send, select() for sending data. As this only
|
||||
// happens when optimistic write failed, we choose to first drain the
|
||||
|
@ -1163,18 +1210,34 @@ void ThreadSocketHandler()
|
|||
// * We send some data.
|
||||
// * We wait for data to be received (and disconnect after timeout).
|
||||
// * We process a message in the buffer (message handler thread).
|
||||
|
||||
bool select_send;
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend && !pnode->vSendMsg.empty()) {
|
||||
select_send = lockSend && !pnode->vSendMsg.empty();
|
||||
}
|
||||
|
||||
bool select_recv;
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
|
||||
select_recv = lockRecv && (
|
||||
pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
|
||||
pnode->GetTotalRecvSize() <= ReceiveFloodSize());
|
||||
}
|
||||
|
||||
LOCK(pnode->cs_hSocket);
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
|
||||
FD_SET(pnode->hSocket, &fdsetError);
|
||||
hSocketMax = max(hSocketMax, pnode->hSocket);
|
||||
have_fds = true;
|
||||
|
||||
if (select_send) {
|
||||
FD_SET(pnode->hSocket, &fdsetSend);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
|
||||
if (lockRecv && (
|
||||
pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() ||
|
||||
pnode->GetTotalRecvSize() <= ReceiveFloodSize()))
|
||||
if (select_recv) {
|
||||
FD_SET(pnode->hSocket, &fdsetRecv);
|
||||
}
|
||||
}
|
||||
|
@ -1228,9 +1291,18 @@ void ThreadSocketHandler()
|
|||
//
|
||||
// Receive
|
||||
//
|
||||
bool recvSet = false;
|
||||
bool sendSet = false;
|
||||
bool errorSet = false;
|
||||
{
|
||||
LOCK(pnode->cs_hSocket);
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
|
||||
recvSet = FD_ISSET(pnode->hSocket, &fdsetRecv);
|
||||
sendSet = FD_ISSET(pnode->hSocket, &fdsetSend);
|
||||
errorSet = FD_ISSET(pnode->hSocket, &fdsetError);
|
||||
}
|
||||
if (recvSet || errorSet)
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
|
||||
if (lockRecv)
|
||||
|
@ -1238,13 +1310,22 @@ void ThreadSocketHandler()
|
|||
{
|
||||
// typical socket buffer is 8K-64K
|
||||
char pchBuf[0x10000];
|
||||
int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
|
||||
int nBytes = 0;
|
||||
{
|
||||
LOCK(pnode->cs_hSocket);
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
|
||||
}
|
||||
if (nBytes > 0)
|
||||
{
|
||||
if (!pnode->ReceiveMsgBytes(pchBuf, nBytes))
|
||||
pnode->CloseSocketDisconnect();
|
||||
pnode->nLastRecv = GetTime();
|
||||
{
|
||||
LOCK(pnode->cs_vRecv);
|
||||
pnode->nRecvBytes += nBytes;
|
||||
}
|
||||
pnode->RecordBytesRecv(nBytes);
|
||||
}
|
||||
else if (nBytes == 0)
|
||||
|
@ -1272,9 +1353,7 @@ void ThreadSocketHandler()
|
|||
//
|
||||
// Send
|
||||
//
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
if (FD_ISSET(pnode->hSocket, &fdsetSend))
|
||||
if (sendSet)
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend)
|
||||
|
@ -1931,9 +2010,11 @@ public:
|
|||
~CNetCleanup()
|
||||
{
|
||||
// Close sockets
|
||||
for (CNode* pnode : vNodes)
|
||||
for (CNode* pnode : vNodes) {
|
||||
LOCK(pnode->cs_hSocket);
|
||||
if (pnode->hSocket != INVALID_SOCKET)
|
||||
CloseSocket(pnode->hSocket);
|
||||
}
|
||||
for (ListenSocket& hListenSocket : vhListenSocket)
|
||||
if (hListenSocket.socket != INVALID_SOCKET)
|
||||
if (!CloseSocket(hListenSocket.socket))
|
||||
|
@ -2158,6 +2239,7 @@ unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAX
|
|||
|
||||
CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
|
||||
ssSend(SER_NETWORK, INIT_PROTO_VERSION),
|
||||
nTimeConnected(GetTime()),
|
||||
addr(addrIn),
|
||||
nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)),
|
||||
addrKnown(5000, 0.001),
|
||||
|
@ -2170,7 +2252,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
|
|||
nLastRecv = 0;
|
||||
nSendBytes = 0;
|
||||
nRecvBytes = 0;
|
||||
nTimeConnected = GetTime();
|
||||
nTimeOffset = 0;
|
||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||
nVersion = 0;
|
||||
|
|
42
src/net.h
42
src/net.h
|
@ -256,7 +256,7 @@ class CNode
|
|||
{
|
||||
public:
|
||||
// socket
|
||||
uint64_t nServices;
|
||||
std::atomic<uint64_t> nServices;
|
||||
SOCKET hSocket;
|
||||
CDataStream ssSend;
|
||||
std::string strSendCommand; // Current command being assembled in ssSend
|
||||
|
@ -265,6 +265,8 @@ public:
|
|||
uint64_t nSendBytes;
|
||||
std::deque<CSerializeData> vSendMsg;
|
||||
CCriticalSection cs_vSend;
|
||||
CCriticalSection cs_hSocket;
|
||||
CCriticalSection cs_vRecv;
|
||||
|
||||
std::deque<CInv> vRecvGetData;
|
||||
std::deque<CNetMessage> vRecvMsg;
|
||||
|
@ -272,19 +274,18 @@ public:
|
|||
uint64_t nRecvBytes;
|
||||
int nRecvVersion;
|
||||
|
||||
int64_t nLastSend;
|
||||
int64_t nLastRecv;
|
||||
int64_t nTimeConnected;
|
||||
int64_t nTimeOffset;
|
||||
std::atomic<int64_t> nLastSend;
|
||||
std::atomic<int64_t> nLastRecv;
|
||||
const int64_t nTimeConnected;
|
||||
std::atomic<int64_t> nTimeOffset;
|
||||
const CAddress addr;
|
||||
std::string addrName;
|
||||
CService addrLocal;
|
||||
int nVersion;
|
||||
// strSubVer is whatever byte array we read from the wire. However, this field is intended
|
||||
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
|
||||
// store the sanitized version in cleanSubVer. The original should be used when dealing with
|
||||
// the network or wire types and the cleaned string used when displayed or logged.
|
||||
std::string strSubVer, cleanSubVer;
|
||||
CCriticalSection cs_SubVer; // used for both cleanSubVer and strSubVer
|
||||
bool fWhitelisted; // This peer can bypass DoS banning.
|
||||
bool fOneShot;
|
||||
bool fClient;
|
||||
|
@ -301,8 +302,8 @@ public:
|
|||
CSemaphoreGrant grantOutbound;
|
||||
CCriticalSection cs_filter;
|
||||
CBloomFilter* pfilter;
|
||||
int nRefCount;
|
||||
NodeId id;
|
||||
std::atomic<int> nRefCount;
|
||||
|
||||
const uint64_t nKeyedNetGroup;
|
||||
|
||||
|
@ -328,7 +329,7 @@ protected:
|
|||
|
||||
public:
|
||||
uint256 hashContinue;
|
||||
int nStartingHeight;
|
||||
std::atomic<int> nStartingHeight;
|
||||
|
||||
// flood relay
|
||||
std::vector<CAddress> vAddrToSend;
|
||||
|
@ -345,15 +346,15 @@ public:
|
|||
|
||||
// Ping time measurement:
|
||||
// The pong reply we're expecting, or 0 if no pong expected.
|
||||
uint64_t nPingNonceSent;
|
||||
std::atomic<uint64_t> nPingNonceSent;
|
||||
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
|
||||
int64_t nPingUsecStart;
|
||||
std::atomic<int64_t> nPingUsecStart;
|
||||
// Last measured round-trip time.
|
||||
int64_t nPingUsecTime;
|
||||
std::atomic<int64_t> nPingUsecTime;
|
||||
// Best measured round-trip time.
|
||||
int64_t nMinPingUsecTime;
|
||||
std::atomic<int64_t> nMinPingUsecTime;
|
||||
// Whether a ping is requested.
|
||||
bool fPingQueued;
|
||||
std::atomic<bool> fPingQueued;
|
||||
|
||||
CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false);
|
||||
~CNode();
|
||||
|
@ -376,6 +377,12 @@ private:
|
|||
|
||||
static uint64_t CalculateKeyedNetGroup(const CAddress& ad);
|
||||
|
||||
|
||||
mutable CCriticalSection cs_addrName;
|
||||
std::string addrName;
|
||||
|
||||
CService addrLocal;
|
||||
mutable CCriticalSection cs_addrLocal;
|
||||
public:
|
||||
|
||||
// Regenerate the span for this CNode. This re-queries the log filter to see
|
||||
|
@ -412,6 +419,10 @@ public:
|
|||
msg.SetVersion(nVersionIn);
|
||||
}
|
||||
|
||||
CService GetAddrLocal() const;
|
||||
//! May not be called more than once
|
||||
void SetAddrLocal(const CService& addrLocalIn);
|
||||
|
||||
CNode* AddRef()
|
||||
{
|
||||
nRefCount++;
|
||||
|
@ -700,6 +711,9 @@ public:
|
|||
//!response the time in seconds left in the current max outbound cycle
|
||||
// in case of no limit, it will always respond with 0
|
||||
static uint64_t GetMaxOutboundTimeLeftInCycle();
|
||||
std::string GetAddrName() const;
|
||||
//! Sets the addrName only if it was not previously set
|
||||
void MaybeSetAddrName(const std::string& addrNameIn);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -68,9 +68,8 @@ static void CopyNodeStats(std::vector<CNodeStats>& vstats)
|
|||
LOCK(cs_vNodes);
|
||||
vstats.reserve(vNodes.size());
|
||||
for (CNode* pnode : vNodes) {
|
||||
CNodeStats stats;
|
||||
pnode->copyStats(stats);
|
||||
vstats.push_back(stats);
|
||||
vstats.emplace_back();
|
||||
pnode->copyStats(vstats.back());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,10 @@ public:
|
|||
|
||||
typedef CMutexLock<CCriticalSection> CCriticalBlock;
|
||||
|
||||
#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
|
||||
#define PASTE(x, y) x ## y
|
||||
#define PASTE2(x, y) PASTE(x, y)
|
||||
|
||||
#define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
|
||||
#define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__)
|
||||
#define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
|
||||
|
||||
|
|
16
src/util.cpp
16
src/util.cpp
|
@ -87,6 +87,7 @@ using namespace std;
|
|||
const char * const BITCOIN_CONF_FILENAME = "zcash.conf";
|
||||
const char * const BITCOIN_PID_FILENAME = "zcashd.pid";
|
||||
|
||||
CCriticalSection cs_args;
|
||||
map<string, string> mapArgs;
|
||||
map<string, vector<string> > mapMultiArgs;
|
||||
bool fDebug = false;
|
||||
|
@ -113,6 +114,7 @@ static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
|
|||
|
||||
void ParseParameters(int argc, const char* const argv[])
|
||||
{
|
||||
LOCK(cs_args);
|
||||
mapArgs.clear();
|
||||
mapMultiArgs.clear();
|
||||
|
||||
|
@ -148,6 +150,7 @@ void ParseParameters(int argc, const char* const argv[])
|
|||
|
||||
std::string GetArg(const std::string& strArg, const std::string& strDefault)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
if (mapArgs.count(strArg))
|
||||
return mapArgs[strArg];
|
||||
return strDefault;
|
||||
|
@ -155,6 +158,7 @@ std::string GetArg(const std::string& strArg, const std::string& strDefault)
|
|||
|
||||
int64_t GetArg(const std::string& strArg, int64_t nDefault)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
if (mapArgs.count(strArg))
|
||||
return atoi64(mapArgs[strArg]);
|
||||
return nDefault;
|
||||
|
@ -162,6 +166,7 @@ int64_t GetArg(const std::string& strArg, int64_t nDefault)
|
|||
|
||||
bool GetBoolArg(const std::string& strArg, bool fDefault)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
if (mapArgs.count(strArg))
|
||||
return InterpretBool(mapArgs[strArg]);
|
||||
return fDefault;
|
||||
|
@ -169,6 +174,7 @@ bool GetBoolArg(const std::string& strArg, bool fDefault)
|
|||
|
||||
bool SoftSetArg(const std::string& strArg, const std::string& strValue)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
if (mapArgs.count(strArg))
|
||||
return false;
|
||||
mapArgs[strArg] = strValue;
|
||||
|
@ -286,7 +292,7 @@ static fs::path ZC_GetDefaultBaseParamsDir()
|
|||
|
||||
const fs::path &ZC_GetParamsDir()
|
||||
{
|
||||
LOCK(csPathCached); // Reuse the same lock as upstream.
|
||||
LOCK2(cs_args, csPathCached);
|
||||
|
||||
fs::path &path = zc_paramsPathCached;
|
||||
|
||||
|
@ -313,6 +319,7 @@ const fs::path &ZC_GetParamsDir()
|
|||
const fs::path GetExportDir()
|
||||
{
|
||||
fs::path path;
|
||||
LOCK(cs_args);
|
||||
if (mapArgs.count("-exportdir")) {
|
||||
path = fs::system_complete(mapArgs["-exportdir"]);
|
||||
if (fs::exists(path) && !fs::is_directory(path)) {
|
||||
|
@ -328,8 +335,7 @@ const fs::path GetExportDir()
|
|||
|
||||
const fs::path &GetDataDir(bool fNetSpecific)
|
||||
{
|
||||
|
||||
LOCK(csPathCached);
|
||||
LOCK2(cs_args, csPathCached);
|
||||
|
||||
fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
|
||||
|
||||
|
@ -357,6 +363,7 @@ const fs::path &GetDataDir(bool fNetSpecific)
|
|||
|
||||
void ClearDatadirCache()
|
||||
{
|
||||
LOCK(csPathCached);
|
||||
pathCached = fs::path();
|
||||
pathCachedNetSpecific = fs::path();
|
||||
}
|
||||
|
@ -402,6 +409,8 @@ void ReadConfigFile(const std::string& confPath,
|
|||
};
|
||||
set<string> unique_options;
|
||||
|
||||
{
|
||||
LOCK(cs_args);
|
||||
for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
|
||||
{
|
||||
string strKey = string("-") + it->string_key;
|
||||
|
@ -420,6 +429,7 @@ void ReadConfigFile(const std::string& confPath,
|
|||
mapSettingsRet[strKey] = strValue;
|
||||
mapMultiSettingsRet[strKey].push_back(strValue);
|
||||
}
|
||||
}
|
||||
// If datadir is changed in .conf file:
|
||||
ClearDatadirCache();
|
||||
}
|
||||
|
|
|
@ -50,8 +50,9 @@ void MilliSleep(int64_t n)
|
|||
|
||||
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
|
||||
{
|
||||
static std::locale classic(std::locale::classic());
|
||||
// std::locale takes ownership of the pointer
|
||||
std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
|
||||
std::locale loc(classic, new boost::posix_time::time_facet(pszFormat));
|
||||
std::stringstream ss;
|
||||
ss.imbue(loc);
|
||||
ss << boost::posix_time::from_time_t(nTime);
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
using namespace std;
|
||||
|
||||
|
||||
unsigned int nWalletDBUpdated;
|
||||
|
||||
|
||||
//
|
||||
// CDB
|
||||
//
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
|
||||
static const bool DEFAULT_WALLET_PRIVDB = true;
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
|
||||
class CDBEnv
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -4835,7 +4835,7 @@ bool CWallet::InitLoadWallet(bool clearWitnessCaches)
|
|||
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||
nWalletDBUpdated++;
|
||||
CWalletDB::IncrementUpdateCounter();
|
||||
|
||||
// Restore wallet transaction metadata after -zapwallettxes=1
|
||||
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
||||
|
|
|
@ -20,18 +20,21 @@
|
|||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <atomic>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static uint64_t nAccountingEntryNumber = 0;
|
||||
|
||||
static std::atomic<unsigned int> nWalletDBUpdateCounter;
|
||||
|
||||
//
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(make_pair(string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
|
@ -39,37 +42,37 @@ bool CWalletDB::EraseName(const string& strAddress)
|
|||
{
|
||||
// This should only be used for sending addresses, never for receiving addresses,
|
||||
// receiving addresses must always have an address book entry if they're not change return.
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(make_pair(string("name"), strAddress));
|
||||
}
|
||||
|
||||
bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(make_pair(string("purpose"), strAddress), strPurpose);
|
||||
}
|
||||
|
||||
bool CWalletDB::ErasePurpose(const string& strPurpose)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(make_pair(string("purpose"), strPurpose));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteTx(uint256 hash, const CWalletTx& wtx)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("tx"), hash), wtx);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseTx(uint256 hash)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("tx"), hash));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||
keyMeta, false))
|
||||
|
@ -89,7 +92,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
|
|||
const CKeyMetadata &keyMeta)
|
||||
{
|
||||
const bool fEraseUnencryptedKey = true;
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||
keyMeta))
|
||||
|
@ -111,7 +114,7 @@ bool CWalletDB::WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
|||
const CKeyMetadata &keyMeta)
|
||||
{
|
||||
const bool fEraseUnencryptedKey = true;
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!Write(std::make_pair(std::string("zkeymeta"), addr), keyMeta))
|
||||
return false;
|
||||
|
@ -131,7 +134,7 @@ bool CWalletDB::WriteCryptedSaplingZKey(
|
|||
const CKeyMetadata &keyMeta)
|
||||
{
|
||||
const bool fEraseUnencryptedKey = true;
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
auto ivk = extfvk.fvk.in_viewing_key();
|
||||
|
||||
if (!Write(std::make_pair(std::string("sapzkeymeta"), ivk), keyMeta))
|
||||
|
@ -149,13 +152,13 @@ bool CWalletDB::WriteCryptedSaplingZKey(
|
|||
|
||||
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!Write(std::make_pair(std::string("zkeymeta"), addr), keyMeta))
|
||||
return false;
|
||||
|
@ -167,7 +170,7 @@ bool CWalletDB::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
|||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const CKeyMetadata &keyMeta)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
if (!Write(std::make_pair(std::string("sapzkeymeta"), ivk), keyMeta))
|
||||
return false;
|
||||
|
@ -179,58 +182,58 @@ bool CWalletDB::WriteSaplingPaymentAddress(
|
|||
const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
|
||||
return Write(std::make_pair(std::string("sapzaddr"), addr), ivk, false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("vkey"), vk), '1');
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("vkey"), vk));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteSaplingExtendedFullViewingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("sapextfvk"), extfvk), '1');
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseSaplingExtendedFullViewingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("sapextfvk"), extfvk));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteWatchOnly(const CScript &dest)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseWatchOnly(const CScript &dest)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::string("bestblock"), locator);
|
||||
}
|
||||
|
||||
|
@ -241,19 +244,19 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
|
|||
|
||||
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::string("orderposnext"), nOrderPosNext);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::string("defaultkey"), vchPubKey);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteWitnessCacheSize(int64_t nWitnessCacheSize)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::string("witnesscachesize"), nWitnessCacheSize);
|
||||
}
|
||||
|
||||
|
@ -264,13 +267,13 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
|
|||
|
||||
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool CWalletDB::ErasePool(int64_t nPool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("pool"), nPool));
|
||||
}
|
||||
|
||||
|
@ -904,8 +907,8 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
|
|||
bool fNoncriticalErrors = false;
|
||||
DBErrors result = DB_LOAD_OK;
|
||||
|
||||
try {
|
||||
LOCK(pwallet->cs_wallet);
|
||||
try {
|
||||
int nMinVersion = 0;
|
||||
if (Read((string)"minversion", nMinVersion))
|
||||
{
|
||||
|
@ -1105,20 +1108,20 @@ void ThreadFlushWalletDB(const string& strFile)
|
|||
if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
|
||||
return;
|
||||
|
||||
unsigned int nLastSeen = nWalletDBUpdated;
|
||||
unsigned int nLastFlushed = nWalletDBUpdated;
|
||||
unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
|
||||
unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
int64_t nLastWalletUpdate = GetTime();
|
||||
while (true)
|
||||
{
|
||||
MilliSleep(500);
|
||||
|
||||
if (nLastSeen != nWalletDBUpdated)
|
||||
if (nLastSeen != CWalletDB::GetUpdateCounter())
|
||||
{
|
||||
nLastSeen = nWalletDBUpdated;
|
||||
nLastSeen = CWalletDB::GetUpdateCounter();
|
||||
nLastWalletUpdate = GetTime();
|
||||
}
|
||||
|
||||
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
|
||||
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
|
||||
{
|
||||
TRY_LOCK(bitdb.cs_db,lockDb);
|
||||
if (lockDb)
|
||||
|
@ -1139,7 +1142,7 @@ void ThreadFlushWalletDB(const string& strFile)
|
|||
if (mi != bitdb.mapFileUseCount.end())
|
||||
{
|
||||
LogPrint("db", "Flushing %s\n", strFile);
|
||||
nLastFlushed = nWalletDBUpdated;
|
||||
nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
// Flush wallet file so it's self contained
|
||||
|
@ -1282,31 +1285,41 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
|
|||
|
||||
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||
}
|
||||
|
||||
|
||||
bool CWalletDB::WriteHDSeed(const HDSeed& seed)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("hdseed"), seed.Fingerprint()), seed.RawSeed());
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& vchCryptedSecret)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::make_pair(std::string("chdseed"), seedFp), vchCryptedSecret);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
nWalletDBUpdateCounter++;
|
||||
return Write(std::string("hdchain"), chain);
|
||||
}
|
||||
|
||||
void CWalletDB::IncrementUpdateCounter()
|
||||
{
|
||||
nWalletDBUpdateCounter++;
|
||||
}
|
||||
|
||||
unsigned int CWalletDB::GetUpdateCounter()
|
||||
{
|
||||
return nWalletDBUpdateCounter;
|
||||
}
|
||||
|
|
|
@ -203,6 +203,8 @@ public:
|
|||
bool WriteSaplingExtendedFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk);
|
||||
bool EraseSaplingExtendedFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk);
|
||||
|
||||
static void IncrementUpdateCounter();
|
||||
static unsigned int GetUpdateCounter();
|
||||
private:
|
||||
CWalletDB(const CWalletDB&);
|
||||
void operator=(const CWalletDB&);
|
||||
|
|
Loading…
Reference in New Issue