mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Transactor journal support and small cleanups
This commit is contained in:
committed by
Vinnie Falco
parent
d447a1db39
commit
436061be22
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -129,8 +129,8 @@ public:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Manager::Manager (Stoppable& parent)
|
||||
: Stoppable ("PeerFinder", parent)
|
||||
, beast::PropertyStream::Source ("peerfinder")
|
||||
: Stoppable ("SiteFiles", parent)
|
||||
, beast::PropertyStream::Source ("sitefiles")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 ();
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
};
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef __TRANSACTOR__
|
||||
#define __TRANSACTOR__
|
||||
#ifndef RIPPLE_TX_TRANSACTOR_H_INCLUDED
|
||||
#define RIPPLE_TX_TRANSACTOR_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user