diff --git a/src/cpp/ripple/ChangeTransactor.cpp b/src/cpp/ripple/ChangeTransactor.cpp index 1d3a80f27b..0fd450ec42 100644 --- a/src/cpp/ripple/ChangeTransactor.cpp +++ b/src/cpp/ripple/ChangeTransactor.cpp @@ -1,4 +1,7 @@ #include "ChangeTransactor.h" +#include "Log.h" + +SETUP_LOG(); TER ChangeTransactor::doApply() { @@ -14,10 +17,16 @@ TER ChangeTransactor::doApply() TER ChangeTransactor::checkSig() { if (mTxn.getFieldAccount160(sfAccount).isNonZero()) + { + cLog(lsWARNING) << "Change transaction had bad source account"; return temBAD_SRC_ACCOUNT; + } if (!mTxn.getSigningPubKey().empty() || !mTxn.getSignature().empty()) + { + cLog(lsWARNING) << "Change transaction had bad signature"; return temBAD_SIGNATURE; + } return tesSUCCESS; } @@ -25,15 +34,26 @@ TER ChangeTransactor::checkSig() TER ChangeTransactor::checkSeq() { if (mTxn.getSequence() != 0) + { + cLog(lsWARNING) << "Change transaction had bad sequence"; return temBAD_SEQUENCE; - + } return tesSUCCESS; } TER ChangeTransactor::payFee() { + if (isSetBit(mParams, tapOPEN_LEDGER)) + { + cLog(lsWARNING) << "Change transaction against open ledger"; + return temINVALID; + } + if (mTxn.getTransactionFee() != STAmount()) + { + cLog(lsWARNING) << "Change transaction with non-zero fee"; return temBAD_FEE; + } return tesSUCCESS; } @@ -70,5 +90,6 @@ TER ChangeTransactor::applyFee() feeObject->setFieldU32(sfReserveIncrement, mTxn.getFieldU32(sfReserveIncrement)); mEngine->entryModify(feeObject); + cLog(lsWARNING) << "Fees have been changed"; return tesSUCCESS; } diff --git a/src/cpp/ripple/FeatureTable.cpp b/src/cpp/ripple/FeatureTable.cpp index 4c58084684..7154723cf4 100644 --- a/src/cpp/ripple/FeatureTable.cpp +++ b/src/cpp/ripple/FeatureTable.cpp @@ -3,6 +3,9 @@ #include #include "Log.h" +#include "Application.h" +#include "ValidationCollection.h" +#include "HashPrefixes.h" SETUP_LOG(); @@ -243,6 +246,7 @@ protected: INT mTarget; // The setting we want std::map mVoteMap; +public: VotableInteger(INT current, INT target) : mCurrent(current), mTarget(target) { ++mVoteMap[mTarget]; // Add our vote @@ -268,8 +272,8 @@ protected: INT ourVote = mCurrent; int weight = 0; - typedef std::pair INTint_pair_t; - BOOST_FOREACH(INTint_pair_t& value, mVoteMap) + typedef typename std::map::value_type mapVType; + BOOST_FOREACH(const mapVType& value, mVoteMap) { // Take most voted value between current and target, inclusive if ((value.first <= std::max(mTarget, mCurrent)) && (value.first >= std::min(mTarget, mCurrent)) && @@ -284,16 +288,88 @@ protected: } }; +void FeeVote::doValidation(Ledger::ref lastClosedLedger, STObject& validation) +{ + if (lastClosedLedger->getBaseFee() != mTargetBaseFee) + { + cLog(lsINFO) << "Voting for base fee of " << mTargetBaseFee; + validation.setFieldU64(sfBaseFee, mTargetBaseFee); + } + + if (lastClosedLedger->getReserve(0) != mTargetReserveBase) + { + cLog(lsINFO) << "Voting for base resrve of " << mTargetReserveBase; + validation.setFieldU32(sfReserveBase, mTargetReserveBase); + } + + if (lastClosedLedger->getReserveInc() != mTargetReserveIncrement) + { + cLog(lsINFO) << "Voting for reserve increment of " << mTargetReserveIncrement; + validation.setFieldU32(sfReserveIncrement, mTargetReserveIncrement); + } +} + void FeeVote::doFeeVoting(Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) { // LCL must be flag ledger assert((lastClosedLedger->getLedgerSeq() % 256) == 0); + VotableInteger baseFeeVote(lastClosedLedger->getBaseFee(), mTargetBaseFee); + VotableInteger baseReserveVote(lastClosedLedger->getReserve(0), mTargetReserveBase); + VotableInteger incReserveVote(lastClosedLedger->getReserveInc(), mTargetReserveIncrement); + // get validations for ledger before flag + ValidationSet set = theApp->getValidations().getValidations(lastClosedLedger->getParentHash()); + BOOST_FOREACH(ValidationSet::value_type& value, set) + { + SerializedValidation& val = *value.second; + if (val.isTrusted()) + { + if (val.isFieldPresent(sfBaseFee)) + baseFeeVote.addVote(val.getFieldU64(sfBaseFee)); + else + baseFeeVote.noVote(); + if (val.isFieldPresent(sfReserveBase)) + baseReserveVote.addVote(val.getFieldU32(sfReserveBase)); + else + baseReserveVote.noVote(); + if (val.isFieldPresent(sfReserveIncrement)) + incReserveVote.addVote(val.getFieldU32(sfReserveIncrement)); + else + incReserveVote.noVote(); + } + } // choose our positions + uint64 baseFee = baseFeeVote.getVotes(); + uint32 baseReserve = baseReserveVote.getVotes(); + uint32 incReserve = incReserveVote.getVotes(); // add transactions to our position + if ((baseFee != lastClosedLedger->getBaseFee()) || + (baseReserve != lastClosedLedger->getReserve(0)) || + (incReserve != lastClosedLedger->getReserveInc())) + { + cLog(lsWARNING) << "We are voting for a fee change: " << baseFee << "/" << baseReserve << "/" << incReserve; + SerializedTransaction trans(ttFEE); + trans.setFieldU64(sfBaseFee, baseFee); + trans.setFieldU32(sfReferenceFeeUnits, 10); + trans.setFieldU32(sfReserveBase, baseReserve); + trans.setFieldU32(sfReserveIncrement, incReserve); + + + Serializer s; + s.add32(sHP_TransactionID); + trans.add(s, true); + uint256 txID = s.getSHA512Half(); + cLog(lsWARNING) << "Vote: " << txID; + + SHAMapItem::pointer tItem = boost::make_shared(txID, s.peekData()); + if (!initialPosition->addGiveItem(tItem, true, false)) + { + cLog(lsWARNING) << "Ledger already had fee change"; + } + } } // vim:ts=4 diff --git a/src/cpp/ripple/FeatureTable.h b/src/cpp/ripple/FeatureTable.h index 0f6403813f..fba08b557f 100644 --- a/src/cpp/ripple/FeatureTable.h +++ b/src/cpp/ripple/FeatureTable.h @@ -93,8 +93,10 @@ public: mTargetReserveIncrement(targetReserveIncrement) { ; } - void doValidation(STObject& baseValidation); + // add our wishes to our validation + void doValidation(Ledger::ref lastClosedLedger, STObject& baseValidation); + // vote on the fee we want void doFeeVoting(Ledger::ref lastClosedLedger, SHAMap::ref initialPosition); }; diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 52c1ca7717..e2021a77f8 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -317,7 +317,16 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) void LedgerConsensus::takeInitialPosition(Ledger& initialLedger) { - SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false); + SHAMap::pointer initialSet; + + if (mProposing && mHaveCorrectLCL && ((mPreviousLedger->getLedgerSeq() % 256) == 0)) + { // previous ledger was flag ledger + SHAMap::pointer preSet = initialLedger.peekTransactionMap()->snapShot(true); + theApp->getFeeVote().doFeeVoting(mPreviousLedger, preSet); + initialSet = preSet->snapShot(false); + } + else + initialSet = initialLedger.peekTransactionMap()->snapShot(false); uint256 txSet = initialSet->getHash(); cLog(lsINFO) << "initial position " << txSet; mapComplete(txSet, initialSet, false); @@ -1208,6 +1217,8 @@ void LedgerConsensus::accept(SHAMap::ref set, LoadEvent::pointer) SerializedValidation::pointer v = boost::make_shared (newLCLHash, theApp->getOPs().getValidationTimeNC(), mValPublic, mProposing); v->setFieldU32(sfLedgerSequence, newLCL->getLedgerSeq()); + if (((newLCL->getLedgerSeq() + 1) % 256) == 0) // next ledger is flag ledger + theApp->getFeeVote().doValidation(newLCL, *v); v->sign(signingHash, mValPrivate); v->setTrusted(); theApp->isNew(signingHash); // suppress it if we receive it diff --git a/src/cpp/ripple/LedgerEntrySet.h b/src/cpp/ripple/LedgerEntrySet.h index fb9affb7ab..2edeab394f 100644 --- a/src/cpp/ripple/LedgerEntrySet.h +++ b/src/cpp/ripple/LedgerEntrySet.h @@ -25,8 +25,6 @@ enum TransactionEngineParams tapRETRY = 0x20, // This is not the transaction's last pass // Transaction can be retried, soft failures allowed - tapAFTER_END = 0x40, // We are processing the transaction last - tapADMIN = 0x400, // Transaction came from a privileged source };