diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp index 4a195cbca..715a84a33 100644 --- a/src/cpp/ripple/Ledger.cpp +++ b/src/cpp/ripple/Ledger.cpp @@ -1618,11 +1618,11 @@ uint64 Ledger::scaleFeeBase(uint64 fee) return theApp->getFeeTrack().scaleFeeBase(fee, mBaseFee, mReferenceFeeUnits); } -uint64 Ledger::scaleFeeLoad(uint64 fee) +uint64 Ledger::scaleFeeLoad(uint64 fee, bool bAdmin) { if (!mBaseFee) updateFees(); - return theApp->getFeeTrack().scaleFeeLoad(fee, mBaseFee, mReferenceFeeUnits); + return theApp->getFeeTrack().scaleFeeLoad(fee, mBaseFee, mReferenceFeeUnits, bAdmin); } std::vector Ledger::getNeededTransactionHashes(int max) diff --git a/src/cpp/ripple/Ledger.h b/src/cpp/ripple/Ledger.h index 36922a179..3fb0a898f 100644 --- a/src/cpp/ripple/Ledger.h +++ b/src/cpp/ripple/Ledger.h @@ -350,7 +350,7 @@ public: } uint64 scaleFeeBase(uint64 fee); - uint64 scaleFeeLoad(uint64 fee); + uint64 scaleFeeLoad(uint64 fee, bool bAdmin); Json::Value getJson(int options); diff --git a/src/cpp/ripple/LedgerEntrySet.h b/src/cpp/ripple/LedgerEntrySet.h index 1174b1e29..e4e0b7373 100644 --- a/src/cpp/ripple/LedgerEntrySet.h +++ b/src/cpp/ripple/LedgerEntrySet.h @@ -24,6 +24,8 @@ enum TransactionEngineParams tapRETRY = 0x20, // This is not the transaction's last pass // Transaction can be retried, soft failures allowed + + tapADMIN = 0x40, // Transaction came from a privileged source }; enum LedgerEntryAction diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 9a09b3378..d83d87822 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -199,7 +199,7 @@ uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint64 div) return (value * mul) / div; } -uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits) +uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin) { static uint64 midrange(0x00000000FFFFFFFF); @@ -209,9 +209,15 @@ uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFe else // normal fee, multiply first for accuracy fee *= referenceFeeUnits; + uint32 feeFactor = std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee); + + // Let admins pay the normal fee until the local load exceeds four times the remote + if (bAdmin && (feeFactor > mRemoteTxnLoadFee) && (feeFactor < (4 * mRemoteTxnLoadFee))) + feeFactor = mRemoteTxnLoadFee; + { boost::mutex::scoped_lock sl(mLock); - fee = mulDiv(fee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee); + fee = mulDiv(fee, feeFactor, lftNormalFee); } if (big) // Fee was big to start, must now multiply @@ -381,9 +387,9 @@ BOOST_AUTO_TEST_CASE(LoadFeeTrack_test) LoadFeeTrack l; BOOST_REQUIRE_EQUAL(l.scaleFeeBase(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000); - BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000); + BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 10000); BOOST_REQUIRE_EQUAL(l.scaleFeeBase(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1); - BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1); + BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 1); // Check new default fee values give same fees as old defaults BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_DEFAULT, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10); diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 25b8aa585..7acf6dc9a 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -169,7 +169,7 @@ public: uint64 scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits); // Scale using load as well as base rate - uint64 scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits); + uint64 scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin); uint32 getRemoteFee(); uint32 getLocalFee(); diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 41006ac86..600e39f6b 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -212,12 +212,12 @@ void NetworkOPs::submitTransaction(Job&, SerializedTransaction::pointer iTrans, // FIXME: Should submit to job queue theApp->getIOService().post(boost::bind(&NetworkOPs::processTransaction, this, - boost::make_shared(trans, false), callback)); + boost::make_shared(trans, false), false, callback)); } // Sterilize transaction through serialization. // This is fully synchronous and deprecated -Transaction::pointer NetworkOPs::submitTransactionSync(Transaction::ref tpTrans, bool bSubmit) +Transaction::pointer NetworkOPs::submitTransactionSync(Transaction::ref tpTrans, bool bAdmin, bool bSubmit) { Serializer s; tpTrans->getSTransaction()->add(s); @@ -232,7 +232,7 @@ Transaction::pointer NetworkOPs::submitTransactionSync(Transaction::ref tpTrans, else if (tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction())) { if (bSubmit) - (void) NetworkOPs::processTransaction(tpTransNew); + (void) NetworkOPs::processTransaction(tpTransNew, bAdmin); } else { @@ -326,7 +326,7 @@ void NetworkOPs::runTransactionQueue() theApp->getIOService().post(boost::bind(&NetworkOPs::runTransactionQueue, this)); } -Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, stCallback callback) +Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, bool bAdmin, stCallback callback) { LoadEvent::autoptr ev = theApp->getJobQueue().getLoadEventAP(jtTXN_PROC, "ProcessTXN"); @@ -352,7 +352,8 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock()); Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true); bool didApply; - TER r = mLedgerMaster->doTransaction(trans->getSTransaction(), tapOPEN_LEDGER | tapNO_CHECK_SIGN, didApply); + TER r = mLedgerMaster->doTransaction(trans->getSTransaction(), + bAdmin ? (tapOPEN_LEDGER | tapNO_CHECK_SIGN | tapADMIN) : (tapOPEN_LEDGER | tapNO_CHECK_SIGN), didApply); trans->setResult(r); if (isTemMalformed(r)) // malformed, cache bad diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index b4aa58c21..1471b5ae5 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -188,12 +188,12 @@ public: // typedef FUNCTION_TYPE stCallback; // must complete immediately void submitTransaction(Job&, SerializedTransaction::pointer, stCallback callback = stCallback()); - Transaction::pointer submitTransactionSync(Transaction::ref tpTrans, bool bSubmit=true); + Transaction::pointer submitTransactionSync(Transaction::ref tpTrans, bool bAdmin, bool bSubmit); void runTransactionQueue(); - Transaction::pointer processTransaction(Transaction::pointer, stCallback); - Transaction::pointer processTransaction(Transaction::pointer transaction) - { return processTransaction(transaction, stCallback()); } + Transaction::pointer processTransaction(Transaction::pointer, bool bAdmin, stCallback); + Transaction::pointer processTransaction(Transaction::pointer transaction, bool bAdmin) + { return processTransaction(transaction, bAdmin, stCallback()); } Transaction::pointer findTransactionByID(const uint256& transactionID); #if 0 diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp index ea3474bbd..a1e397cdd 100644 --- a/src/cpp/ripple/Peer.cpp +++ b/src/cpp/ripple/Peer.cpp @@ -850,7 +850,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx else tx = boost::make_shared(stx, false); - theApp->getOPs().processTransaction(tx); + theApp->getOPs().processTransaction(tx, (flags & SF_TRUSTED) != 0); #ifndef TRUST_NETWORK } @@ -888,6 +888,8 @@ void Peer::recvTransaction(ripple::TMTransaction& packet) if ((flags & SF_RETRY) == 0) return; } + if (mCluster) + flags |= SF_TRUSTED | SF_SIGGOOD; theApp->getJobQueue().addJob(jtTRANSACTION, "recvTransction->checkTransaction", BIND_TYPE(&checkTransaction, P_1, flags, stx, boost::weak_ptr(shared_from_this()))); @@ -1043,13 +1045,13 @@ void Peer::recvHaveTxSet(ripple::TMHaveTransactionSet& packet) } static void checkValidation(Job&, SerializedValidation::pointer val, uint256 signingHash, - bool isTrusted, boost::shared_ptr packet, boost::weak_ptr peer) + bool isTrusted, bool isCluster, boost::shared_ptr packet, boost::weak_ptr peer) { #ifndef TRUST_NETWORK try #endif { - if (!val->isValid(signingHash)) + if (!isCluster && !val->isValid(signingHash)) { cLog(lsWARNING) << "Validation is invalid"; Peer::punishPeer(peer, LT_InvalidRequest); @@ -1106,7 +1108,7 @@ void Peer::recvValidation(const boost::shared_ptr& packet) bool isTrusted = theApp->getUNL().nodeInUNL(val->getSignerPublic()); theApp->getJobQueue().addJob(isTrusted ? jtVALIDATION_t : jtVALIDATION_ut, "recvValidation->checkValidation", - BIND_TYPE(&checkValidation, P_1, val, signingHash, isTrusted, packet, + BIND_TYPE(&checkValidation, P_1, val, signingHash, isTrusted, mCluster, packet, boost::weak_ptr(shared_from_this()))); } #ifndef TRUST_NETWORK diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 8f38484cc..770a43339 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -324,7 +324,8 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit) try { - tpTrans = mNetOps->submitTransactionSync(tpTrans, bSubmit); // FIXME: For performance, should use asynch interface + // FIXME: For performance, should use asynch interface + tpTrans = mNetOps->submitTransactionSync(tpTrans, mRole == ADMIN, bSubmit); if (!tpTrans) { jvResult["error"] = "invalidTransaction"; @@ -1452,7 +1453,7 @@ Json::Value RPCHandler::doSubmit(Json::Value jvRequest, int& cost) try { - (void) mNetOps->processTransaction(tpTrans); + (void) mNetOps->processTransaction(tpTrans, mRole == ADMIN); } catch (std::exception& e) { diff --git a/src/cpp/ripple/Suppression.h b/src/cpp/ripple/Suppression.h index d401a8f41..876cb833a 100644 --- a/src/cpp/ripple/Suppression.h +++ b/src/cpp/ripple/Suppression.h @@ -19,6 +19,7 @@ DEFINE_INSTANCE(Suppression); #define SF_SIGGOOD 0x04 // Signature is good #define SF_SAVED 0x08 #define SF_RETRY 0x10 // Transaction can be retried +#define SF_TRUSTED 0x20 // comes from trusted source class Suppression : private IS_INSTANCE(Suppression) { diff --git a/src/cpp/ripple/Transactor.cpp b/src/cpp/ripple/Transactor.cpp index c7924b7a8..e3396b205 100644 --- a/src/cpp/ripple/Transactor.cpp +++ b/src/cpp/ripple/Transactor.cpp @@ -42,7 +42,7 @@ Transactor::Transactor(const SerializedTransaction& txn,TransactionEngineParams void Transactor::calculateFee() { - mFeeDue = STAmount(mEngine->getLedger()->scaleFeeLoad(calculateBaseFee())); + mFeeDue = STAmount(mEngine->getLedger()->scaleFeeLoad(calculateBaseFee(), isSetBit(mParams, tapADMIN))); } uint64 Transactor::calculateBaseFee()