aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp59
1 files changed, 32 insertions, 27 deletions
diff --git a/src/main.cpp b/src/main.cpp
index d115f763f6..e1a0973352 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -29,7 +29,6 @@
#include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp>
-using namespace boost;
using namespace std;
#if defined(NDEBUG)
@@ -626,34 +625,11 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
bool IsStandardTx(const CTransaction& tx, string& reason)
{
- AssertLockHeld(cs_main);
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
reason = "version";
return false;
}
- // Treat non-final transactions as non-standard to prevent a specific type
- // of double-spend attack, as well as DoS attacks. (if the transaction
- // can't be mined, the attacker isn't expending resources broadcasting it)
- // Basically we don't want to propagate transactions that can't be included in
- // the next block.
- //
- // However, IsFinalTx() is confusing... Without arguments, it uses
- // chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height()
- // is set to the value of nHeight in the block. However, when IsFinalTx()
- // is called within CBlock::AcceptBlock(), the height of the block *being*
- // evaluated is what is used. Thus if we want to know if a transaction can
- // be part of the *next* block, we need to call IsFinalTx() with one more
- // than chainActive.Height().
- //
- // Timestamps on the other hand don't get any special treatment, because we
- // can't know what timestamp the next block will have, and there aren't
- // timestamp applications where it matters.
- if (!IsFinalTx(tx, chainActive.Height() + 1)) {
- reason = "non-final";
- return false;
- }
-
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
@@ -764,7 +740,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// IsStandard() will have already returned false
// and this method isn't called.
vector<vector<unsigned char> > stack;
- if (!EvalScript(stack, tx.vin[i].scriptSig, false, BaseSignatureChecker()))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
return false;
if (whichType == TX_SCRIPTHASH)
@@ -942,6 +918,26 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
error("AcceptToMemoryPool : nonstandard transaction: %s", reason),
REJECT_NONSTANDARD, reason);
+ // Only accept nLockTime-using transactions that can be mined in the next
+ // block; we don't want our mempool filled up with transactions that can't
+ // be mined yet.
+ //
+ // However, IsFinalTx() is confusing... Without arguments, it uses
+ // chainActive.Height() to evaluate nLockTime; when a block is accepted,
+ // chainActive.Height() is set to the value of nHeight in the block.
+ // However, when IsFinalTx() is called within CBlock::AcceptBlock(), the
+ // height of the block *being* evaluated is what is used. Thus if we want
+ // to know if a transaction can be part of the *next* block, we need to
+ // call IsFinalTx() with one more than chainActive.Height().
+ //
+ // Timestamps on the other hand don't get any special treatment, because we
+ // can't know what timestamp the next block will have, and there aren't
+ // timestamp applications where it matters.
+ if (!IsFinalTx(tx, chainActive.Height() + 1))
+ return state.DoS(0,
+ error("AcceptToMemoryPool : non-final"),
+ REJECT_NONSTANDARD, "non-final");
+
// is it already in the memory pool?
uint256 hash = tx.GetHash();
if (pool.exists(hash))
@@ -1031,6 +1027,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
hash.ToString(), nFees, txMinFee),
REJECT_INSUFFICIENTFEE, "insufficient fee");
+ // Require that free transactions have sufficient priority to be mined in the next block.
+ if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
+ return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
+ }
+
// Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
@@ -1050,7 +1051,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// At default rate it would take over a month to fill 1GB
if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
- REJECT_INSUFFICIENTFEE, "insufficient priority");
+ REJECT_INSUFFICIENTFEE, "rate limited free transaction");
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
}
@@ -1883,6 +1884,7 @@ enum FlushStateMode {
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
LOCK(cs_main);
static int64_t nLastWrite = 0;
+ try {
if ((mode == FLUSH_STATE_ALWAYS) ||
((mode == FLUSH_STATE_PERIODIC || mode == FLUSH_STATE_IF_NEEDED) && pcoinsTip->GetCacheSize() > nCoinCacheSize) ||
(mode == FLUSH_STATE_PERIODIC && GetTimeMicros() > nLastWrite + DATABASE_WRITE_INTERVAL * 1000000)) {
@@ -1922,6 +1924,9 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
}
nLastWrite = GetTimeMicros();
}
+ } catch (const std::runtime_error& e) {
+ return state.Abort(std::string("System error while flushing: ") + e.what());
+ }
return true;
}
@@ -2789,7 +2794,7 @@ bool AbortNode(const std::string &strMessage, const std::string &userMessage) {
bool CheckDiskSpace(uint64_t nAdditionalBytes)
{
- uint64_t nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
+ uint64_t nFreeBytesAvailable = boost::filesystem::space(GetDataDir()).available;
// Check for nMinDiskSpace bytes (currently 50MB)
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)