diff --git a/core/include/main.h b/core/include/main.h index 92b73fe5ad..8d9b39f718 100644 --- a/core/include/main.h +++ b/core/include/main.h @@ -29,7 +29,8 @@ static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const int64 COIN = 100000000; static const int64 CENT = 1000000; -static const int64 MIN_TX_FEE = 50000; +static const int64 MIN_TX_FEE = CENT; +static const int64 MIN_RELAY_TX_FEE = 50000; static const int64 MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } static const int COINBASE_MATURITY = 100; @@ -86,7 +87,7 @@ bool AddKey(const CKey& key); std::vector GenerateNewKey(); bool AddToWallet(const CWalletTx& wtxIn); void WalletUpdateSpent(const COutPoint& prevout); -int ScanForWalletTransactions(CBlockIndex* pindexStart); +int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); bool LoadBlockIndex(bool fAllowNew=true); void PrintBlockTree(); @@ -599,12 +600,14 @@ public: return dPriority > COIN * 144 / 250; } - int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true) const + int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const { - // Base fee is 1 cent per kilobyte + // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE + int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE; + unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK); unsigned int nNewBlockSize = nBlockSize + nBytes; - int64 nMinFee = (1 + (int64)nBytes / 1000) * MIN_TX_FEE; + int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; if (fAllowFree) { @@ -623,11 +626,11 @@ public: } } - // To limit dust spam, require MIN_TX_FEE if any output is less than 0.01 - if (nMinFee < MIN_TX_FEE) + // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 + if (nMinFee < nBaseFee) BOOST_FOREACH(const CTxOut& txout, vout) if (txout.nValue < CENT) - nMinFee = MIN_TX_FEE; + nMinFee = nBaseFee; // Raise the price as the block approaches full if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) diff --git a/core/include/net.h b/core/include/net.h index 6bbcd64e42..d1ded87232 100644 --- a/core/include/net.h +++ b/core/include/net.h @@ -283,13 +283,29 @@ public: return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0); } + bool IsRFC1918() const + { + return IsIPv4() && (GetByte(3) == 10 || + (GetByte(3) == 192 && GetByte(2) == 168) || + (GetByte(3) == 172 && + (GetByte(2) >= 16 && GetByte(2) <= 31))); + } + + bool IsRFC3927() const + { + return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); + } + + bool IsLocal() const + { + return IsIPv4() && (GetByte(3) == 127 || + GetByte(3) == 0); + } + bool IsRoutable() const { return IsValid() && - !(GetByte(3) == 10 || - (GetByte(3) == 192 && GetByte(2) == 168) || - GetByte(3) == 127 || - GetByte(3) == 0); + !(IsRFC1918() || IsRFC3927() || IsLocal()); } bool IsValid() const diff --git a/core/include/serialize.h b/core/include/serialize.h index 8e7677a2eb..0d66d6a956 100644 --- a/core/include/serialize.h +++ b/core/include/serialize.h @@ -33,7 +33,7 @@ class CDataStream; class CAutoFile; static const unsigned int MAX_SIZE = 0x02000000; -static const int VERSION = 32200; +static const int VERSION = 32300; static const char* pszSubVer = ""; static const bool VERSION_IS_BETA = true; diff --git a/core/include/util.h b/core/include/util.h index eccdbd372d..32a98e6264 100644 --- a/core/include/util.h +++ b/core/include/util.h @@ -197,7 +197,7 @@ std::string GetPidFile(); void CreatePidFile(std::string pidFile, pid_t pid); void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); #ifdef __WXMSW__ -string MyGetSpecialFolderPath(int nFolder, bool fCreate); +std::string MyGetSpecialFolderPath(int nFolder, bool fCreate); #endif std::string GetDefaultDataDir(); std::string GetDataDir(); diff --git a/core/src/init.cpp b/core/src/init.cpp index d40d29cf09..f7a1ce9ef1 100644 --- a/core/src/init.cpp +++ b/core/src/init.cpp @@ -386,7 +386,7 @@ bool AppInit2(int argc, char* argv[]) { printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); nStart = GetTimeMillis(); - ScanForWalletTransactions(pindexRescan); + ScanForWalletTransactions(pindexRescan, true); printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); } diff --git a/core/src/irc.cpp b/core/src/irc.cpp index 099d9e0735..a76374d143 100644 --- a/core/src/irc.cpp +++ b/core/src/irc.cpp @@ -265,11 +265,11 @@ void ThreadIRCSeed2(void* parg) while (!fShutdown) { //CAddress addrConnect("216.155.130.130:6667"); // chat.freenode.net - CAddress addrConnect("92.243.23.21:6667"); // irc.lfnet.org + CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org if (!fTOR) { //struct hostent* phostent = gethostbyname("chat.freenode.net"); - CAddress addrIRC("irc.lfnet.org:6667", 0, true); + CAddress addrIRC("irc.lfnet.org", 6667, true); if (addrIRC.IsValid()) addrConnect = addrIRC; } @@ -339,9 +339,16 @@ void ThreadIRCSeed2(void* parg) Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); } } - - Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r"); - Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r" : "WHO #bitcoin\r"); + + if (fTestNet) { + Send(hSocket, "JOIN #bitcoinTEST\r"); + Send(hSocket, "WHO #bitcoinTEST\r"); + } else { + // randomly join #bitcoin00-#bitcoin99 + int channel_number = GetRandInt(100); + Send(hSocket, strprintf("JOIN #bitcoin%02d\r", channel_number).c_str()); + Send(hSocket, strprintf("WHO #bitcoin%02d\r", channel_number).c_str()); + } int64 nStart = GetTime(); string strLine; diff --git a/core/src/main.cpp b/core/src/main.cpp index 68b6b4ee1b..0456041ee5 100644 --- a/core/src/main.cpp +++ b/core/src/main.cpp @@ -731,13 +731,13 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi } // Don't accept it if it can't get into a block - if (nFees < GetMinFee(1000)) + if (nFees < GetMinFee(1000, true, true)) return error("AcceptToMemoryPool() : not enough fees"); // Continuously rate-limit free transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make other's transactions take longer to confirm. - if (nFees < MIN_TX_FEE) + if (nFees < MIN_RELAY_TX_FEE) { static CCriticalSection cs; static double dFreeCount; @@ -884,7 +884,7 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) return false; } -int ScanForWalletTransactions(CBlockIndex* pindexStart) +int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) { int ret = 0; @@ -897,7 +897,7 @@ int ScanForWalletTransactions(CBlockIndex* pindexStart) block.ReadFromDisk(pindex, true); BOOST_FOREACH(CTransaction& tx, block.vtx) { - if (AddToWalletIfInvolvingMe(tx, &block)) + if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) ret++; } pindex = pindex->pnext; @@ -3329,7 +3329,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Transaction fee required depends on block size bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority)); - int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree); + int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, true); // Connecting shouldn't fail due to dependency on other memory pool transactions // because we're already processing them in order of dependency @@ -3854,9 +3854,18 @@ bool CreateTransaction(const vector >& vecSend, CWalletTx& dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain(); } - // Fill a vout back to self with any change - int64 nChange = nValueIn - nTotalValue; - if (nChange >= CENT) + int64 nChange = nValueIn - nValue - nFeeRet; + + // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE + // or until nChange becomes zero + if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) + { + int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); + nChange -= nMoveToFee; + nFeeRet += nMoveToFee; + } + + if (nChange > 0) { // Note: We use a new key here to keep it from being obvious which side is the change. // The drawback is that by not reusing a previous key, the change may be lost if a diff --git a/core/src/net.cpp b/core/src/net.cpp index 1320781cb2..39360a334c 100644 --- a/core/src/net.cpp +++ b/core/src/net.cpp @@ -56,6 +56,10 @@ CAddress addrProxy("127.0.0.1",9050); +unsigned short GetListenPort() +{ + return (unsigned short)(GetArg("-port", GetDefaultPort())); +} void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) { @@ -84,8 +88,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); #endif - bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168)); - bool fProxy = (fUseProxy && fRoutable); + bool fProxy = (fUseProxy && addrConnect.IsRoutable()); struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr()); if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) @@ -965,7 +968,7 @@ void ThreadMapPort2(void* parg) printf("ThreadMapPort started\n"); char port[6]; - sprintf(port, "%d", GetDefaultPort()); + sprintf(port, "%d", GetListenPort()); const char * rootdescurl = 0; const char * multicastif = 0; @@ -1058,7 +1061,7 @@ void DNSAddressSeed() for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { vector vaddr; - if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, true)) + if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true)) { BOOST_FOREACH (CAddress& addr, vaddr) { @@ -1435,14 +1438,11 @@ void ThreadMessageHandler2(void* parg) - - - bool BindListenPort(string& strError) { strError = ""; int nOne = 1; - addrLocalHost.port = htons(GetDefaultPort()); + addrLocalHost.port = htons(GetListenPort()); #ifdef __WXMSW__ // Initialize Windows Sockets @@ -1494,7 +1494,7 @@ bool BindListenPort(string& strError) memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer - sockaddr.sin_port = htons(GetDefaultPort()); + sockaddr.sin_port = htons(GetListenPort()); if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) { int nErr = WSAGetLastError(); @@ -1556,7 +1556,7 @@ void StartNode(void* parg) printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP); // Take the first IP that isn't loopback 127.x.x.x - CAddress addr(*(unsigned int*)&s4->sin_addr, 0, nLocalServices); + CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices); if (addr.IsValid() && addr.GetByte(3) != 127) { addrLocalHost = addr; diff --git a/core/src/rpc.cpp b/core/src/rpc.cpp index 9efcbbb15a..530bef4a43 100644 --- a/core/src/rpc.cpp +++ b/core/src/rpc.cpp @@ -199,12 +199,26 @@ double GetDifficulty() { // Floating point number that is a multiple of the minimum difficulty, // minimum difficulty = 1.0. + if (pindexBest == NULL) return 1.0; - int nShift = 256 - 32 - 31; // to fit in a uint - double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint(); - double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint(); - return dMinimum / dCurrently; + int nShift = (pindexBest->nBits >> 24) & 0xff; + + double dDiff = + (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff); + + while (nShift < 29) + { + dDiff *= 256.0; + nShift++; + } + while (nShift > 29) + { + dDiff /= 256.0; + nShift--; + } + + return dDiff; } Value getdifficulty(const Array& params, bool fHelp) diff --git a/core/src/util.cpp b/core/src/util.cpp index 4e93f625de..6199109289 100644 --- a/core/src/util.cpp +++ b/core/src/util.cpp @@ -271,7 +271,7 @@ string strprintf(const char* format, ...) if (ret >= 0 && ret < limit) break; if (p != buffer) - delete p; + delete[] p; limit *= 2; p = new char[limit]; if (p == NULL) @@ -279,7 +279,7 @@ string strprintf(const char* format, ...) } string str(p, p+ret); if (p != buffer) - delete p; + delete[] p; return str; }