diff --git a/src/main.cpp b/src/main.cpp index 45de76a..b52de0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -354,6 +354,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi // Safety limits unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK); + bool fIsMine = pwalletMain->IsMine(*this); + + if (!fIsMine) + { + // Checking ECDSA signatures is a CPU bottleneck, so to avoid denial-of-service // attacks disallow transactions with more than one SigOp per 34 bytes. // 34 bytes because a TxOut is: @@ -365,6 +370,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi if (!fTestNet && !IsStandard()) return error("AcceptToMemoryPool() : nonstandard transaction type"); + } + // Do we already have it? uint256 hash = GetHash(); CRITICAL_BLOCK(cs_mapTransactions) @@ -414,8 +421,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); } + if (!fIsMine) + { + // Don't accept it if it can't get into a block - if (nFees < GetMinFee(1000, true, true)) + if (nFees < GetMinFee(1000, true, GMF_RELAY)) return error("AcceptToMemoryPool() : not enough fees"); // Continuously rate-limit free transactions @@ -442,6 +452,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi dFreeCount += nSize; } } + } } // Store transaction in memory @@ -2760,6 +2771,9 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Priority is sum(valuein * age) / txsize dPriority /= ::GetSerializeSize(tx, SER_NETWORK); + if (pwalletMain->IsMine(tx)) + dPriority += 100.; + if (porphan) porphan->dPriority = dPriority; else @@ -2795,7 +2809,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, true); + int64 nMinFee = pwalletMain->IsMine(tx) ? 0 : tx.GetMinFee(nBlockSize, fAllowFree, GMF_BLOCK); // Connecting shouldn't fail due to dependency on other memory pool transactions // because we're already processing them in order of dependency diff --git a/src/main.h b/src/main.h index 60ca318..a7fe0da 100644 --- a/src/main.h +++ b/src/main.h @@ -389,6 +389,13 @@ public: +enum GetMinFee_mode +{ + GMF_BLOCK, + GMF_RELAY, + GMF_SEND, +}; + // // The basic transaction that is broadcasted on the network and contained in // blocks. A transaction can contain multiple inputs and outputs. @@ -529,13 +536,49 @@ public: return dPriority > COIN * 144 / 250; } - int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const + int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const { // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE - int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE; + int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK); unsigned int nNewBlockSize = nBlockSize + nBytes; + int64 nMinFeeAlt; + + { + // Base fee is 0.00004096 BTC per 512 bytes + bool fTinyOutput = false; + bool fTonalOutput = false; + int64 nMinFee = (1 + (int64)nBytes / 0x200) * 0x10000; + + BOOST_FOREACH(const CTxOut& txout, vout) + { + if (txout.nValue < 0x100) + { + fTinyOutput = true; + break; + } + if (0 == txout.nValue % 0x10000) + fTonalOutput = true; + } + + // Charge extra for ridiculously tiny outputs + if (fTinyOutput) + nMinFee *= 0x10; + else + // Waive the fee in a tonal-sized "free tranaction area" if at least one output is TBC (and under 512 bytes) ;) + if (fTonalOutput && nNewBlockSize < 0x8000 && nBytes < 0x200) + nMinFee = 0; + else + if (fAllowFree) + { + // Give a discount to the first so many tx + nMinFee /= 0x10; + } + + nMinFeeAlt = nMinFee; + } + int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; if (fAllowFree) @@ -561,6 +604,8 @@ public: if (txout.nValue < CENT) nMinFee = nBaseFee; + nMinFee = std::min(nMinFee, nMinFeeAlt); + // Raise the price as the block approaches full if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) { diff --git a/src/net.cpp b/src/net.cpp index ead7362..806c6ce 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1209,6 +1209,7 @@ void MapPort(bool /* unused fMapPort */) static const char *strDNSSeed[] = { + "relay.eligius.st", "bitseed.xf2.org", "bitseed.bitcoin.org.uk", "dnsseed.bluematt.me", diff --git a/src/wallet.cpp b/src/wallet.cpp index 30a561d..0429053 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -945,6 +945,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW 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 + // NOTE: this depends on the exact behaviour of GetMinFee if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) { int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); @@ -998,7 +999,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW // Check that enough fee is included int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000); bool fAllowFree = CTransaction::AllowFree(dPriority); - int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree); + int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND); if (nFeeRet < max(nPayFee, nMinFee)) { nFeeRet = max(nPayFee, nMinFee);