Transactor journal support and small cleanups

This commit is contained in:
Nik Bougalis
2014-03-17 13:33:11 -07:00
committed by Vinnie Falco
parent d447a1db39
commit 436061be22
20 changed files with 692 additions and 485 deletions

View File

@@ -295,7 +295,6 @@
<ClInclude Include="..\..\modules\beast_core\containers\ScopedValueSetter.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\FatalError.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\SemanticVersion.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\Throw.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\UnitTestUtilities.h" />
<ClInclude Include="..\..\modules\beast_core\diagnostic\MeasureFunctionCallTime.h" />
<ClInclude Include="..\..\modules\beast_core\files\DirectoryIterator.h" />

View File

@@ -404,9 +404,6 @@
<ClInclude Include="..\..\modules\beast_core\time\Time.h">
<Filter>beast_core\time</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\diagnostic\Throw.h">
<Filter>beast_core\diagnostic</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_core\files\RandomAccessFile.h">
<Filter>beast_core\files</Filter>
</ClInclude>

View File

@@ -129,8 +129,8 @@ public:
//------------------------------------------------------------------------------
Manager::Manager (Stoppable& parent)
: Stoppable ("PeerFinder", parent)
, beast::PropertyStream::Source ("peerfinder")
: Stoppable ("SiteFiles", parent)
, beast::PropertyStream::Source ("sitefiles")
{
}

View File

@@ -19,32 +19,27 @@
namespace ripple {
SETUP_LOG (AccountSetTransactor)
TER AccountSetTransactor::doApply ()
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet>";
std::uint32_t const uTxFlags = mTxn.getFlags ();
const std::uint32_t uTxFlags = mTxn.getFlags ();
std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
std::uint32_t uFlagsOut = uFlagsIn;
const std::uint32_t uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
std::uint32_t uFlagsOut = uFlagsIn;
const std::uint32_t uSetFlag = mTxn.getFieldU32 (sfSetFlag);
const std::uint32_t uClearFlag = mTxn.getFieldU32 (sfClearFlag);
std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag);
std::uint32_t const uClearFlag = mTxn.getFieldU32 (sfClearFlag);
// legacy AccountSet flags
bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
bool bSetRequireAuth = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
bool bSetDisallowXRP = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);
bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
bool bSetRequireAuth = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
bool bSetDisallowXRP = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);
if (uTxFlags & tfAccountSetMask)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Invalid flags set.";
m_journal.info << "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
@@ -54,8 +49,7 @@ TER AccountSetTransactor::doApply ()
if (bSetRequireAuth && bClearRequireAuth)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";
m_journal.info << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG;
}
@@ -63,20 +57,18 @@ TER AccountSetTransactor::doApply ()
{
if (!mEngine->getNodes ().dirIsEmpty (Ledger::getOwnerDirIndex (mTxnAccountID)))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Retry: Owner directory not empty.";
m_journal.info << "Retry: Owner directory not empty.";
return isSetBit(mParams, tapRETRY) ? terOWNERS : tecOWNERS;
}
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set RequireAuth.";
m_journal.info << "Set RequireAuth.";
uFlagsOut |= lsfRequireAuth;
}
if (bClearRequireAuth && isSetBit (uFlagsIn, lsfRequireAuth))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear RequireAuth.";
m_journal.info << "Clear RequireAuth.";
uFlagsOut &= ~lsfRequireAuth;
}
@@ -86,22 +78,19 @@ TER AccountSetTransactor::doApply ()
if (bSetRequireDest && bClearRequireDest)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";
m_journal.info << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG;
}
if (bSetRequireDest && !isSetBit (uFlagsIn, lsfRequireDestTag))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfRequireDestTag.";
m_journal.info << "Set lsfRequireDestTag.";
uFlagsOut |= lsfRequireDestTag;
}
if (bClearRequireDest && isSetBit (uFlagsIn, lsfRequireDestTag))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfRequireDestTag.";
m_journal.info << "Clear lsfRequireDestTag.";
uFlagsOut &= ~lsfRequireDestTag;
}
@@ -111,22 +100,19 @@ TER AccountSetTransactor::doApply ()
if (bSetDisallowXRP && bClearDisallowXRP)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";
m_journal.info << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG;
}
if (bSetDisallowXRP && !isSetBit (uFlagsIn, lsfDisallowXRP))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfDisallowXRP.";
m_journal.info << "Set lsfDisallowXRP.";
uFlagsOut |= lsfDisallowXRP;
}
if (bClearDisallowXRP && isSetBit (uFlagsIn, lsfDisallowXRP))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfDisallowXRP.";
m_journal.info << "Clear lsfDisallowXRP.";
uFlagsOut &= ~lsfDisallowXRP;
}
@@ -136,8 +122,7 @@ TER AccountSetTransactor::doApply ()
if ((uSetFlag == asfDisableMaster) && (uClearFlag == asfDisableMaster))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";
m_journal.info << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG;
}
@@ -146,15 +131,13 @@ TER AccountSetTransactor::doApply ()
if (!mTxnAccount->isFieldPresent (sfRegularKey))
return tecNO_REGULAR_KEY;
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfDisableMaster.";
m_journal.info << "Set lsfDisableMaster.";
uFlagsOut |= lsfDisableMaster;
}
if ((uClearFlag == asfDisableMaster) && isSetBit (uFlagsIn, lsfDisableMaster))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfDisableMaster.";
m_journal.info << "Clear lsfDisableMaster.";
uFlagsOut &= ~lsfDisableMaster;
}
@@ -164,15 +147,13 @@ TER AccountSetTransactor::doApply ()
if ((uSetFlag == asfAccountTxnID) && (uClearFlag != asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set AccountTxnID";
m_journal.info << "Set AccountTxnID";
mTxnAccount->makeFieldPresent (sfAccountTxnID);
}
if ((uClearFlag == asfAccountTxnID) && (uSetFlag != asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear AccountTxnID";
m_journal.info << "Clear AccountTxnID";
mTxnAccount->makeFieldAbsent (sfAccountTxnID);
}
@@ -186,14 +167,12 @@ TER AccountSetTransactor::doApply ()
if (!uHash)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset email hash";
m_journal.info << "unset email hash";
mTxnAccount->makeFieldAbsent (sfEmailHash);
}
else
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set email hash";
m_journal.info << "set email hash";
mTxnAccount->setFieldH128 (sfEmailHash, uHash);
}
}
@@ -208,14 +187,12 @@ TER AccountSetTransactor::doApply ()
if (!uHash)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset wallet locator";
m_journal.info << "unset wallet locator";
mTxnAccount->makeFieldAbsent (sfEmailHash);
}
else
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set wallet locator";
m_journal.info << "set wallet locator";
mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
}
}
@@ -230,19 +207,19 @@ TER AccountSetTransactor::doApply ()
if (vucPublic.empty ())
{
WriteLog (lsDEBUG, AccountSetTransactor) << "AccountSet: set message key";
m_journal.debug << "set message key";
mTxnAccount->makeFieldAbsent (sfMessageKey);
}
if (vucPublic.size () > PUBLIC_BYTES_MAX)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: message key too long";
m_journal.info << "message key too long";
return telBAD_PUBLIC_KEY;
}
else
{
WriteLog (lsDEBUG, AccountSetTransactor) << "AccountSet: set message key";
m_journal.debug << "set message key";
mTxnAccount->setFieldVL (sfMessageKey, vucPublic);
}
@@ -258,19 +235,19 @@ TER AccountSetTransactor::doApply ()
if (vucDomain.empty ())
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset domain";
m_journal.info << "unset domain";
mTxnAccount->makeFieldAbsent (sfDomain);
}
else if (vucDomain.size () > DOMAIN_BYTES_MAX)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: domain too long";
m_journal.info << "domain too long";
return telBAD_DOMAIN;
}
else
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set domain";
m_journal.info << "set domain";
mTxnAccount->setFieldVL (sfDomain, vucDomain);
}
@@ -282,24 +259,21 @@ TER AccountSetTransactor::doApply ()
if (mTxn.isFieldPresent (sfTransferRate))
{
std::uint32_t uRate = mTxn.getFieldU32 (sfTransferRate);
std::uint32_t uRate = mTxn.getFieldU32 (sfTransferRate);
if (!uRate || uRate == QUALITY_ONE)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset transfer rate";
m_journal.info << "unset transfer rate";
mTxnAccount->makeFieldAbsent (sfTransferRate);
}
else if (uRate > QUALITY_ONE)
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set transfer rate";
m_journal.info << "set transfer rate";
mTxnAccount->setFieldU32 (sfTransferRate, uRate);
}
else
{
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: bad transfer rate";
m_journal.info << "bad transfer rate";
return temBAD_TRANSFER_RATE;
}
}
@@ -307,8 +281,6 @@ TER AccountSetTransactor::doApply ()
if (uFlagsIn != uFlagsOut)
mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);
WriteLog (lsINFO, AccountSetTransactor) << "AccountSet<";
return tesSUCCESS;
}

View File

@@ -17,17 +17,38 @@
*/
//==============================================================================
#ifndef ACCOUNTSETTRANSACTOR_H
#define ACCOUNTSETTRANSACTOR_H
#ifndef RIPPLE_TX_ACCOUNTSET_H_INCLUDED
#define RIPPLE_TX_ACCOUNTSET_H_INCLUDED
namespace ripple {
class AccountSetTransactor : public Transactor
class AccountSetTransactorLog;
template <>
char const*
LogPartition::getPartitionName <AccountSetTransactorLog> ()
{
return "Tx/AccountSet";
}
class AccountSetTransactor
: public Transactor
{
public:
AccountSetTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
AccountSetTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <AccountSetTransactorLog> ())
{
TER doApply ();
}
TER doApply () override;
};
}

