//------------------------------------------------------------------------------ /* Copyright (c) 2011-2013, OpenCoin, Inc. */ //============================================================================== class Features; //------------------------------------------------------------------------------ class FeeVote : public IFeeVote { private: // VFALCO TODO rename template parameter (wtf, looks like a macro) template class VotableInteger { public: VotableInteger (INT current, INT target) : mCurrent (current), mTarget (target) { ++mVoteMap[mTarget]; // Add our vote } bool mayVote () { return mCurrent != mTarget; // If we love the current setting, we will not vote } void addVote (INT vote) { ++mVoteMap[vote]; } void noVote () { addVote (mCurrent); } INT getVotes () { INT ourVote = mCurrent; int weight = 0; 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)) && (value.second > weight)) { ourVote = value.first; weight = value.second; } } return ourVote; } private: INT mCurrent; // The current setting INT mTarget; // The setting we want std::map mVoteMap; }; public: FeeVote (uint64 targetBaseFee, uint32 targetReserveBase, uint32 targetReserveIncrement) : mTargetBaseFee (targetBaseFee) , mTargetReserveBase (targetReserveBase) , mTargetReserveIncrement (targetReserveIncrement) { } //-------------------------------------------------------------------------- void doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) { if (lastClosedLedger->getBaseFee () != mTargetBaseFee) { WriteLog (lsINFO, Features) << "Voting for base fee of " << mTargetBaseFee; baseValidation.setFieldU64 (sfBaseFee, mTargetBaseFee); } if (lastClosedLedger->getReserve (0) != mTargetReserveBase) { WriteLog (lsINFO, Features) << "Voting for base resrve of " << mTargetReserveBase; baseValidation.setFieldU32 (sfReserveBase, mTargetReserveBase); } if (lastClosedLedger->getReserveInc () != mTargetReserveIncrement) { WriteLog (lsINFO, Features) << "Voting for reserve increment of " << mTargetReserveIncrement; baseValidation.setFieldU32 (sfReserveIncrement, mTargetReserveIncrement); } } //-------------------------------------------------------------------------- void doVoting (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 = getApp().getValidations ().getValidations (lastClosedLedger->getParentHash ()); BOOST_FOREACH (ValidationSet::value_type const & value, set) { SerializedValidation const& 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 ())) { WriteLog (lsWARNING, Features) << "We are voting for a fee change: " << baseFee << "/" << baseReserve << "/" << incReserve; SerializedTransaction trans (ttFEE); trans.setFieldAccount (sfAccount, uint160 ()); trans.setFieldU64 (sfBaseFee, baseFee); trans.setFieldU32 (sfReferenceFeeUnits, 10); trans.setFieldU32 (sfReserveBase, baseReserve); trans.setFieldU32 (sfReserveIncrement, incReserve); uint256 txID = trans.getTransactionID (); WriteLog (lsWARNING, Features) << "Vote: " << txID; Serializer s; trans.add (s, true); SHAMapItem::pointer tItem = boost::make_shared (txID, s.peekData ()); if (!initialPosition->addGiveItem (tItem, true, false)) { WriteLog (lsWARNING, Features) << "Ledger already had fee change"; } } } private: uint64 mTargetBaseFee; uint32 mTargetReserveBase; uint32 mTargetReserveIncrement; }; //------------------------------------------------------------------------------ IFeeVote* IFeeVote::New (uint64 targetBaseFee, uint32 targetReserveBase, uint32 targetReserveIncrement) { return new FeeVote (targetBaseFee, targetReserveBase, targetReserveIncrement); } // vim:ts=4