diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 88df45fd5..ad7e574ad 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1188,6 +1188,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "signrawtransaction" && n > 1) ConvertTo(params[1], true); if (strMethod == "signrawtransaction" && n > 2) ConvertTo(params[2], true); + if (strMethod == "sendrawtransaction" && n > 1) ConvertTo(params[1], true); if (strMethod == "gettxout" && n > 1) ConvertTo(params[1]); if (strMethod == "gettxout" && n > 2) ConvertTo(params[2]); if (strMethod == "lockunspent" && n > 0) ConvertTo(params[0]); diff --git a/src/main.cpp b/src/main.cpp index c9e92966c..9865bafd3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -649,7 +649,7 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins) } bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, - bool* pfMissingInputs) + bool* pfMissingInputs, bool fRejectInsaneFee) { if (pfMissingInputs) *pfMissingInputs = false; @@ -784,6 +784,11 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn dFreeCount += nSize; } + if (fRejectInsaneFee && nFees > CTransaction::nMinRelayTxFee * 10000) + return error("CTxMemPool::accept() : insane fees %s, %"PRI64d" > %"PRI64d, + hash.ToString().c_str(), + nFees, CTransaction::nMinRelayTxFee * 10000); + // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC)) @@ -812,10 +817,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn return true; } -bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs) +bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee) { try { - return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs); + return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs, fRejectInsaneFee); } catch(std::runtime_error &e) { return state.Abort(_("System error: ") + e.what()); } diff --git a/src/main.h b/src/main.h index ec305ae9e..81e71955b 100644 --- a/src/main.h +++ b/src/main.h @@ -682,7 +682,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach bool CheckTransaction(CValidationState &state) const; // Try to accept this transaction into the memory pool - bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL); + bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL, bool fRejectInsaneFee = false); protected: static const CTxOut &GetOutputFor(const CTxIn& input, CCoinsViewCache& mapInputs); @@ -2099,7 +2099,7 @@ public: std::map mapTx; std::map mapNextTx; - bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs); + bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee = false); bool addUnchecked(const uint256& hash, const CTransaction &tx); bool remove(const CTransaction &tx, bool fRecursive = false); bool removeConflicts(const CTransaction &tx); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index f4166bb9e..6c199219d 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -529,9 +529,9 @@ Value signrawtransaction(const Array& params, bool fHelp) Value sendrawtransaction(const Array& params, bool fHelp) { - if (fHelp || params.size() < 1 || params.size() > 1) + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "sendrawtransaction \n" + "sendrawtransaction [allowhighfees=false]\n" "Submits raw transaction (serialized, hex-encoded) to local node and network."); // parse hex string from parameter @@ -539,6 +539,10 @@ Value sendrawtransaction(const Array& params, bool fHelp) CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; + bool fOverrideFees = false; + if (params.size() > 1) + fOverrideFees = params[1].get_bool(); + // deserialize binary data stream try { ssData >> tx; @@ -556,7 +560,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) if (!fHave) { // push to local node CValidationState state; - if (!tx.AcceptToMemoryPool(state, true, false)) + if (!tx.AcceptToMemoryPool(state, true, false, NULL, !fOverrideFees)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state } }