View File

@@ -19,8 +19,6 @@
namespace ripple {
SETUP_LOG (ChangeTransactor)
TER ChangeTransactor::doApply ()
{
if (mTxn.getTxnType () == ttFEATURE)
@@ -36,13 +34,13 @@ TER ChangeTransactor::checkSig ()
{
if (mTxn.getFieldAccount160 (sfAccount).isNonZero ())
{
WriteLog (lsWARNING, ChangeTransactor) << "Change transaction had bad source account";
m_journal.warning << "Bad source account";
return temBAD_SRC_ACCOUNT;
}
if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ())
{
WriteLog (lsWARNING, ChangeTransactor) << "Change transaction had bad signature";
m_journal.warning << "Bad signature";
return temBAD_SIGNATURE;
}
@@ -53,7 +51,7 @@ TER ChangeTransactor::checkSeq ()
{
if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID))
{
WriteLog (lsWARNING, ChangeTransactor) << "Change transaction had bad sequence";
m_journal.warning << "Bad sequence";
return temBAD_SEQUENCE;
}
@@ -64,7 +62,7 @@ TER ChangeTransactor::payFee ()
{
if (mTxn.getTransactionFee () != STAmount ())
{
WriteLog (lsWARNING, ChangeTransactor) << "Change transaction with non-zero fee";
m_journal.warning << "Non-zero fee";
return temBAD_FEE;
}
@@ -77,14 +75,14 @@ TER ChangeTransactor::preCheck ()
if (mTxnAccountID.isNonZero ())
{
WriteLog (lsWARNING, ChangeTransactor) << "applyTransaction: bad source id";
m_journal.warning << "Bad source id";
return temBAD_SRC_ACCOUNT;
}
if (isSetBit (mParams, tapOPEN_LEDGER))
{
WriteLog (lsWARNING, ChangeTransactor) << "Change transaction against open ledger";
m_journal.warning << "Change transaction against open ledger";
return temINVALID;
}
@@ -93,14 +91,16 @@ TER ChangeTransactor::preCheck ()
TER ChangeTransactor::applyFeature ()
{
uint256 feature = mTxn.getFieldH256 (sfFeature);
uint256 feature (mTxn.getFieldH256 (sfFeature));
SLE::pointer featureObject = mEngine->entryCache (ltFEATURES, Ledger::getLedgerFeatureIndex ());
SLE::pointer featureObject (mEngine->entryCache (
ltFEATURES, Ledger::getLedgerFeatureIndex ()));
if (!featureObject)
featureObject = mEngine->entryCreate (ltFEATURES, Ledger::getLedgerFeatureIndex ());
featureObject = mEngine->entryCreate (
ltFEATURES, Ledger::getLedgerFeatureIndex ());
STVector256 features = featureObject->getFieldV256 (sfFeatures);
STVector256 features (featureObject->getFieldV256 (sfFeatures));
if (features.hasValue (feature))
return tefALREADY;
@@ -120,22 +120,30 @@ TER ChangeTransactor::applyFeature ()
TER ChangeTransactor::applyFee ()
{
SLE::pointer feeObject = mEngine->entryCache (ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
SLE::pointer feeObject = mEngine->entryCache (
ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
if (!feeObject)
feeObject = mEngine->entryCreate (ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
feeObject = mEngine->entryCreate (
ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
WriteLog (lsINFO, ChangeTransactor) << "Previous fee object: " << feeObject->getJson (0);
m_journal.info <<
"Previous fee object: " << feeObject->getJson (0);
feeObject->setFieldU64 (sfBaseFee, mTxn.getFieldU64 (sfBaseFee));
feeObject->setFieldU32 (sfReferenceFeeUnits, mTxn.getFieldU32 (sfReferenceFeeUnits));
feeObject->setFieldU32 (sfReserveBase, mTxn.getFieldU32 (sfReserveBase));
feeObject->setFieldU32 (sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
feeObject->setFieldU64 (
sfBaseFee, mTxn.getFieldU64 (sfBaseFee));
feeObject->setFieldU32 (
sfReferenceFeeUnits, mTxn.getFieldU32 (sfReferenceFeeUnits));
feeObject->setFieldU32 (
sfReserveBase, mTxn.getFieldU32 (sfReserveBase));
feeObject->setFieldU32 (
sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
mEngine->entryModify (feeObject);
WriteLog (lsINFO, ChangeTransactor) << "New fee object: " << feeObject->getJson (0);
WriteLog (lsWARNING, ChangeTransactor) << "Fees have been changed";
m_journal.info <<
"New fee object: " << feeObject->getJson (0);
m_journal.warning << "Fees have been changed";
return tesSUCCESS;
}

View File

@@ -17,32 +17,53 @@
*/
//==============================================================================
#ifndef RIPPLE_TX_CHANGE_H_INCLUDED
#define RIPPLE_TX_CHANGE_H_INCLUDED
namespace ripple {
class ChangeTransactor : public Transactor
class ChangeTransactorLog;
template <>
char const*
LogPartition::getPartitionName <ChangeTransactorLog> ()
{
return "Tx/Change";
}
class ChangeTransactor
: public Transactor
{
public:
ChangeTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine)
: Transactor (txn, params, engine)
ChangeTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <ChangeTransactorLog> ())
{
;
}
TER doApply ();
TER checkSig ();
TER checkSeq ();
TER payFee ();
TER preCheck ();
TER doApply () override;
TER checkSig () override;
TER checkSeq () override;
TER payFee () override;
TER preCheck () override;
private:
TER applyFeature ();
TER applyFee ();
// VFALCO TODO Can this be removed?
bool mustHaveValidAccount ()
bool mustHaveValidAccount () override
{
return false;
}
};
}
#endif

View File

@@ -19,54 +19,54 @@
namespace ripple {
SETUP_LOG (OfferCancelTransactor)
TER OfferCancelTransactor::doApply ()
{
TER terResult;
const std::uint32_t uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
const std::uint32_t uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
WriteLog (lsDEBUG, OfferCancelTransactor) << "OfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
m_journal.debug <<
"uAccountSequenceNext=" << uAccountSequenceNext <<
" uOfferSequence=" << uOfferSequence;
const std::uint32_t uTxFlags = mTxn.getFlags ();
std::uint32_t const uTxFlags (mTxn.getFlags ());
if (uTxFlags & tfUniversalMask)
{
WriteLog (lsINFO, OfferCancelTransactor) << "OfferCancel: Malformed transaction: Invalid flags set.";
m_journal.info <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
if (!uOfferSequence || uAccountSequenceNext - 1 <= uOfferSequence)
{
WriteLog (lsINFO, OfferCancelTransactor) << "OfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
terResult = temBAD_SEQUENCE;
m_journal.info <<
"uAccountSequenceNext=" << uAccountSequenceNext <<
" uOfferSequence=" << uOfferSequence;
return temBAD_SEQUENCE;
}
else
uint256 const uOfferIndex (
Ledger::getOfferIndex (mTxnAccountID, uOfferSequence));
SLE::pointer sleOffer (
mEngine->entryCache (ltOFFER, uOfferIndex));
if (sleOffer)
{
const uint256 uOfferIndex = Ledger::getOfferIndex (mTxnAccountID, uOfferSequence);
SLE::pointer sleOffer = mEngine->entryCache (ltOFFER, uOfferIndex);
m_journal.debug <<
"OfferCancel: uOfferSequence=" << uOfferSequence;
if (sleOffer)
{
WriteLog (lsDEBUG, OfferCancelTransactor) << "OfferCancel: uOfferSequence=" << uOfferSequence;
terResult = mEngine->getNodes ().offerDelete (sleOffer);
}
else
{
WriteLog (lsWARNING, OfferCancelTransactor) << "OfferCancel: offer not found: "
<< RippleAddress::createHumanAccountID (mTxnAccountID)
<< " : " << uOfferSequence
<< " : " << uOfferIndex.ToString ();
terResult = tesSUCCESS;
}
return mEngine->getNodes ().offerDelete (sleOffer);
}
return terResult;
m_journal.warning <<
"OfferCancel: offer not found: " <<
RippleAddress::createHumanAccountID (mTxnAccountID) <<
" : " << uOfferSequence <<
" : " << uOfferIndex.ToString ();
return tesSUCCESS;
}
}

View File

@@ -17,17 +17,38 @@
*/
//==============================================================================
#ifndef OFFERCANCELTRANSACTOR_H
#define OFFERCANCELTRANSACTOR_H
#ifndef RIPPLE_TX_OFFERCANCEL_H_INCLUDED
#define RIPPLE_TX_OFFERCANCEL_H_INCLUDED
namespace ripple {
class OfferCancelTransactor : public Transactor
class OfferCancelTransactorLog;
template <>
char const*
LogPartition::getPartitionName <OfferCancelTransactorLog> ()
{
return "Tx/OfferCancel";
}
class OfferCancelTransactor
: public Transactor
{
public:
OfferCancelTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
OfferCancelTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <OfferCancelTransactorLog> ())
{
TER doApply ();
}
TER doApply () override;
};
}

View File

@@ -17,16 +17,10 @@
*/
//==============================================================================
#include "../../ripple_basics/log/LogPartition.h"
#include "../../ripple_basics/utility/PlatformMacros.h"
#include "OfferCreateTransactor.h"
namespace ripple {
SETUP_LOG (OfferCreateTransactor)
// Make sure an offer is still valid. If not, mark it unfunded.
bool OfferCreateTransactor::bValidOffer (
bool OfferCreateTransactor::isValidOffer (
SLE::ref sleOffer,
const uint160& uOfferOwnerID,
const STAmount& saOfferPays,
@@ -35,14 +29,14 @@ bool OfferCreateTransactor::bValidOffer (
boost::unordered_set<uint256>& usOfferUnfundedFound,
boost::unordered_set<uint256>& usOfferUnfundedBecame,
boost::unordered_set<uint160>& usAccountTouched,
STAmount& saOfferFunds) // <--
STAmount& saOfferFunds) const // <--
{
bool bValid = false;
if (sleOffer->isFieldPresent (sfExpiration) && sleOffer->getFieldU32 (sfExpiration) <= mEngine->getLedger ()->getParentCloseTimeNC ())
{
// Offer is expired. Expired offers are considered unfunded. Delete it.
WriteLog (lsINFO, OfferCreateTransactor) << "bValidOffer: encountered expired offer";
m_journal.info << "isValidOffer: encountered expired offer";
usOfferUnfundedFound.insert (sleOffer->getIndex());
@@ -51,7 +45,7 @@ bool OfferCreateTransactor::bValidOffer (
else if (uOfferOwnerID == uTakerAccountID)
{
// Would take own offer. Consider old offer expired. Delete it.
WriteLog (lsINFO, OfferCreateTransactor) << "bValidOffer: encountered taker's own old offer";
m_journal.info << "isValidOffer: encountered taker's own old offer";
usOfferUnfundedFound.insert (sleOffer->getIndex());
@@ -60,8 +54,9 @@ bool OfferCreateTransactor::bValidOffer (
else if (!saOfferGets.isPositive () || !saOfferPays.isPositive ())
{
// Offer has bad amounts. Consider offer expired. Delete it.
WriteLog (lsWARNING, OfferCreateTransactor) << boost::str (boost::format ("bValidOffer: BAD OFFER: saOfferPays=%s saOfferGets=%s")
% saOfferPays % saOfferGets);
m_journal.warning << "isValidOffer: BAD OFFER:" <<
" saOfferPays=" << saOfferPays <<
" saOfferGets=" << saOfferGets;
usOfferUnfundedFound.insert (sleOffer->getIndex());
@@ -69,14 +64,14 @@ bool OfferCreateTransactor::bValidOffer (
}
else
{
WriteLog (lsTRACE, OfferCreateTransactor) << "bValidOffer: saOfferPays=" << saOfferPays.getFullText ();
m_journal.trace << "isValidOffer: saOfferPays=" << saOfferPays.getFullText ();
saOfferFunds = mEngine->getNodes ().accountFunds (uOfferOwnerID, saOfferPays);
if (!saOfferFunds.isPositive ())
{
// Offer is unfunded, possibly due to previous balance action.
WriteLog (lsDEBUG, OfferCreateTransactor) << "bValidOffer: offer unfunded: delete";
m_journal.debug << "isValidOffer: offer unfunded: delete";
boost::unordered_set<uint160>::iterator account = usAccountTouched.find (uOfferOwnerID);
@@ -132,7 +127,7 @@ TER OfferCreateTransactor::takeOffers (
assert (saTakerPays && saTakerGets);
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: bSell: " << bSell << ": against book: " << uBookBase.ToString ();
m_journal.debug << "takeOffers: bSell: " << bSell << ": against book: " << uBookBase.ToString ();
LedgerEntrySet& lesActive = mEngine->getNodes ();
const std::uint64_t uTakeQuality = STAmount::getRate (saTakerGets, saTakerPays);
@@ -157,7 +152,7 @@ TER OfferCreateTransactor::takeOffers (
STAmount saTakerFunds = lesActive.accountFunds (uTakerAccountID, saTakerPays);
STAmount saSubTakerPays = saTakerPays - saTakerPaid; // How much more to spend.
STAmount saSubTakerGets = saTakerGets - saTakerGot; // How much more is wanted.
std::uint64_t uTipQuality = bookIterator.getCurrentQuality();
std::uint64_t uTipQuality = bookIterator.getCurrentQuality();
if (!saTakerFunds.isPositive ())
{
@@ -176,22 +171,14 @@ TER OfferCreateTransactor::takeOffers (
// Offer does not cross this offer
STAmount saTipRate = STAmount::setRate (uTipQuality);
WriteLog (lsDEBUG, OfferCreateTransactor) << boost::str (boost::format ("takeOffers: done: uTakeQuality=%d %c uTipQuality=%d saTakerRate=%s %c saTipRate=%s bPassive=%d")
% uTakeQuality
% (uTakeQuality == uTipQuality
? '='
: uTakeQuality < uTipQuality
? '<'
: '>')
% uTipQuality
% saTakerRate
% (saTakerRate == saTipRate
? '='
: saTakerRate < saTipRate
? '<'
: '>')
% saTipRate
% bPassive);
m_journal.debug << "takeOffers: done:" <<
" uTakeQuality=" << uTakeQuality <<
" " << get_compare_sign (uTakeQuality, uTipQuality) <<
" uTipQuality=" << uTipQuality <<
" saTakerRate=" << saTakerRate <<
" " << get_compare_sign (saTakerRate, saTipRate) <<
" saTipRate=" << saTakerRate <<
" bPassive=" << bPassive;
terResult = tesSUCCESS;
}
@@ -204,13 +191,13 @@ TER OfferCreateTransactor::takeOffers (
if (!sleOffer)
{ // offer is in directory but not in ledger
uint256 offerIndex = bookIterator.getCurrentIndex ();
WriteLog (lsWARNING, OfferCreateTransactor) << "takeOffers: offer not found : " << offerIndex;
m_journal.warning << "takeOffers: offer not found : " << offerIndex;
usMissingOffers.insert (missingOffer_t (
bookIterator.getCurrentIndex (), bookIterator.getCurrentDirectory ()));
}
else
{
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: considering offer : " << sleOffer->getJson (0);
m_journal.debug << "takeOffers: considering offer : " << sleOffer->getJson (0);
const uint160& uOfferOwnerID = sleOffer->getFieldAccount160 (sfAccount);
STAmount saOfferPays = sleOffer->getFieldAmount (sfTakerGets);
@@ -219,7 +206,7 @@ TER OfferCreateTransactor::takeOffers (
STAmount saOfferFunds; // Funds of offer owner to payout.
bool bValid;
bValid = bValidOffer (
bValid = isValidOffer (
sleOffer, uOfferOwnerID, saOfferPays, saOfferGets,
uTakerAccountID,
usOfferUnfundedFound, usOfferUnfundedBecame, usAccountTouched,
@@ -233,17 +220,17 @@ TER OfferCreateTransactor::takeOffers (
STAmount saOfferIssuerFee;
STAmount saOfferRate = STAmount::setRate (uTipQuality);
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerFunds: " << saTakerFunds.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saOfferFunds: " << saOfferFunds.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saOfferRate: " << saOfferRate.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saSubTakerPays: " << saSubTakerPays.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saSubTakerGets: " << saSubTakerGets.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText ();
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saTakerFunds: " << saTakerFunds.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saOfferFunds: " << saOfferFunds.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saOfferPays: " << saOfferPays.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saOfferRate: " << saOfferRate.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saSubTakerPays: " << saSubTakerPays.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saSubTakerGets: " << saSubTakerGets.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText ();
m_journal.trace << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText ();
bool bOfferDelete = STAmount::applyOffer (
bSell,
@@ -261,8 +248,8 @@ TER OfferCreateTransactor::takeOffers (
saTakerIssuerFee,
saOfferIssuerFee);
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText ();
// Adjust offer
@@ -277,7 +264,7 @@ TER OfferCreateTransactor::takeOffers (
if (bOfferDelete)
{
// Offer now fully claimed or now unfunded.
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: Offer claimed: Delete.";
m_journal.debug << "takeOffers: Offer claimed: Delete.";
usOfferUnfundedBecame.insert (sleOffer->getIndex()); // Delete unfunded offer on success.
@@ -286,11 +273,11 @@ TER OfferCreateTransactor::takeOffers (
}
else if (saSubTakerGot)
{
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: Offer partial claim.";
m_journal.debug << "takeOffers: Offer partial claim.";
if (!saOfferPays.isPositive () || !saOfferGets.isPositive ())
{
WriteLog (lsWARNING, OfferCreateTransactor) << "takeOffers: ILLEGAL OFFER RESULT.";
m_journal.warning << "takeOffers: ILLEGAL OFFER RESULT.";
bUnfunded = true;
terResult = bOpenLedger ? telFAILED_PROCESSING : tecFAILED_PROCESSING;
}
@@ -298,7 +285,7 @@ TER OfferCreateTransactor::takeOffers (
else
{
// Taker got nothing, probably due to rounding. Consider taker unfunded.
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: No claim.";
m_journal.debug << "takeOffers: No claim.";
bUnfunded = true;
terResult = tesSUCCESS; // Done.
@@ -335,10 +322,10 @@ TER OfferCreateTransactor::takeOffers (
STAmount saTakerUsed = STAmount::multiply (saSubTakerGot, saTakerRate, saTakerPays);
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerCould: " << saTakerCould.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerRate: " << saTakerRate.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: applyOffer: saTakerUsed: " << saTakerUsed.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saTakerCould: " << saTakerCould.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saTakerRate: " << saTakerRate.getFullText ();
m_journal.debug << "takeOffers: applyOffer: saTakerUsed: " << saTakerUsed.getFullText ();
saSubTakerPaid = std::min (saTakerCould, saTakerUsed);
}
@@ -357,28 +344,28 @@ TER OfferCreateTransactor::takeOffers (
if (temUNCERTAIN == terResult)
terResult = tesSUCCESS;
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: " << transToken (terResult);
m_journal.debug << "takeOffers: " << transToken (terResult);
if (tesSUCCESS == terResult)
{
// On success, delete offers that became unfunded.
BOOST_FOREACH (uint256 const & uOfferIndex, usOfferUnfundedBecame)
{
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: became unfunded: " << uOfferIndex.ToString ();
m_journal.debug << "takeOffers: became unfunded: " << uOfferIndex.ToString ();
lesActive.offerDelete (uOfferIndex);
}
}
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers< " << transToken (terResult);
m_journal.debug << "takeOffers< " << transToken (terResult);
return terResult;
}
TER OfferCreateTransactor::doApply ()
{
WriteLog (lsTRACE, OfferCreateTransactor) << "OfferCreate> " << mTxn.getJson (0);
const std::uint32_t uTxFlags = mTxn.getFlags ();
m_journal.trace << "OfferCreate> " << mTxn.getJson (0);
const std::uint32_t uTxFlags = mTxn.getFlags ();
const bool bPassive = isSetBit (uTxFlags, tfPassive);
const bool bImmediateOrCancel = isSetBit (uTxFlags, tfImmediateOrCancel);
const bool bFillOrKill = isSetBit (uTxFlags, tfFillOrKill);
@@ -389,31 +376,31 @@ TER OfferCreateTransactor::doApply ()
if (!saTakerPays.isLegalNet () || !saTakerGets.isLegalNet ())
return temBAD_AMOUNT;
WriteLog (lsTRACE, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: saTakerPays=%s saTakerGets=%s")
% saTakerPays.getFullText ()
% saTakerGets.getFullText ());
m_journal.trace <<
"saTakerPays=" << saTakerPays.getFullText () <<
" saTakerGets=" << saTakerGets.getFullText ();
const uint160 uPaysIssuerID = saTakerPays.getIssuer ();
const uint160 uGetsIssuerID = saTakerGets.getIssuer ();
const std::uint32_t uExpiration = mTxn.getFieldU32 (sfExpiration);
const std::uint32_t uExpiration = mTxn.getFieldU32 (sfExpiration);
const bool bHaveExpiration = mTxn.isFieldPresent (sfExpiration);
const bool bHaveCancel = mTxn.isFieldPresent (sfOfferSequence);
const std::uint32_t uCancelSequence = mTxn.getFieldU32 (sfOfferSequence);
const std::uint32_t uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
const std::uint32_t uSequence = mTxn.getSequence ();
const std::uint32_t uCancelSequence = mTxn.getFieldU32 (sfOfferSequence);
const std::uint32_t uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
const std::uint32_t uSequence = mTxn.getSequence ();
const uint256 uLedgerIndex = Ledger::getOfferIndex (mTxnAccountID, uSequence);
WriteLog (lsTRACE, OfferCreateTransactor) << "OfferCreate: Creating offer node: " << uLedgerIndex.ToString () << " uSequence=" << uSequence;
m_journal.trace << "Creating offer node: " << uLedgerIndex.ToString () << " uSequence=" << uSequence;
const uint160 uPaysCurrency = saTakerPays.getCurrency ();
const uint160 uGetsCurrency = saTakerGets.getCurrency ();
const std::uint64_t uRate = STAmount::getRate (saTakerGets, saTakerPays);
const std::uint64_t uRate = STAmount::getRate (saTakerGets, saTakerPays);
TER terResult = tesSUCCESS;
uint256 uDirectory; // Delete hints.
std::uint64_t uOwnerNode;
std::uint64_t uBookNode;
std::uint64_t uOwnerNode;
std::uint64_t uBookNode;
LedgerEntrySet& lesActive = mEngine->getNodes ();
LedgerEntrySet lesCheckpoint = lesActive; // Checkpoint with just fees paid.
@@ -423,61 +410,61 @@ TER OfferCreateTransactor::doApply ()
if (uTxFlags & tfOfferCreateMask)
{
WriteLog (lsINFO, OfferCreateTransactor) << "OfferCreate: Malformed transaction: Invalid flags set.";
m_journal.info << "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
else if (bImmediateOrCancel && bFillOrKill)
{
WriteLog (lsINFO, OfferCreateTransactor) << "OfferCreate: Malformed transaction: both IoC and FoK set.";
m_journal.info << "Malformed transaction: both IoC and FoK set.";
return temINVALID_FLAG;
}
else if (bHaveExpiration && !uExpiration)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: bad expiration";
m_journal.warning << "Malformed offer: bad expiration";
terResult = temBAD_EXPIRATION;
}
else if (saTakerPays.isNative () && saTakerGets.isNative ())
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: XRP for XRP";
m_journal.warning << "Malformed offer: XRP for XRP";
terResult = temBAD_OFFER;
}
else if (!saTakerPays.isPositive () || !saTakerGets.isPositive ())
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: bad amount";
m_journal.warning << "Malformed offer: bad amount";
terResult = temBAD_OFFER;
}
else if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: redundant offer";
m_journal.warning << "Malformed offer: redundant offer";
terResult = temREDUNDANT;
}
else if (CURRENCY_BAD == uPaysCurrency || CURRENCY_BAD == uGetsCurrency)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: Bad currency.";
m_journal.warning << "Malformed offer: Bad currency.";
terResult = temBAD_CURRENCY;
}
else if (saTakerPays.isNative () != !uPaysIssuerID || saTakerGets.isNative () != !uGetsIssuerID)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: bad issuer";
m_journal.warning << "Malformed offer: bad issuer";
terResult = temBAD_ISSUER;
}
else if (!lesActive.accountFunds (mTxnAccountID, saTakerGets).isPositive ())
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: delay: Offers must be at least partially funded.";
m_journal.warning << "delay: Offers must be at least partially funded.";
terResult = tecUNFUNDED_OFFER;
}
else if (bHaveCancel && (!uCancelSequence || uAccountSequenceNext - 1 <= uCancelSequence))
{
WriteLog (lsINFO, OfferCreateTransactor) << "OfferCreate: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uCancelSequence;
m_journal.info << "uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uCancelSequence;
terResult = temBAD_SEQUENCE;
}
@@ -490,13 +477,13 @@ TER OfferCreateTransactor::doApply ()
if (sleCancel)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: uCancelSequence=" << uCancelSequence;
m_journal.warning << "uCancelSequence=" << uCancelSequence;
terResult = mEngine->getNodes ().offerDelete (sleCancel);
}
else
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: offer not found: "
m_journal.warning << "offer not found: "
<< RippleAddress::createHumanAccountID (mTxnAccountID)
<< " : " << uCancelSequence
<< " : " << uCancelIndex.ToString ();
@@ -511,7 +498,7 @@ TER OfferCreateTransactor::doApply ()
if (!sleTakerPays)
{
WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: delay: can't receive IOUs from non-existent issuer: " << RippleAddress::createHumanAccountID (uPaysIssuerID);
m_journal.warning << "delay: can't receive IOUs from non-existent issuer: " << RippleAddress::createHumanAccountID (uPaysIssuerID);
terResult = isSetBit (mParams, tapRETRY) ? terNO_ACCOUNT : tecNO_ISSUER;
}
@@ -526,7 +513,7 @@ TER OfferCreateTransactor::doApply ()
}
else if (!isSetBit (sleRippleState->getFieldU32 (sfFlags), (bHigh ? lsfHighAuth : lsfLowAuth)))
{
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: delay: can't receive IOUs from issuer without auth.";
m_journal.debug << "delay: can't receive IOUs from issuer without auth.";
terResult = isSetBit (mParams, tapRETRY) ? terNO_AUTH : tecNO_AUTH;
}
@@ -542,13 +529,14 @@ TER OfferCreateTransactor::doApply ()
{
const uint256 uTakeBookBase = Ledger::getBookBase (uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID);
WriteLog (lsINFO, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: take against book: %s for %s -> %s")
% uTakeBookBase.ToString ()
% saTakerGets.getFullText ()
% saTakerPays.getFullText ());
m_journal.info <<
"take against book:" << uTakeBookBase.ToString () <<
" for " << saTakerGets.getFullText () <<
" -> " << saTakerPays.getFullText ();
// Take using the parameters of the offer.
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: BEFORE saTakerGets=" << saTakerGets.getFullText ();
m_journal.debug <<
"takeOffers: BEFORE saTakerGets=" << saTakerGets.getFullText ();
terResult = takeOffers (
bOpenLedger,
@@ -563,27 +551,32 @@ TER OfferCreateTransactor::doApply ()
saGot, // How much was got.
bUnfunded);
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers=" << terResult;
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: saPaid=" << saPaid.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: saGot=" << saGot.getFullText ();
m_journal.debug << "takeOffers=" << terResult;
m_journal.debug << "takeOffers: saPaid=" << saPaid.getFullText ();
m_journal.debug << "takeOffers: saGot=" << saGot.getFullText ();
if (tesSUCCESS == terResult && !bUnfunded)
{
saTakerPays -= saGot; // Reduce pay in from takers by what offer just got.
saTakerGets -= saPaid; // Reduce pay out to takers by what srcAccount just paid.
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: AFTER saTakerPays=" << saTakerPays.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: AFTER saTakerGets=" << saTakerGets.getFullText ();
m_journal.debug <<
"takeOffers: AFTER saTakerPays=" << saTakerPays.getFullText ();
m_journal.debug <<
"takeOffers: AFTER saTakerGets=" << saTakerGets.getFullText ();
}
}
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: saTakerGets=" << saTakerGets.getFullText ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: mTxnAccountID=" << RippleAddress::createHumanAccountID (mTxnAccountID);
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: FUNDS=" << lesActive.accountFunds (mTxnAccountID, saTakerGets).getFullText ();
// WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: uPaysIssuerID=" << RippleAddress::createHumanAccountID(uPaysIssuerID);
// WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: takeOffers: uGetsIssuerID=" << RippleAddress::createHumanAccountID(uGetsIssuerID);
m_journal.debug <<
"takeOffers: saTakerPays=" <<saTakerPays.getFullText ();
m_journal.debug <<
"takeOffers: saTakerGets=" << saTakerGets.getFullText ();
m_journal.debug <<
"takeOffers: mTxnAccountID=" <<
RippleAddress::createHumanAccountID (mTxnAccountID);
m_journal.debug <<
"takeOffers: FUNDS=" <<
lesActive.accountFunds (mTxnAccountID, saTakerGets).getFullText ();
if (tesSUCCESS != terResult)
{
@@ -639,9 +632,9 @@ TER OfferCreateTransactor::doApply ()
else
{
// We need to place the remainder of the offer into its order book.
WriteLog (lsINFO, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: offer not fully consumed: saTakerPays=%s saTakerGets=%s")
% saTakerPays.getFullText ()
% saTakerGets.getFullText ());
m_journal.info << "offer not fully consumed:"
" saTakerPays=" << saTakerPays.getFullText () <<
" saTakerGets=" << saTakerGets.getFullText ();
// Add offer to owner's directory.
terResult = lesActive.dirAdd (uOwnerNode, Ledger::getOwnerDirIndex (mTxnAccountID), uLedgerIndex,
@@ -654,12 +647,12 @@ TER OfferCreateTransactor::doApply ()
uint256 uBookBase = Ledger::getBookBase (uPaysCurrency, uPaysIssuerID, uGetsCurrency, uGetsIssuerID);
WriteLog (lsINFO, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: adding to book: %s : %s/%s -> %s/%s")
% uBookBase.ToString ()
% saTakerPays.getHumanCurrency ()
% RippleAddress::createHumanAccountID (saTakerPays.getIssuer ())
% saTakerGets.getHumanCurrency ()
% RippleAddress::createHumanAccountID (saTakerGets.getIssuer ()));
m_journal.info <<
"adding to book: " << uBookBase.ToString () <<
" : " << saTakerPays.getHumanCurrency () <<
"/" << RippleAddress::createHumanAccountID (saTakerPays.getIssuer ()) <<
" -> " << saTakerGets.getHumanCurrency () <<
"/" << RippleAddress::createHumanAccountID (saTakerGets.getIssuer ());
uDirectory = Ledger::getQualityIndex (uBookBase, uRate); // Use original rate.
@@ -672,15 +665,22 @@ TER OfferCreateTransactor::doApply ()
if (tesSUCCESS == terResult)
{
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: sfAccount=" << RippleAddress::createHumanAccountID (mTxnAccountID);
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: uPaysIssuerID=" << RippleAddress::createHumanAccountID (uPaysIssuerID);
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: uGetsIssuerID=" << RippleAddress::createHumanAccountID (uGetsIssuerID);
WriteLog (lsTRACE, OfferCreateTransactor) << "OfferCreate: saTakerPays.isNative()=" << saTakerPays.isNative ();
WriteLog (lsTRACE, OfferCreateTransactor) << "OfferCreate: saTakerGets.isNative()=" << saTakerGets.isNative ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: uPaysCurrency=" << saTakerPays.getHumanCurrency ();
WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: uGetsCurrency=" << saTakerGets.getHumanCurrency ();
m_journal.debug <<
"sfAccount=" << RippleAddress::createHumanAccountID (mTxnAccountID);
m_journal.debug <<
"uPaysIssuerID=" << RippleAddress::createHumanAccountID (uPaysIssuerID);
m_journal.debug <<
"uGetsIssuerID=" << RippleAddress::createHumanAccountID (uGetsIssuerID);
m_journal.trace <<
"saTakerPays.isNative()=" << saTakerPays.isNative ();
m_journal.trace <<
"saTakerGets.isNative()=" << saTakerGets.isNative ();
m_journal.debug <<
"uPaysCurrency=" << saTakerPays.getHumanCurrency ();
m_journal.debug <<
"uGetsCurrency=" << saTakerGets.getHumanCurrency ();
SLE::pointer sleOffer = mEngine->entryCreate (ltOFFER, uLedgerIndex);
SLE::pointer sleOffer (mEngine->entryCreate (ltOFFER, uLedgerIndex));
sleOffer->setFieldAccount (sfAccount, mTxnAccountID);
sleOffer->setFieldU32 (sfSequence, uSequence);
@@ -699,9 +699,9 @@ TER OfferCreateTransactor::doApply ()
if (bSell)
sleOffer->setFlag (lsfSell);
WriteLog (lsTRACE, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: final terResult=%s sleOffer=%s")
% transToken (terResult)
% sleOffer->getJson (0));
m_journal.trace <<
"final terResult=" << transToken (terResult) <<
" sleOffer=" << sleOffer->getJson (0);
}
}
@@ -712,8 +712,8 @@ TER OfferCreateTransactor::doApply ()
// Go through the list of unfunded offers and remove them
BOOST_FOREACH (uint256 const & uOfferIndex, usOfferUnfundedFound)
{
WriteLog (lsINFO, OfferCreateTransactor) << "takeOffers: found unfunded: " << uOfferIndex.ToString ();
m_journal.info <<
"takeOffers: found unfunded: " << uOfferIndex.ToString ();
lesActive.offerDelete (uOfferIndex);
@@ -733,24 +733,25 @@ TER OfferCreateTransactor::doApply ()
vuiIndexes.erase (it);
sleDirectory->setFieldV256 (sfIndexes, svIndexes);
lesActive.entryModify (sleDirectory);
WriteLog (lsWARNING, OfferCreateTransactor) << "takeOffers: offer " << indexes.first <<
m_journal.warning << "takeOffers: offer " << indexes.first <<
" removed from directory " << indexes.second;
}
else
{
WriteLog (lsINFO, OfferCreateTransactor) << "takeOffers: offer " << indexes.first <<
m_journal.info << "takeOffers: offer " << indexes.first <<
" not found in directory " << indexes.second;
}
}
else
{
WriteLog (lsWARNING, OfferCreateTransactor) << "takeOffers: directory " << indexes.second <<
m_journal.warning << "takeOffers: directory " << indexes.second <<
" not found for offer " << indexes.first;
}
}
}
CondLog (tesSUCCESS != terResult, lsINFO, OfferCreateTransactor) << boost::str (boost::format ("OfferCreate: final terResult=%s") % transToken (terResult));
if (tesSUCCESS != terResult) m_journal.info <<
"final terResult=" << transToken (terResult);
return terResult;
}

View File

@@ -17,43 +17,80 @@
*/
//==============================================================================
#ifndef __OFFERCREATETRANSACTOR__
#define __OFFERCREATETRANSACTOR__
#ifndef RIPPLE_TX_OFFERCREATE_H_INCLUDED
#define RIPPLE_TX_OFFERCREATE_H_INCLUDED
namespace ripple {
class OfferCreateTransactor : public Transactor
class OfferCreateTransactorLog;
template <>
char const*
LogPartition::getPartitionName <OfferCreateTransactorLog> ()
{
return "Tx/OfferCreate";
}
class OfferCreateTransactor
: public Transactor
{
private:
template <class T>
static std::string
get_compare_sign (T const& lhs, T const& rhs)
{
if (lhs > rhs)
return ">";
if (rhs > lhs)
return "<";
// If neither is bigger than the other, they must be equal
return "=";
}
public:
OfferCreateTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
OfferCreateTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <OfferCreateTransactorLog> ())
{
}
TER doApply ();
private:
bool bValidOffer (
bool isValidOffer (
SLE::ref sleOfferDir,
const uint160& uOfferOwnerID,
const STAmount& saOfferPays,
const STAmount& saOfferGets,
const uint160& uTakerAccountID,
uint160 const& uOfferOwnerID,
STAmount const& saOfferPays,
STAmount const& saOfferGets,
uint160 const& uTakerAccountID,
boost::unordered_set<uint256>& usOfferUnfundedFound,
boost::unordered_set<uint256>& usOfferUnfundedBecame,
boost::unordered_set<uint160>& usAccountTouched,
STAmount& saOfferFunds);
STAmount& saOfferFunds) const;
TER takeOffers (
const bool bOpenLedger,
const bool bPassive,
const bool bSell,
bool const bOpenLedger,
bool const bPassive,
bool const bSell,
uint256 const& uBookBase,
const uint160& uTakerAccountID,
uint160 const& uTakerAccountID,
SLE::ref sleTakerAccount,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
STAmount const& saTakerPays,
STAmount const& saTakerGets,
STAmount& saTakerPaid,
STAmount& saTakerGot,
bool& bUnfunded);
boost::unordered_set<uint256> usOfferUnfundedFound; // Offers found unfunded.
boost::unordered_set<uint256> usOfferUnfundedFound; // Offers found unfunded.
typedef std::pair <uint256, uint256> missingOffer_t;
std::set<missingOffer_t> usMissingOffers;

View File

@@ -19,115 +19,128 @@
namespace ripple {
SETUP_LOG (PaymentTransactor)
#define RIPPLE_PATHS_MAX 6
TER PaymentTransactor::doApply ()
{
// Ripple if source or destination is non-native or if there are paths.
const std::uint32_t uTxFlags = mTxn.getFlags ();
const bool bPartialPayment = isSetBit (uTxFlags, tfPartialPayment);
const bool bLimitQuality = isSetBit (uTxFlags, tfLimitQuality);
const bool bNoRippleDirect = isSetBit (uTxFlags, tfNoRippleDirect);
const bool bPaths = mTxn.isFieldPresent (sfPaths);
const bool bMax = mTxn.isFieldPresent (sfSendMax);
const uint160 uDstAccountID = mTxn.getFieldAccount160 (sfDestination);
const STAmount saDstAmount = mTxn.getFieldAmount (sfAmount);
const STAmount saMaxAmount = bMax
? mTxn.getFieldAmount (sfSendMax)
: saDstAmount.isNative ()
? saDstAmount
: STAmount (saDstAmount.getCurrency (), mTxnAccountID, saDstAmount.getMantissa (), saDstAmount.getExponent (), saDstAmount.isNegative ());
const uint160 uSrcCurrency = saMaxAmount.getCurrency ();
const uint160 uDstCurrency = saDstAmount.getCurrency ();
const bool bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const bPartialPayment = isSetBit (uTxFlags, tfPartialPayment);
bool const bLimitQuality = isSetBit (uTxFlags, tfLimitQuality);
bool const bNoRippleDirect = isSetBit (uTxFlags, tfNoRippleDirect);
bool const bPaths = mTxn.isFieldPresent (sfPaths);
bool const bMax = mTxn.isFieldPresent (sfSendMax);
uint160 const uDstAccountID = mTxn.getFieldAccount160 (sfDestination);
STAmount const saDstAmount = mTxn.getFieldAmount (sfAmount);
STAmount const saMaxAmount = bMax
? mTxn.getFieldAmount (sfSendMax)
: saDstAmount.isNative ()
? saDstAmount
: STAmount (saDstAmount.getCurrency (),
mTxnAccountID,
saDstAmount.getMantissa (),
saDstAmount.getExponent (),
saDstAmount.isNegative ());
uint160 const uSrcCurrency = saMaxAmount.getCurrency ();
uint160 const uDstCurrency = saDstAmount.getCurrency ();
bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
WriteLog (lsINFO, PaymentTransactor) << boost::str (boost::format ("Payment> saMaxAmount=%s saDstAmount=%s")
% saMaxAmount.getFullText ()
% saDstAmount.getFullText ());
m_journal.info <<
"saMaxAmount=" << saMaxAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText ();
if (!saDstAmount.isLegalNet () || !saMaxAmount.isLegalNet ())
return temBAD_AMOUNT;
if (uTxFlags & tfPaymentMask)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Invalid flags set.";
m_journal.info <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
else if (!uDstAccountID)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Payment destination account not specified.";
m_journal.info <<
"Malformed transaction: Payment destination account not specified.";
return temDST_NEEDED;
}
else if (bMax && !saMaxAmount.isPositive ())
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: bad max amount: " << saMaxAmount.getFullText ();
m_journal.info <<
"Malformed transaction: bad max amount: " << saMaxAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (!saDstAmount.isPositive ())
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
m_journal.info <<
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (CURRENCY_BAD == uSrcCurrency || CURRENCY_BAD == uDstCurrency)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Bad currency.";
m_journal.info <<
"Malformed transaction: Bad currency.";
return temBAD_CURRENCY;
}
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{
WriteLog (lsINFO, PaymentTransactor) << boost::str (boost::format ("Payment: Malformed transaction: Redundant transaction: src=%s, dst=%s, src_cur=%s, dst_cur=%s")
% mTxnAccountID.ToString ()
% uDstAccountID.ToString ()
% uSrcCurrency.ToString ()
% uDstCurrency.ToString ());
m_journal.info <<
"Malformed transaction: Redundant transaction:" <<
" src=" << mTxnAccountID.ToString () <<
" dst=" << uDstAccountID.ToString () <<
" src_cur=" << uSrcCurrency.ToString () <<
" dst_cur=" << uDstCurrency.ToString ();
return temREDUNDANT;
}
else if (bMax && saMaxAmount == saDstAmount && saMaxAmount.getCurrency () == saDstAmount.getCurrency ())
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Redundant SendMax.";
m_journal.info <<
"Malformed transaction: Redundant SendMax.";
return temREDUNDANT_SEND_MAX;
}
else if (bXRPDirect && bMax)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: SendMax specified for XRP to XRP.";
m_journal.info <<
"Malformed transaction: SendMax specified for XRP to XRP.";
return temBAD_SEND_XRP_MAX;
}
else if (bXRPDirect && bPaths)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Paths specified for XRP to XRP.";
m_journal.info <<
"Malformed transaction: Paths specified for XRP to XRP.";
return temBAD_SEND_XRP_PATHS;
}
else if (bXRPDirect && bPartialPayment)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Partial payment specified for XRP to XRP.";
m_journal.info <<
"Malformed transaction: Partial payment specified for XRP to XRP.";
return temBAD_SEND_XRP_PARTIAL;
}
else if (bXRPDirect && bLimitQuality)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: Limit quality specified for XRP to XRP.";
m_journal.info <<
"Malformed transaction: Limit quality specified for XRP to XRP.";
return temBAD_SEND_XRP_LIMIT;
}
else if (bXRPDirect && bNoRippleDirect)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: No ripple direct specified for XRP to XRP.";
m_journal.info <<
"Malformed transaction: No ripple direct specified for XRP to XRP.";
return temBAD_SEND_XRP_NO_DIRECT;
}
SLE::pointer sleDst = mEngine->entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
SLE::pointer sleDst (mEngine->entryCache (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
if (!sleDst)
{
@@ -135,36 +148,46 @@ TER PaymentTransactor::doApply ()
if (!saDstAmount.isNative ())
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Delay transaction: Destination account does not exist.";
m_journal.info <<
"Delay transaction: Destination account does not exist.";
// Another transaction could create the account and then this transaction would succeed.
return tecNO_DST;
}
else if (isSetBit (mParams, tapOPEN_LEDGER) && bPartialPayment)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Delay transaction: Partial payment not allowed to create account.";
// Make retry work smaller, by rejecting this.
m_journal.info <<
"Delay transaction: Partial payment not allowed to create account.";
// Another transaction could create the account and then this transaction would succeed.
// Another transaction could create the account and then this
// transaction would succeed.
return telNO_DST_PARTIAL;
}
else if (saDstAmount.getNValue () < mEngine->getLedger ()->getReserve (0)) // Reserve is not scaled by load.
// Note: Reserve is not scaled by load.
else if (saDstAmount.getNValue () < mEngine->getLedger ()->getReserve (0))
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Delay transaction: Destination account does not exist. Insufficent payment to create account.";
m_journal.info <<
"Delay transaction: Destination account does not exist. " <<
"Insufficent payment to create account.";
// Another transaction could create the account and then this transaction would succeed.
// Another transaction could create the account and then this
// transaction would succeed.
return tecNO_DST_INSUF_XRP;
}
// Create the account.
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
sleDst = mEngine->entryCreate (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
sleDst->setFieldAccount (sfAccount, uDstAccountID);
sleDst->setFieldU32 (sfSequence, 1);
}
else if ((sleDst->getFlags () & lsfRequireDestTag) && !mTxn.isFieldPresent (sfDestinationTag))
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Malformed transaction: DestinationTag required.";
m_journal.info <<
"Malformed transaction: DestinationTag required.";
return tefDST_TAG_NEEDED;
}
@@ -173,24 +196,27 @@ TER PaymentTransactor::doApply ()
mEngine->entryModify (sleDst);
}
TER terResult;
TER terResult;
// XXX Should bMax be sufficient to imply ripple?
const bool bRipple = bPaths || bMax || !saDstAmount.isNative ();
bool const bRipple = bPaths || bMax || !saDstAmount.isNative ();
if (bRipple)
{
// Ripple payment
STPathSet spsPaths = mTxn.getFieldPathSet (sfPaths);
STPathSet spsPaths = mTxn.getFieldPathSet (sfPaths);
std::vector<PathState::pointer> vpsExpanded;
STAmount saMaxAmountAct;
STAmount saDstAmountAct;
STAmount saMaxAmountAct;
STAmount saDstAmountAct;
try
{
terResult = isSetBit (mParams, tapOPEN_LEDGER) && spsPaths.size () > RIPPLE_PATHS_MAX
? telBAD_PATH_COUNT // Too many paths for proposed ledger.
: RippleCalc::rippleCalc (
bool const openLedger = isSetBit (mParams, tapOPEN_LEDGER);
bool const tooManyPaths = spsPaths.size () > MaxPathSize;
terResult = openLedger && tooManyPaths
? telBAD_PATH_COUNT // Too many paths for proposed ledger.
: RippleCalc::rippleCalc (
mEngine->getNodes (),
saMaxAmountAct,
saDstAmountAct,
@@ -202,8 +228,8 @@ TER PaymentTransactor::doApply ()
spsPaths,
bPartialPayment,
bLimitQuality,
bNoRippleDirect, // Always compute for finalizing ledger.
false, // Not standalone, delete unfundeds.
bNoRippleDirect, // Always compute for finalizing ledger.
false, // Not standalone, delete unfundeds.
isSetBit (mParams, tapOPEN_LEDGER));
if (isTerRetry(terResult))
@@ -212,9 +238,10 @@ TER PaymentTransactor::doApply ()
if ((tesSUCCESS == terResult) && (saDstAmountAct != saDstAmount))
mEngine->getNodes().setDeliveredAmount (saDstAmountAct);
}
catch (const std::exception& e)
catch (std::exception const& e)
{
WriteLog (lsINFO, PaymentTransactor) << "Payment: Caught throw: " << e.what ();
m_journal.info <<
"Caught throw: " << e.what ();
terResult = tefEXCEPTION;
}
@@ -223,16 +250,17 @@ TER PaymentTransactor::doApply ()
{
// Direct XRP payment.
const std::uint32_t uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
const std::uint64_t uReserve = mEngine->getLedger ()->getReserve (uOwnerCount);
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
std::uint64_t const uReserve (mEngine->getLedger ()->getReserve (uOwnerCount));
// Make sure have enough reserve to send. Allow final spend to use reserve for fee.
if (mPriorBalance < saDstAmount + std::max(uReserve, mTxn.getTransactionFee ().getNValue ()))
{
// Vote no. However, transaction might succeed, if applied in a different order.
WriteLog (lsINFO, PaymentTransactor) << "";
WriteLog (lsINFO, PaymentTransactor) << boost::str (boost::format ("Payment: Delay transaction: Insufficient funds: %s / %s (%d)")
% mPriorBalance.getText () % (saDstAmount + uReserve).getText () % uReserve);
m_journal.info << "Delay transaction: Insufficient funds: " <<
" " << mPriorBalance.getText () <<
" / " << (saDstAmount + uReserve).getText () <<
" (" << uReserve << ")";
terResult = tecUNFUNDED_PAYMENT;
}
@@ -245,7 +273,7 @@ TER PaymentTransactor::doApply ()
if ((sleDst->getFlags () & lsfPasswordSpent))
sleDst->clearFlag (lsfPasswordSpent);
terResult = tesSUCCESS;
terResult = tesSUCCESS;
}
}
@@ -254,7 +282,8 @@ TER PaymentTransactor::doApply ()
if (transResultInfo (terResult, strToken, strHuman))
{
WriteLog (lsINFO, PaymentTransactor) << boost::str (boost::format ("Payment: %s: %s") % strToken % strHuman);
m_journal.info <<
strToken << ": " << strHuman;
}
else
{

View File

@@ -17,15 +17,39 @@
*/
//==============================================================================
#ifndef __PAYMENTTRANSACTOR__
#define __PAYMENTTRANSACTOR__
#ifndef RIPPLE_TX_PAYMENT_H_INCLUDED
#define RIPPLE_TX_PAYMENT_H_INCLUDED
namespace ripple {
class PaymentTransactor : public Transactor
class PaymentTransactorLog;
template <>
char const*
LogPartition::getPartitionName <PaymentTransactorLog> ()
{
return "Tx/Payment";
}
class PaymentTransactor
: public Transactor
{
/* The largest number of paths we allow */
static std::size_t const MaxPathSize = 6;
public:
PaymentTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
PaymentTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <PaymentTransactorLog> ())
{
}
TER doApply ();
};

View File

@@ -19,8 +19,6 @@
namespace ripple {
SETUP_LOG (RegularKeySetTransactor)
std::uint64_t RegularKeySetTransactor::calculateBaseFee ()
{
if ( mTxnAccount
@@ -37,13 +35,12 @@ std::uint64_t RegularKeySetTransactor::calculateBaseFee ()
TER RegularKeySetTransactor::doApply ()
{
Log::out() << "RegularKeySet>";
const std::uint32_t uTxFlags = mTxn.getFlags ();
std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfUniversalMask)
{
WriteLog (lsINFO, RegularKeySetTransactor) << "RegularKeySet: Malformed transaction: Invalid flags set.";
m_journal.info <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
@@ -55,18 +52,16 @@ TER RegularKeySetTransactor::doApply ()
if (mTxn.isFieldPresent (sfRegularKey))
{
uint160 uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
uint160 uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
mTxnAccount->setFieldAccount (sfRegularKey, uAuthKeyID);
}
else
{
if (mTxnAccount->isFlag (lsfDisableMaster))
return tecMASTER_DISABLED;
return tecMASTER_DISABLED;
mTxnAccount->makeFieldAbsent (sfRegularKey);
}
Log::out() << "RegularKeySet<";
return tesSUCCESS;
}

View File

@@ -17,19 +17,39 @@
*/
//==============================================================================
#ifndef REGULARKEYSETTRANSACTOR_H
#define REGULARKEYSETTRANSACTOR_H
#ifndef RIPPLE_TX_REGULARSETKEY_H_INCLUDED
#define RIPPLE_TX_REGULARSETKEY_H_INCLUDED
namespace ripple {
class RegularKeySetTransactor : public Transactor
class RegularKeySetTransactorLog;
template <>
char const*
LogPartition::getPartitionName <RegularKeySetTransactorLog> ()
{
return "Tx/RegularKeySet";
}
class RegularKeySetTransactor
: public Transactor
{
std::uint64_t calculateBaseFee ();
public:
RegularKeySetTransactor (const SerializedTransaction& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (txn, params, engine) {}
RegularKeySetTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <RegularKeySetTransactorLog> ())
{
}
TER checkFee ();
TER doApply ();
};

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef __TRANSACTOR__
#define __TRANSACTOR__
#ifndef RIPPLE_TX_TRANSACTOR_H_INCLUDED
#define RIPPLE_TX_TRANSACTOR_H_INCLUDED
namespace ripple {

View File

@@ -19,110 +19,121 @@
namespace ripple {
SETUP_LOG (TrustSetTransactor)
TER TrustSetTransactor::doApply ()
{
TER terResult = tesSUCCESS;
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet>";
TER terResult = tesSUCCESS;
const STAmount saLimitAmount = mTxn.getFieldAmount (sfLimitAmount);
const bool bQualityIn = mTxn.isFieldPresent (sfQualityIn);
const bool bQualityOut = mTxn.isFieldPresent (sfQualityOut);
const uint160 uCurrencyID = saLimitAmount.getCurrency ();
uint160 uDstAccountID = saLimitAmount.getIssuer ();
const bool bHigh = mTxnAccountID > uDstAccountID; // true, iff current is high account.
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn));
bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut));
uint160 const uCurrencyID (saLimitAmount.getCurrency ());
uint160 uDstAccountID (saLimitAmount.getIssuer ());
std::uint32_t uQualityIn = bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0;
std::uint32_t uQualityOut = bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0;
// true, iff current is high account.
bool const bHigh = mTxnAccountID > uDstAccountID;
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
if (!saLimitAmount.isLegalNet ())
return temBAD_AMOUNT;
if (bQualityIn && QUALITY_ONE == uQualityIn)
uQualityIn = 0;
uQualityIn = 0;
if (bQualityOut && QUALITY_ONE == uQualityOut)
uQualityOut = 0;
const std::uint32_t uTxFlags = mTxn.getFlags ();
std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfTrustSetMask)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Invalid flags set.";
m_journal.info <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
const bool bSetAuth = isSetBit (uTxFlags, tfSetfAuth);
const bool bSetNoRipple = isSetBit (uTxFlags, tfSetNoRipple);
const bool bClearNoRipple = isSetBit (uTxFlags, tfClearNoRipple);
bool const bSetAuth = isSetBit (uTxFlags, tfSetfAuth);
bool const bSetNoRipple = isSetBit (uTxFlags, tfSetNoRipple);
bool const bClearNoRipple = isSetBit (uTxFlags, tfClearNoRipple);
if (bSetAuth && !isSetBit (mTxnAccount->getFieldU32 (sfFlags), lsfRequireAuth))
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Retry: Auth not required.";
m_journal.info <<
"Retry: Auth not required.";
return tefNO_AUTH_REQUIRED;
}
if (saLimitAmount.isNative ())
{
WriteLog (lsINFO, TrustSetTransactor) << boost::str (boost::format ("doTrustSet: Malformed transaction: Native credit limit: %s")
% saLimitAmount.getFullText ());
m_journal.info <<
"Malformed transaction: Native credit limit: " <<
saLimitAmount.getFullText ();
return temBAD_LIMIT;
}
if (saLimitAmount.isNegative ())
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Negative credit limit.";
m_journal.info <<
"Malformed transaction: Negative credit limit.";
return temBAD_LIMIT;
}
// Check if destination makes sense.
if (!uDstAccountID || uDstAccountID == ACCOUNT_ONE)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Destination account not specified.";
m_journal.info <<
"Malformed transaction: Destination account not specified.";
return temDST_NEEDED;
}
if (mTxnAccountID == uDstAccountID)
{
SLE::pointer selDelete = mEngine->entryCache (ltRIPPLE_STATE, Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID));
SLE::pointer selDelete (
mEngine->entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex (
mTxnAccountID, uDstAccountID, uCurrencyID)));
if (selDelete)
{
WriteLog (lsWARNING, TrustSetTransactor) << "doTrustSet: Clearing redundant line.";
m_journal.warning <<
"Clearing redundant line.";
return mEngine->getNodes ().trustDelete (selDelete, mTxnAccountID, uDstAccountID);
return mEngine->getNodes ().trustDelete (
selDelete, mTxnAccountID, uDstAccountID);
}
else
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Can not extend credit to self.";
m_journal.info <<
"Malformed transaction: Can not extend credit to self.";
return temDST_IS_SRC;
}
}
SLE::pointer sleDst = mEngine->entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
SLE::pointer sleDst (mEngine->entryCache (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
if (!sleDst)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Delay transaction: Destination account does not exist.";
m_journal.info <<
"Delay transaction: Destination account does not exist.";
return tecNO_DST;
}
const std::uint32_t uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
// The reserve required to create the line.
const std::uint64_t uReserveCreate = (uOwnerCount < 2) ? 0 : mEngine->getLedger ()->getReserve (uOwnerCount + 1);
std::uint64_t const uReserveCreate =
(uOwnerCount < 2)
? 0
: mEngine->getLedger ()->getReserve (uOwnerCount + 1);
STAmount saLimitAllow = saLimitAmount;
STAmount saLimitAllow = saLimitAmount;
saLimitAllow.setIssuer (mTxnAccountID);
SLE::pointer sleRippleState = mEngine->entryCache (ltRIPPLE_STATE, Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID));
SLE::pointer sleRippleState (mEngine->entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID)));
if (sleRippleState)
{
@@ -219,8 +230,8 @@ TER TrustSetTransactor::doApply ()
uHighQualityOut = bHigh ? 0 : sleRippleState->getFieldU32 (sfHighQualityOut);
}
const std::uint32_t uFlagsIn = sleRippleState->getFieldU32 (sfFlags);
std::uint32_t uFlagsOut = uFlagsIn;
std::uint32_t const uFlagsIn (sleRippleState->getFieldU32 (sfFlags));
std::uint32_t uFlagsOut (uFlagsIn);
if (bSetNoRipple && !bClearNoRipple && (bHigh ? saHighBalance : saLowBalance).isGEZero())
{
@@ -236,20 +247,20 @@ TER TrustSetTransactor::doApply ()
if (QUALITY_ONE == uHighQualityOut) uHighQualityOut = 0;
const bool bLowReserveSet = uLowQualityIn || uLowQualityOut ||
bool const bLowReserveSet = uLowQualityIn || uLowQualityOut ||
isSetBit (uFlagsOut, lsfLowNoRipple) ||
!!saLowLimit || saLowBalance.isPositive ();
const bool bLowReserveClear = !bLowReserveSet;
bool const bLowReserveClear = !bLowReserveSet;
const bool bHighReserveSet = uHighQualityIn || uHighQualityOut ||
bool const bHighReserveSet = uHighQualityIn || uHighQualityOut ||
isSetBit (uFlagsOut, lsfHighNoRipple) ||
!!saHighLimit || saHighBalance.isPositive ();
const bool bHighReserveClear = !bHighReserveSet;
bool const bHighReserveClear = !bHighReserveSet;
const bool bDefault = bLowReserveClear && bHighReserveClear;
bool const bDefault = bLowReserveClear && bHighReserveClear;
const bool bLowReserved = isSetBit (uFlagsIn, lsfLowReserve);
const bool bHighReserved = isSetBit (uFlagsIn, lsfHighReserve);
bool const bLowReserved = isSetBit (uFlagsIn, lsfLowReserve);
bool const bHighReserved = isSetBit (uFlagsIn, lsfHighReserve);
bool bReserveIncrease = false;
@@ -308,16 +319,19 @@ TER TrustSetTransactor::doApply ()
else if (bReserveIncrease
&& mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Delay transaction: Insufficent reserve to add trust line.";
// Another transaction could provide XRP to the account and then this transaction would succeed.
m_journal.info <<
"Delay transaction: Insufficent reserve to add trust line.";
// Another transaction could provide XRP to the account and then
// this transaction would succeed.
terResult = tecINSUF_RESERVE_LINE;
}
else
{
mEngine->entryModify (sleRippleState);
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Modify ripple line";
m_journal.info <<
"Modify ripple line";
}
}
// Line does not exist.
@@ -325,16 +339,17 @@ TER TrustSetTransactor::doApply ()
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Redundant: Setting non-existent ripple line to defaults.";
m_journal.info <<
"Redundant: Setting non-existent ripple line to defaults.";
return tecNO_LINE_REDUNDANT;
}
else if (mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Delay transaction: Line does not exist. Insufficent reserve to create line.";
m_journal.info <<
"Delay transaction: Line does not exist. Insufficent reserve to create line.";
// Another transaction could create the account and then this transaction would succeed.
terResult = tecNO_LINE_INSUF_RESERVE;
terResult = tecNO_LINE_INSUF_RESERVE;
}
else if (CURRENCY_BAD == uCurrencyID)
{
@@ -342,13 +357,16 @@ TER TrustSetTransactor::doApply ()
}
else
{
STAmount saBalance = STAmount (uCurrencyID, ACCOUNT_ONE); // Zero balance in currency.
// Zero balance in currency.
STAmount saBalance (STAmount (uCurrencyID, ACCOUNT_ONE));
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Creating ripple line: "
<< Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID).ToString ();
m_journal.info <<
"doTrustSet: Creating ripple line: " <<
Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID).ToString ();
// Create a new ripple line.
terResult = mEngine->getNodes ().trustCreate (
terResult = mEngine->getNodes ().trustCreate (
bHigh,
mTxnAccountID,
uDstAccountID,
@@ -362,8 +380,6 @@ TER TrustSetTransactor::doApply ()
uQualityOut);
}
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet<";
return terResult;
}

View File

@@ -17,15 +17,35 @@
*/
//==============================================================================
#ifndef TRUSTSETTRANSACTOR_H
#define TRUSTSETTRANSACTOR_H
#ifndef RIPPLE_TX_TRUSTSET_H_INCLUDED
#define RIPPLE_TX_TRUSTSET_H_INCLUDED
namespace ripple {
class TrustSetTransactor : public Transactor
class TrustSetTransactorLog;
template <>
char const*
LogPartition::getPartitionName <TrustSetTransactorLog> ()
{
return "Tx/TrustSet";
}
class TrustSetTransactor
: public Transactor
{
public:
TrustSetTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
TrustSetTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <TrustSetTransactorLog> ())
{
}
TER doApply ();
};

View File

@@ -19,60 +19,67 @@
namespace ripple {
SETUP_LOG (WalletAddTransactor)
TER WalletAddTransactor::doApply ()
{
Log::out() << "WalletAdd>";
Blob const vucPubKey = mTxn.getFieldVL (sfPublicKey);
Blob const vucSignature = mTxn.getFieldVL (sfSignature);
const uint160 uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
const RippleAddress naMasterPubKey = RippleAddress::createAccountPublic (vucPubKey);
const uint160 uDstAccountID = naMasterPubKey.getAccountID ();
const std::uint32_t uTxFlags = mTxn.getFlags ();
std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfUniversalMask)
{
WriteLog (lsINFO, WalletAddTransactor) << "WalletAdd: Malformed transaction: Invalid flags set.";
m_journal.info <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
Blob const vucPubKey = mTxn.getFieldVL (sfPublicKey);
Blob const vucSignature = mTxn.getFieldVL (sfSignature);
uint160 const uAuthKeyID (mTxn.getFieldAccount160 (sfRegularKey));
RippleAddress const naMasterPubKey (
RippleAddress::createAccountPublic (vucPubKey));
uint160 const uDstAccountID (naMasterPubKey.getAccountID ());
// FIXME: This should be moved to the transaction's signature check logic and cached
if (!naMasterPubKey.accountPublicVerify (
Serializer::getSHA512Half (uAuthKeyID.begin (), uAuthKeyID.size ()), vucSignature, ECDSA::not_strict))
Serializer::getSHA512Half (uAuthKeyID.begin (), uAuthKeyID.size ()),
vucSignature, ECDSA::not_strict))
{
Log::out() << "WalletAdd: unauthorized: bad signature ";
m_journal.info <<
"Unauthorized: bad signature ";
return tefBAD_ADD_AUTH;
}
SLE::pointer sleDst = mEngine->entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
SLE::pointer sleDst (mEngine->entryCache (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
if (sleDst)
{
Log::out() << "WalletAdd: account already created";
m_journal.info <<
"account already created";
return tefCREATED;
}
// Direct XRP payment.
STAmount saDstAmount = mTxn.getFieldAmount (sfAmount);
const STAmount saSrcBalance = mTxnAccount->getFieldAmount (sfBalance);
const std::uint32_t uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
const std::uint64_t uReserve = mEngine->getLedger ()->getReserve (uOwnerCount);
STAmount saPaid = mTxn.getTransactionFee ();
STAmount saDstAmount = mTxn.getFieldAmount (sfAmount);
STAmount saPaid = mTxn.getTransactionFee ();
STAmount const saSrcBalance = mTxnAccount->getFieldAmount (sfBalance);
std::uint32_t const uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
std::uint64_t const uReserve = mEngine->getLedger ()->getReserve (uOwnerCount);
// Make sure have enough reserve to send. Allow final spend to use reserve for fee.
if (saSrcBalance + saPaid < saDstAmount + uReserve) // Reserve is not scaled by fee.
// Make sure have enough reserve to send. Allow final spend to use reserve
// for fee.
// Note: Reserve is not scaled by fee.
if (saSrcBalance + saPaid < saDstAmount + uReserve)
{
// Vote no. However, transaction might succeed, if applied in a different order.
WriteLog (lsINFO, WalletAddTransactor) << boost::str (boost::format ("WalletAdd: Delay transaction: Insufficient funds: %s / %s (%d)")
% saSrcBalance.getText () % (saDstAmount + uReserve).getText () % uReserve);
// Vote no. However, transaction might succeed, if applied in a
// different order.
m_journal.info <<
"Delay transaction: Insufficient funds: %s / %s (%d)" <<
saSrcBalance.getText () << " / " <<
(saDstAmount + uReserve).getText () << " with reserve = " <<
uReserve;
return tecUNFUNDED_ADD;
}
@@ -80,15 +87,14 @@ TER WalletAddTransactor::doApply ()
mTxnAccount->setFieldAmount (sfBalance, saSrcBalance - saDstAmount);
// Create the account.
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT,
Ledger::getAccountRootIndex (uDstAccountID));
sleDst->setFieldAccount (sfAccount, uDstAccountID);
sleDst->setFieldU32 (sfSequence, 1);
sleDst->setFieldAmount (sfBalance, saDstAmount);
sleDst->setFieldAccount (sfRegularKey, uAuthKeyID);
Log::out() << "WalletAdd<";
return tesSUCCESS;
}

View File

@@ -17,15 +17,35 @@
*/
//==============================================================================
#ifndef WALLETADDTRANSACTOR_H
#define WALLETADDTRANSACTOR_H
#ifndef RIPPLE_TX_WALLETADD_H_INCLUDED
#define RIPPLE_TX_WALLETADD_H_INCLUDED
namespace ripple {
class WalletAddTransactor : public Transactor
class WalletAddTransactorLog;
template <>
char const*
LogPartition::getPartitionName <WalletAddTransactorLog> ()
{
return "Tx/WalletAdd";
}
class WalletAddTransactor
: public Transactor
{
public:
WalletAddTransactor (const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine) : Transactor (txn, params, engine) {}
WalletAddTransactor (
SerializedTransaction const& txn,
TransactionEngineParams params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
LogPartition::getJournal <WalletAddTransactorLog> ())
{
}
TER doApply ();
};