Allow administrators to submit transactions that don't meet the local load fee.

This commit is contained in:
JoelKatz
2013-04-15 17:14:20 -07:00
parent 0c1c14f49a
commit 8ed0d107fd
11 changed files with 37 additions and 24 deletions

View File

@@ -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<uint256> Ledger::getNeededTransactionHashes(int max)

View File

@@ -350,7 +350,7 @@ public:
}
uint64 scaleFeeBase(uint64 fee);
uint64 scaleFeeLoad(uint64 fee);
uint64 scaleFeeLoad(uint64 fee, bool bAdmin);
Json::Value getJson(int options);

View File

@@ -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

View File

@@ -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);

View File

@@ -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();

View File

@@ -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<Transaction>(trans, false), callback));
boost::make_shared<Transaction>(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

View File

@@ -188,12 +188,12 @@ public:
//
typedef FUNCTION_TYPE<void (Transaction::pointer, TER)> 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

View File

@@ -850,7 +850,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx
else
tx = boost::make_shared<Transaction>(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<Peer>(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<ripple::TMValidation> packet, boost::weak_ptr<Peer> peer)
bool isTrusted, bool isCluster, boost::shared_ptr<ripple::TMValidation> packet, boost::weak_ptr<Peer> 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<ripple::TMValidation>& 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<Peer>(shared_from_this())));
}
#ifndef TRUST_NETWORK

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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()