mirror of
https://git.hush.is/hush/hush3.git
synced 2025-07-17 00:01:50 -04:00
Compare commits
8 Commits
ac413ecb2e
...
d1b649825a
Author | SHA1 | Date | |
---|---|---|---|
|
d1b649825a | ||
|
63ad87f69b | ||
|
c1baab7b8a | ||
|
bde7273c9f | ||
|
560f8e2f41 | ||
|
71928fa228 | ||
|
24b3f1f93b | ||
|
794463015a |
46
src/main.cpp
46
src/main.cpp
@ -6841,9 +6841,6 @@ void static ProcessGetData(CNode* pfrom)
|
||||
}
|
||||
}
|
||||
|
||||
// Track requests for our stuff.
|
||||
GetMainSignals().Inventory(inv.hash);
|
||||
|
||||
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
|
||||
break;
|
||||
}
|
||||
@ -7000,6 +6997,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
{
|
||||
pfrom->PushMessage(NetMsgType::GETADDR);
|
||||
pfrom->fGetAddr = true;
|
||||
// pfrom->m_getaddr_sent = true;
|
||||
// When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND addresses in response
|
||||
// (bypassing the MAX_ADDR_PROCESSING_TOKEN_BUCKET limit).
|
||||
pfrom->m_addr_token_bucket += MAX_ADDR_TO_SEND;
|
||||
}
|
||||
addrman.Good(pfrom->addr);
|
||||
} else {
|
||||
@ -7103,15 +7104,37 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
vector<CAddress> vAddrOk;
|
||||
int64_t nNow = GetTime();
|
||||
int64_t nSince = nNow - 10 * 60;
|
||||
|
||||
// Update/increment addr rate limiting bucket.
|
||||
const int64_t current_time = GetTimeMicros();
|
||||
if (pfrom->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
|
||||
// Don't increment bucket if it's already full
|
||||
const auto time_diff = std::max(current_time - pfrom->m_addr_token_timestamp, (int64_t) 0);
|
||||
const double increment = (time_diff / 1000000) * MAX_ADDR_RATE_PER_SECOND;
|
||||
pfrom->m_addr_token_bucket = std::min<double>(pfrom->m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET);
|
||||
}
|
||||
pfrom->m_addr_token_timestamp = current_time;
|
||||
|
||||
uint64_t num_proc = 0;
|
||||
uint64_t num_rate_limit = 0;
|
||||
|
||||
BOOST_FOREACH(CAddress& addr, vAddr)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
// Apply rate limiting if the address is not allowlisted
|
||||
if (!pfrom->IsAllowlistedRange(addr)) {
|
||||
if (pfrom->m_addr_token_bucket < 1.0) break;
|
||||
pfrom->m_addr_token_bucket -= 1.0;
|
||||
}
|
||||
|
||||
if(p2pdebug)
|
||||
fprintf(stderr,"%s: %s.nTime=%d\n", __func__, addr.ToString().c_str(), addr.nTime);
|
||||
|
||||
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
||||
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
||||
pfrom->AddAddressKnown(addr);
|
||||
pfrom->AddAddressIfNotAlreadyKnown(addr);
|
||||
|
||||
++num_proc;
|
||||
bool fReachable = IsReachable(addr);
|
||||
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||
{
|
||||
@ -7150,6 +7173,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
fprintf(stderr,"%s: %s with nTime=%d is not reachable\n",__func__,addr.ToString().c_str(), addr.nTime);
|
||||
}
|
||||
}
|
||||
pfrom->m_addr_processed += num_proc;
|
||||
pfrom->m_addr_rate_limited += num_rate_limit;
|
||||
LogPrintf("ProcessMessage: Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d%s\n",
|
||||
vAddr.size(),
|
||||
num_proc,
|
||||
num_rate_limit,
|
||||
pfrom->GetId(),
|
||||
fLogIPs ? ", peeraddr=" + pfrom->addr.ToString() : "");
|
||||
|
||||
addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60);
|
||||
if (vAddr.size() < 1000)
|
||||
pfrom->fGetAddr = false;
|
||||
@ -7320,9 +7352,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
}
|
||||
}
|
||||
|
||||
// Track requests for our stuff
|
||||
GetMainSignals().Inventory(inv.hash);
|
||||
|
||||
if (pfrom->nSendSize > (SendBufferSize() * 2)) {
|
||||
Misbehaving(pfrom->GetId(), 50);
|
||||
return error("send buffer size() = %u", pfrom->nSendSize);
|
||||
@ -7960,9 +7989,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
vAddr.reserve(pto->vAddrToSend.size());
|
||||
BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
|
||||
{
|
||||
if (!pto->addrKnown.contains(addr.GetKey()))
|
||||
if (pto->AddAddressIfNotAlreadyKnown(addr))
|
||||
{
|
||||
pto->addrKnown.insert(addr.GetKey());
|
||||
vAddr.push_back(addr);
|
||||
|
||||
if (vAddr.size() >= MAX_ADDR_TO_SEND)
|
||||
|
@ -924,13 +924,6 @@ static bool ProcessBlockFound(CBlock* pblock)
|
||||
reservekey.KeepKey();
|
||||
}
|
||||
}
|
||||
// Track how many getdata requests this block gets
|
||||
//if ( 0 )
|
||||
{
|
||||
//fprintf(stderr,"lock cs_wallet\n");
|
||||
LOCK(wallet.cs_wallet);
|
||||
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
||||
}
|
||||
#endif
|
||||
//fprintf(stderr,"process new block\n");
|
||||
|
||||
|
12
src/net.cpp
12
src/net.cpp
@ -556,6 +556,10 @@ void CNode::CloseSocketDisconnect()
|
||||
CloseSocket(hSocket);
|
||||
}
|
||||
}
|
||||
{
|
||||
LOCK(cs_addrKnown);
|
||||
addrKnown.reset();
|
||||
}
|
||||
|
||||
// in case this fails, we'll empty the recv buffer when the CNode is deleted
|
||||
TRY_LOCK(cs_vRecvMsg, lockRecv);
|
||||
@ -809,6 +813,9 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
|
||||
stats.dPingTime = (((double)nPingUsecTime) / 1e6);
|
||||
stats.dMinPing = (((double)nMinPingUsecTime) / 1e6);
|
||||
stats.dPingWait = (((double)nPingUsecWait) / 1e6);
|
||||
stats.m_addr_processed = m_addr_processed.load();
|
||||
stats.m_addr_rate_limited = m_addr_rate_limited.load();
|
||||
|
||||
|
||||
// Leave string empty if addrLocal invalid (not filled in yet)
|
||||
stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
|
||||
@ -1945,6 +1952,11 @@ void ThreadMessageHandler()
|
||||
|
||||
bool fSleep = true;
|
||||
|
||||
// Randomize the order in which we process messages from/to our peers.
|
||||
// This prevents attacks in which an attacker exploits having multiple
|
||||
// consecutive connections in the vNodes list.
|
||||
random_shuffle(vNodesCopy.begin(), vNodesCopy.end(), GetRandInt);
|
||||
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
{
|
||||
if (pnode->fDisconnect)
|
||||
|
50
src/net.h
50
src/net.h
@ -72,6 +72,13 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||
static const unsigned int MAX_INV_SZ = 50000;
|
||||
/** The maximum number of new addresses to accumulate before announcing. */
|
||||
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
||||
/** The maximum rate of address records we're willing to process on average. Can be bypassed using
|
||||
* the NetPermissionFlags::Addr permission. */
|
||||
static constexpr double MAX_ADDR_RATE_PER_SECOND{0.1};
|
||||
/** The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND
|
||||
* based increments won't go above this, but the MAX_ADDR_TO_SEND increment following GETADDR
|
||||
* is exempt from this limit. */
|
||||
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET{MAX_ADDR_TO_SEND};
|
||||
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
|
||||
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = (_MAX_BLOCK_SIZE + 24); // 24 is msgheader size
|
||||
/** Maximum length of strSubVer in `version` message */
|
||||
@ -295,6 +302,9 @@ public:
|
||||
// CAddress addrBind; // https://github.com/bitcoin/bitcoin/commit/a7e3c2814c8e49197889a4679461be42254e5c51
|
||||
uint32_t m_mapped_as;
|
||||
|
||||
uint64_t m_addr_processed{0};
|
||||
uint64_t m_addr_rate_limited{0};
|
||||
|
||||
/**
|
||||
* Whether the peer has signaled support for receiving ADDRv2 (BIP155)
|
||||
* messages, implying a preference to receive ADDRv2 instead of ADDR ones.
|
||||
@ -302,9 +312,6 @@ public:
|
||||
bool m_wants_addrv2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class CNetMessage {
|
||||
public:
|
||||
bool in_data; // parsing header (false) or data (true)
|
||||
@ -425,6 +432,8 @@ public:
|
||||
CCriticalSection cs_filter;
|
||||
CBloomFilter* pfilter;
|
||||
int nRefCount;
|
||||
CRollingBloomFilter addrKnown;
|
||||
mutable CCriticalSection cs_addrKnown;
|
||||
NodeId id;
|
||||
|
||||
/**
|
||||
@ -433,6 +442,15 @@ public:
|
||||
*/
|
||||
bool m_wants_addrv2{false};
|
||||
|
||||
/** Number of addr messages that can be processed from this peer. Start at 1 to permit self-announcement. */
|
||||
double m_addr_token_bucket{1.0};
|
||||
/** When m_addr_token_bucket was last updated */
|
||||
int64_t m_addr_token_timestamp{GetTimeMicros()};
|
||||
/** Total number of addresses that were dropped due to rate limiting. */
|
||||
std::atomic<uint64_t> m_addr_rate_limited{0};
|
||||
/** Total number of addresses that were processed (excludes rate limited ones). */
|
||||
std::atomic<uint64_t> m_addr_processed{0};
|
||||
|
||||
protected:
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
@ -462,7 +480,6 @@ public:
|
||||
|
||||
// flood relay
|
||||
std::vector<CAddress> vAddrToSend;
|
||||
CRollingBloomFilter addrKnown;
|
||||
bool fGetAddr;
|
||||
std::set<uint256> setKnown;
|
||||
|
||||
@ -545,11 +562,25 @@ public:
|
||||
nRefCount--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AddAddressKnown(const CAddress& _addr)
|
||||
bool AddAddressIfNotAlreadyKnown(const CAddress& addr)
|
||||
{
|
||||
addrKnown.insert(_addr.GetKey());
|
||||
LOCK(cs_addrKnown);
|
||||
// Avoid adding to addrKnown after it has been reset in CloseSocketDisconnect.
|
||||
if (fDisconnect) {
|
||||
return false;
|
||||
}
|
||||
if (!addrKnown.contains(addr.GetKey())) {
|
||||
addrKnown.insert(addr.GetKey());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAddressKnown(const CAddress& addr) const
|
||||
{
|
||||
LOCK(cs_addrKnown);
|
||||
return addrKnown.contains(addr.GetKey());
|
||||
}
|
||||
|
||||
void PushAddress(const CAddress& _addr)
|
||||
@ -562,7 +593,8 @@ public:
|
||||
// Known checking here is only to save space from duplicates.
|
||||
// SendMessages will filter it again for knowns that were added
|
||||
// after addresses were pushed.
|
||||
if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey()) && addr_format_supported) {
|
||||
if (_addr.IsValid() && !IsAddressKnown(addr) && addr_format_supported) {
|
||||
|
||||
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
|
||||
vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr;
|
||||
} else {
|
||||
|
@ -204,6 +204,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
obj.push_back(Pair("inflight", heights));
|
||||
}
|
||||
obj.push_back(Pair("allowlisted", stats.fAllowlisted));
|
||||
obj.pushKV("addr_processed", stats.m_addr_processed);
|
||||
obj.pushKV("addr_rate_limited", stats.m_addr_rate_limited);
|
||||
|
||||
ret.push_back(obj);
|
||||
}
|
||||
|
@ -31,19 +31,15 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
||||
g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3));
|
||||
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
|
||||
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||
//g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
|
||||
g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
|
||||
}
|
||||
|
||||
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||
g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
|
||||
//g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
|
||||
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
|
||||
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||
g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3));
|
||||
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
||||
@ -57,7 +53,6 @@ void UnregisterAllValidationInterfaces() {
|
||||
//g_signals.ScriptForMining.disconnect_all_slots();
|
||||
g_signals.BlockChecked.disconnect_all_slots();
|
||||
g_signals.Broadcast.disconnect_all_slots();
|
||||
g_signals.Inventory.disconnect_all_slots();
|
||||
g_signals.ChainTip.disconnect_all_slots();
|
||||
g_signals.SetBestChain.disconnect_all_slots();
|
||||
g_signals.UpdatedTransaction.disconnect_all_slots();
|
||||
|
@ -40,10 +40,8 @@ protected:
|
||||
virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, boost::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added) {}
|
||||
virtual void SetBestChain(const CBlockLocator &locator) {}
|
||||
virtual void UpdatedTransaction(const uint256 &hash) {}
|
||||
virtual void Inventory(const uint256 &hash) {}
|
||||
virtual void ResendWalletTransactions(int64_t nBestBlockTime) {}
|
||||
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
|
||||
virtual void ResetRequestCount(const uint256 &hash) {};
|
||||
friend void ::RegisterValidationInterface(CValidationInterface*);
|
||||
friend void ::UnregisterValidationInterface(CValidationInterface*);
|
||||
friend void ::UnregisterAllValidationInterfaces();
|
||||
@ -64,8 +62,6 @@ struct CMainSignals {
|
||||
boost::signals2::signal<void (const CBlockIndex *, const CBlock *, boost::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>>)> ChainTip;
|
||||
/** Notifies listeners of a new active block chain. */
|
||||
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
|
||||
/** Notifies listeners about an inventory item being seen on the network. */
|
||||
boost::signals2::signal<void (const uint256 &)> Inventory;
|
||||
/** Tells listeners to broadcast their data. */
|
||||
boost::signals2::signal<void (int64_t nBestBlockTime)> Broadcast;
|
||||
/** Notifies listeners of a block validation result */
|
||||
|
@ -2273,45 +2273,6 @@ int64_t CWalletTx::GetTxTime() const
|
||||
return n ? n : nTimeReceived;
|
||||
}
|
||||
|
||||
int CWalletTx::GetRequestCount() const
|
||||
{
|
||||
// Returns -1 if it wasn't being tracked
|
||||
int nRequests = -1;
|
||||
{
|
||||
LOCK(pwallet->cs_wallet);
|
||||
if (IsCoinBase())
|
||||
{
|
||||
// Generated block
|
||||
if (!hashBlock.IsNull())
|
||||
{
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*mi).second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Did anyone request this transaction?
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
{
|
||||
nRequests = (*mi).second;
|
||||
|
||||
// How about the block it's in?
|
||||
if (nRequests == 0 && !hashBlock.IsNull())
|
||||
{
|
||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
||||
if (mi != pwallet->mapRequestCount.end())
|
||||
nRequests = (*mi).second;
|
||||
else
|
||||
nRequests = 1; // If it's in someone else's block it must have got out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nRequests;
|
||||
}
|
||||
|
||||
// GetAmounts will determine the transparent debits and credits for a given wallet tx.
|
||||
void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
|
||||
list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
|
||||
@ -4082,9 +4043,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
delete pwalletdb;
|
||||
}
|
||||
|
||||
// Track how many getdata requests our transaction gets
|
||||
mapRequestCount[wtxNew.GetHash()] = 0;
|
||||
|
||||
std::string strCmd = GetArg("-txsend", "");
|
||||
|
||||
if (fBroadcastTransactions)
|
||||
|
@ -606,7 +606,6 @@ public:
|
||||
bool WriteToDisk(CWalletDB *pwalletdb);
|
||||
|
||||
int64_t GetTxTime() const;
|
||||
int GetRequestCount() const;
|
||||
|
||||
bool RelayWalletTransaction();
|
||||
|
||||
@ -1017,7 +1016,6 @@ public:
|
||||
std::map<uint256, CWalletTx> mapWallet;
|
||||
|
||||
int64_t nOrderPosNext;
|
||||
std::map<uint256, int> mapRequestCount;
|
||||
|
||||
std::map<CTxDestination, CAddressBookData> mapAddressBook;
|
||||
|
||||
@ -1236,22 +1234,7 @@ public:
|
||||
|
||||
void UpdatedTransaction(const uint256 &hashTx);
|
||||
|
||||
void Inventory(const uint256 &hash)
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
|
||||
if (mi != mapRequestCount.end())
|
||||
(*mi).second++;
|
||||
}
|
||||
}
|
||||
|
||||
//void GetScriptForMining(boost::shared_ptr<CReserveScript> &script);
|
||||
void ResetRequestCount(const uint256 &hash)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
mapRequestCount[hash] = 0;
|
||||
};
|
||||
|
||||
unsigned int GetKeyPoolSize()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user