mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-22 19:45:49 +00:00
Refactor View, MetaView, and tx processing:
This tidies up the View interface and makes transaction application a free function, with the removal of the TransactionEngine class. A new class ApplyContext provides all the state information needed to apply a Transactor. The Transactor is refactored to perform all the processing activities previously part of TransactionEngine. The calculation of metadata from a MetaView is improved. A new apply function performs all the steps for calculating and inserting metadata into the tx map. Transaction processing code path is passed a Config instead of retrieving the global, and uses the Journal supplied in the call to apply() consistently. To support transaction processing and RPC operations, a new POD type ViewInfo is added which consolidates static information about open and closed ledgers, such as the ledger sequence number or the closing times. Ledger and MetaView are refactored to use this info. The ViewInfo now contains the "open ledger" setting. The tapOPEN_LEDGER ViewFlag is removed. The view property of being an open ledger is obtained from the base or by using the MetaView constructor which presents a closed ledger as an open one. View, MetaView: * Fix missing includes * Add apply free function * Use Journal in TransactionEngine * Use BasicView in TransactionEngine * inline NetworkOPs::batchApply * Add shallow_copy, open_ledger MetaView ctor tags * Add ViewInfo with open flag, seq, close times * Make parent_ a reference * Tidy up ctor arguments and base_ name * Remove tapOPEN_LEDGER * add assert to MetaView::apply * ViewInfo comment * Throw, pass Journal in txInsert * Add BasicView::txCount TransactionEngine: * Add apply * Make TransactionEngine private * Refactor MetaView::apply and apply() * Rename to TxMeta * Refactor treatment of metadata in MetaView, TransactionEngine * Rename to ApplyContext * Use ApplyContext& in Transactor * Pass Config in ApplyContext * Declare Transactor classes in headers * Use view flags in Transactor
This commit is contained in:
@@ -1409,6 +1409,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\TxMeta.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedger.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedgers.h">
|
||||
@@ -1475,6 +1479,8 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\TxMeta.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\main\Application.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -1719,6 +1725,18 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\apply.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\apply.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\ApplyContext.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\ApplyContext.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -1729,22 +1747,32 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelOffer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CancelTicket.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelTicket.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\Change.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\Change.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateOffer.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateOffer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateTicket.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateTicket.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\InboundTransactions.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -1765,22 +1793,32 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\Payment.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetAccount.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetAccount.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetRegularKey.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetRegularKey.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetSignerList.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetSignerList.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetTrust.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetTrust.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SignerEntries.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -1801,18 +1839,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionEngine.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMaster.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMeta.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\Transactor.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
@@ -1849,12 +1879,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionEngine.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMeta.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\base_uint.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\BasicConfig.h">
|
||||
@@ -1869,6 +1895,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\contract.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\CountedObject.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\DecayingSample.h">
|
||||
|
||||
@@ -2145,6 +2145,9 @@
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\MetaView.cpp">
|
||||
<Filter>ripple\app\ledger\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\ledger\impl\TxMeta.cpp">
|
||||
<Filter>ripple\app\ledger\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedger.h">
|
||||
<Filter>ripple\app\ledger</Filter>
|
||||
</ClInclude>
|
||||
@@ -2217,6 +2220,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h">
|
||||
<Filter>ripple\app\ledger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\ledger\TxMeta.h">
|
||||
<Filter>ripple\app\ledger</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\main\Application.cpp">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClCompile>
|
||||
@@ -2454,6 +2460,18 @@
|
||||
<ClCompile Include="..\..\src\ripple\app\tests\Regression_test.cpp">
|
||||
<Filter>ripple\app\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\apply.h">
|
||||
<Filter>ripple\app\tx</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\apply.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\ApplyContext.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\ApplyContext.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -2463,18 +2481,33 @@
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CancelOffer.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelOffer.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CancelTicket.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelTicket.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\Change.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\Change.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateOffer.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateOffer.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateTicket.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateTicket.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\InboundTransactions.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -2493,18 +2526,33 @@
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\Payment.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\Payment.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetAccount.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetAccount.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetRegularKey.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetRegularKey.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetSignerList.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetSignerList.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetTrust.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetTrust.h">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\SignerEntries.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -2523,15 +2571,9 @@
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionAcquire.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionEngine.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMaster.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMeta.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\app\tx\impl\Transactor.cpp">
|
||||
<Filter>ripple\app\tx\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -2568,15 +2610,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h">
|
||||
<Filter>ripple\app\tx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionEngine.h">
|
||||
<Filter>ripple\app\tx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h">
|
||||
<Filter>ripple\app\tx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMeta.h">
|
||||
<Filter>ripple\app\tx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\base_uint.h">
|
||||
<Filter>ripple\basics</Filter>
|
||||
</ClInclude>
|
||||
@@ -2598,6 +2634,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h">
|
||||
<Filter>ripple\basics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\contract.h">
|
||||
<Filter>ripple\basics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\basics\CountedObject.h">
|
||||
<Filter>ripple\basics</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -36,7 +36,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit)
|
||||
|
||||
mTxn = std::make_shared<STTx> (std::ref (txnIt));
|
||||
mRawMeta = sit.getVL ();
|
||||
mMeta = std::make_shared<TransactionMetaSet> (mTxn->getTransactionID (),
|
||||
mMeta = std::make_shared<TxMeta> (mTxn->getTransactionID (),
|
||||
ledger->getLedgerSeq (), mRawMeta);
|
||||
mAffected = mMeta->getAffectedAccounts ();
|
||||
mResult = mMeta->getResultTER ();
|
||||
@@ -44,7 +44,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit)
|
||||
}
|
||||
|
||||
AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger,
|
||||
STTx::ref txn, TransactionMetaSet::ref met)
|
||||
STTx::ref txn, TxMeta::ref met)
|
||||
: mLedger (ledger)
|
||||
, mTxn (txn)
|
||||
, mMeta (met)
|
||||
|
||||
@@ -53,14 +53,14 @@ public:
|
||||
public:
|
||||
AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit);
|
||||
AcceptedLedgerTx (Ledger::ref ledger, STTx::ref,
|
||||
TransactionMetaSet::ref);
|
||||
TxMeta::ref);
|
||||
AcceptedLedgerTx (Ledger::ref ledger, STTx::ref, TER result);
|
||||
|
||||
STTx::ref getTxn () const
|
||||
{
|
||||
return mTxn;
|
||||
}
|
||||
TransactionMetaSet::ref getMeta () const
|
||||
TxMeta::ref getMeta () const
|
||||
{
|
||||
return mMeta;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
private:
|
||||
Ledger::pointer mLedger;
|
||||
STTx::pointer mTxn;
|
||||
TransactionMetaSet::pointer mMeta;
|
||||
TxMeta::pointer mMeta;
|
||||
TER mResult;
|
||||
boost::container::flat_set<AccountID> mAffected;
|
||||
Blob mRawMeta;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/app/ledger/AcceptedLedger.h>
|
||||
#include <ripple/app/ledger/InboundLedgers.h>
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
@@ -81,9 +82,6 @@ makeGenesisAccount (AccountID const& id,
|
||||
Ledger::Ledger (RippleAddress const& masterPublicKey,
|
||||
std::uint64_t balanceInDrops)
|
||||
: mTotCoins (balanceInDrops)
|
||||
, seq_ (1) // First Ledger
|
||||
, mCloseTime (0)
|
||||
, mParentCloseTime (0)
|
||||
, mCloseResolution (ledgerDefaultTimeResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
@@ -94,13 +92,15 @@ Ledger::Ledger (RippleAddress const& masterPublicKey,
|
||||
// VFALCO Needs audit
|
||||
, fees_(getFees(*this, getConfig()))
|
||||
{
|
||||
// first ledger
|
||||
info_.seq = 1;
|
||||
auto sle = makeGenesisAccount(
|
||||
calcAccountID(masterPublicKey),
|
||||
balanceInDrops);
|
||||
WriteLog (lsTRACE, Ledger)
|
||||
<< "root account: " << sle->getJson(0);
|
||||
unchecked_insert(std::move(sle));
|
||||
stateMap_->flushDirty (hotACCOUNT_NODE, seq_);
|
||||
stateMap_->flushDirty (hotACCOUNT_NODE, info_.seq);
|
||||
}
|
||||
|
||||
Ledger::Ledger (uint256 const& parentHash,
|
||||
@@ -117,9 +117,6 @@ Ledger::Ledger (uint256 const& parentHash,
|
||||
, mTransHash (transHash)
|
||||
, mAccountHash (accountHash)
|
||||
, mTotCoins (totCoins)
|
||||
, seq_ (ledgerSeq)
|
||||
, mCloseTime (closeTime)
|
||||
, mParentCloseTime (parentCloseTime)
|
||||
, mCloseResolution (closeResolution)
|
||||
, mCloseFlags (closeFlags)
|
||||
, mImmutable (true)
|
||||
@@ -131,6 +128,10 @@ Ledger::Ledger (uint256 const& parentHash,
|
||||
// VFALCO Needs audit
|
||||
, fees_(getFees(*this, getConfig()))
|
||||
{
|
||||
info_.seq = ledgerSeq;
|
||||
info_.parentCloseTime = parentCloseTime;
|
||||
info_.closeTime = closeTime;
|
||||
|
||||
updateHash ();
|
||||
loaded = true;
|
||||
|
||||
@@ -157,12 +158,8 @@ Ledger::Ledger (Ledger const& ledger,
|
||||
bool isMutable)
|
||||
: mParentHash (ledger.mParentHash)
|
||||
, mTotCoins (ledger.mTotCoins)
|
||||
, seq_ (ledger.seq_)
|
||||
, mCloseTime (ledger.mCloseTime)
|
||||
, mParentCloseTime (ledger.mParentCloseTime)
|
||||
, mCloseResolution (ledger.mCloseResolution)
|
||||
, mCloseFlags (ledger.mCloseFlags)
|
||||
, mClosed (ledger.mClosed)
|
||||
, mValidated (ledger.mValidated)
|
||||
, mAccepted (ledger.mAccepted)
|
||||
, mImmutable (!isMutable)
|
||||
@@ -170,16 +167,15 @@ Ledger::Ledger (Ledger const& ledger,
|
||||
, stateMap_ (ledger.stateMap_->snapShot (isMutable))
|
||||
// VFALCO Needs audit
|
||||
, fees_(getFees(*this, getConfig()))
|
||||
, info_ (ledger.info_)
|
||||
{
|
||||
updateHash ();
|
||||
}
|
||||
|
||||
// Create a new ledger that follows this one
|
||||
// Create a new open ledger that follows this one
|
||||
Ledger::Ledger (bool /* dummy */,
|
||||
Ledger& prevLedger)
|
||||
: mTotCoins (prevLedger.mTotCoins)
|
||||
, seq_ (prevLedger.seq_ + 1)
|
||||
, mParentCloseTime (prevLedger.mCloseTime)
|
||||
, mCloseResolution (prevLedger.mCloseResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
@@ -189,6 +185,10 @@ Ledger::Ledger (bool /* dummy */,
|
||||
// VFALCO Needs audit
|
||||
, fees_(getFees(*this, getConfig()))
|
||||
{
|
||||
info_.open = true;
|
||||
info_.seq = prevLedger.info_.seq + 1;
|
||||
info_.parentCloseTime =
|
||||
prevLedger.info_.closeTime;
|
||||
prevLedger.updateHash ();
|
||||
|
||||
mParentHash = prevLedger.getHash ();
|
||||
@@ -196,16 +196,17 @@ Ledger::Ledger (bool /* dummy */,
|
||||
assert (mParentHash.isNonZero ());
|
||||
|
||||
mCloseResolution = getNextLedgerTimeResolution (prevLedger.mCloseResolution,
|
||||
prevLedger.getCloseAgree (), seq_);
|
||||
prevLedger.getCloseAgree (), info_.seq);
|
||||
|
||||
if (prevLedger.mCloseTime == 0)
|
||||
if (prevLedger.info_.closeTime == 0)
|
||||
{
|
||||
mCloseTime = roundCloseTime (
|
||||
info_.closeTime = roundCloseTime (
|
||||
getApp().getOPs ().getCloseTimeNC (), mCloseResolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCloseTime = prevLedger.mCloseTime + mCloseResolution;
|
||||
info_.closeTime =
|
||||
prevLedger.info_.closeTime + mCloseResolution;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +221,6 @@ Ledger::Ledger (void const* data,
|
||||
|
||||
Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime)
|
||||
: mTotCoins (0)
|
||||
, seq_ (ledgerSeq)
|
||||
, mCloseTime (closeTime)
|
||||
, mParentCloseTime (0)
|
||||
, mCloseResolution (ledgerDefaultTimeResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
@@ -235,6 +233,9 @@ Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime)
|
||||
// VFALCO Needs audit
|
||||
, fees_(getFees(*this, getConfig()))
|
||||
{
|
||||
info_.seq = ledgerSeq;
|
||||
info_.parentCloseTime = 0;
|
||||
info_.closeTime = closeTime;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -275,13 +276,13 @@ void Ledger::updateHash()
|
||||
// VFALCO This has to match addRaw
|
||||
mHash = sha512Half(
|
||||
HashPrefix::ledgerMaster,
|
||||
std::uint32_t(seq_),
|
||||
std::uint32_t(info_.seq),
|
||||
std::uint64_t(mTotCoins),
|
||||
mParentHash,
|
||||
mTransHash,
|
||||
mAccountHash,
|
||||
std::uint32_t(mParentCloseTime),
|
||||
std::uint32_t(mCloseTime),
|
||||
std::uint32_t(info_.parentCloseTime),
|
||||
std::uint32_t(info_.closeTime),
|
||||
std::uint8_t(mCloseResolution),
|
||||
std::uint8_t(mCloseFlags));
|
||||
mValidHash = true;
|
||||
@@ -292,13 +293,13 @@ void Ledger::setRaw (SerialIter& sit, bool hasPrefix)
|
||||
if (hasPrefix)
|
||||
sit.get32 ();
|
||||
|
||||
seq_ = sit.get32 ();
|
||||
info_.seq = sit.get32 ();
|
||||
mTotCoins = sit.get64 ();
|
||||
mParentHash = sit.get256 ();
|
||||
mTransHash = sit.get256 ();
|
||||
mAccountHash = sit.get256 ();
|
||||
mParentCloseTime = sit.get32 ();
|
||||
mCloseTime = sit.get32 ();
|
||||
info_.parentCloseTime = sit.get32 ();
|
||||
info_.closeTime = sit.get32 ();
|
||||
mCloseResolution = sit.get8 ();
|
||||
mCloseFlags = sit.get8 ();
|
||||
updateHash ();
|
||||
@@ -310,13 +311,13 @@ void Ledger::setRaw (SerialIter& sit, bool hasPrefix)
|
||||
|
||||
void Ledger::addRaw (Serializer& s) const
|
||||
{
|
||||
s.add32 (seq_);
|
||||
s.add32 (info_.seq);
|
||||
s.add64 (mTotCoins);
|
||||
s.add256 (mParentHash);
|
||||
s.add256 (mTransHash);
|
||||
s.add256 (mAccountHash);
|
||||
s.add32 (mParentCloseTime);
|
||||
s.add32 (mCloseTime);
|
||||
s.add32 (info_.parentCloseTime);
|
||||
s.add32 (info_.closeTime);
|
||||
s.add8 (mCloseResolution);
|
||||
s.add8 (mCloseFlags);
|
||||
}
|
||||
@@ -326,8 +327,9 @@ void Ledger::setAccepted (
|
||||
{
|
||||
// Used when we witnessed the consensus. Rounds the close time, updates the
|
||||
// hash, and sets the ledger accepted and immutable.
|
||||
assert (mClosed && !mAccepted);
|
||||
mCloseTime = correctCloseTime ? roundCloseTime (closeTime, closeResolution)
|
||||
assert (closed() && !mAccepted);
|
||||
info_.closeTime = correctCloseTime
|
||||
? roundCloseTime (closeTime, closeResolution)
|
||||
: closeTime;
|
||||
mCloseResolution = closeResolution;
|
||||
mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
|
||||
@@ -338,9 +340,10 @@ void Ledger::setAccepted (
|
||||
void Ledger::setAccepted ()
|
||||
{
|
||||
// used when we acquired the ledger
|
||||
// FIXME assert(mClosed && (mCloseTime != 0) && (mCloseResolution != 0));
|
||||
// FIXME assert(closed() && (info_.closeTime != 0) && (mCloseResolution != 0));
|
||||
if ((mCloseFlags & sLCF_NoConsensusTime) == 0)
|
||||
mCloseTime = roundCloseTime (mCloseTime, mCloseResolution);
|
||||
info_.closeTime = roundCloseTime(
|
||||
info_.closeTime, mCloseResolution);
|
||||
|
||||
mAccepted = true;
|
||||
setImmutable ();
|
||||
@@ -396,7 +399,7 @@ getTransaction (Ledger const& ledger,
|
||||
bool
|
||||
getTransaction (Ledger const& ledger,
|
||||
uint256 const& txID, Transaction::pointer& txn,
|
||||
TransactionMetaSet::pointer& meta,
|
||||
TxMeta::pointer& meta,
|
||||
TransactionMaster& cache)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
@@ -428,7 +431,7 @@ getTransaction (Ledger const& ledger,
|
||||
else
|
||||
it.getVL (); // skip transaction
|
||||
|
||||
meta = std::make_shared<TransactionMetaSet> (
|
||||
meta = std::make_shared<TxMeta> (
|
||||
txID, ledger.seq(), it.getVL ());
|
||||
}
|
||||
else
|
||||
@@ -442,7 +445,7 @@ getTransaction (Ledger const& ledger,
|
||||
}
|
||||
|
||||
bool getTransactionMeta (Ledger const& ledger,
|
||||
uint256 const& txID, TransactionMetaSet::pointer& meta)
|
||||
uint256 const& txID, TxMeta::pointer& meta)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
auto const item =
|
||||
@@ -456,7 +459,7 @@ bool getTransactionMeta (Ledger const& ledger,
|
||||
|
||||
SerialIter it (item->slice());
|
||||
it.getVL (); // skip transaction
|
||||
meta = std::make_shared<TransactionMetaSet> (txID, ledger.seq(), it.getVL ());
|
||||
meta = std::make_shared<TxMeta> (txID, ledger.seq(), it.getVL ());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -506,7 +509,7 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
WriteLog (lsFATAL, Ledger) << "sAL: " << getAccountHash ()
|
||||
<< " != " << stateMap_->getHash ();
|
||||
WriteLog (lsFATAL, Ledger) << "saveAcceptedLedger: seq="
|
||||
<< seq_ << ", current=" << current;
|
||||
<< info_.seq << ", current=" << current;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
@@ -529,7 +532,7 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
catch (...)
|
||||
{
|
||||
WriteLog (lsWARNING, Ledger) << "An accepted ledger was missing nodes";
|
||||
getApp().getLedgerMaster().failedSave(seq_, mHash);
|
||||
getApp().getLedgerMaster().failedSave(info_.seq, mHash);
|
||||
// Clients can now trust the database for information about this
|
||||
// ledger sequence.
|
||||
getApp().pendingSaves().erase(getLedgerSeq());
|
||||
@@ -538,7 +541,7 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
|
||||
{
|
||||
auto db = getApp().getLedgerDB ().checkoutDb();
|
||||
*db << boost::str (deleteLedger % seq_);
|
||||
*db << boost::str (deleteLedger % info_.seq);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -604,7 +607,7 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
}
|
||||
else
|
||||
WriteLog (lsWARNING, Ledger)
|
||||
<< "Transaction in ledger " << seq_
|
||||
<< "Transaction in ledger " << info_.seq
|
||||
<< " affects no accounts";
|
||||
|
||||
*db <<
|
||||
@@ -621,9 +624,9 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
|
||||
// TODO(tom): ARG!
|
||||
*db << boost::str (addLedger %
|
||||
to_string (getHash ()) % seq_ % to_string (mParentHash) %
|
||||
beast::lexicalCastThrow <std::string> (mTotCoins) % mCloseTime %
|
||||
mParentCloseTime % mCloseResolution % mCloseFlags %
|
||||
to_string (getHash ()) % info_.seq % to_string (mParentHash) %
|
||||
beast::lexicalCastThrow <std::string> (mTotCoins) % info_.closeTime %
|
||||
info_.parentCloseTime % mCloseResolution % mCloseFlags %
|
||||
to_string (mAccountHash) % to_string (mTransHash));
|
||||
}
|
||||
|
||||
@@ -875,13 +878,13 @@ bool Ledger::isAcquiringAS (void) const
|
||||
|
||||
boost::posix_time::ptime Ledger::getCloseTime () const
|
||||
{
|
||||
return ptFromSeconds (mCloseTime);
|
||||
return ptFromSeconds (info_.closeTime);
|
||||
}
|
||||
|
||||
void Ledger::setCloseTime (boost::posix_time::ptime ptm)
|
||||
{
|
||||
assert (!mImmutable);
|
||||
mCloseTime = iToSeconds (ptm);
|
||||
info_.closeTime = iToSeconds (ptm);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -969,55 +972,50 @@ Ledger::unchecked_replace(
|
||||
auto const ours = std::move(sle);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Ledger::txCount() const
|
||||
{
|
||||
// Always zero for closed ledgers.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Ledger::txExists (uint256 const& key) const
|
||||
{
|
||||
return txMap().hasItem (key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
Ledger::txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData)
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
Serializer const> const& metaData)
|
||||
{
|
||||
if (metaData)
|
||||
{
|
||||
// low-level - just add to table
|
||||
Serializer s (txn->getDataLength () + metaData->getDataLength () + 16);
|
||||
Serializer s(txn->getDataLength () +
|
||||
metaData->getDataLength () + 16);
|
||||
s.addVL (txn->peekData ());
|
||||
s.addVL (metaData->peekData ());
|
||||
auto item = std::make_shared<
|
||||
SHAMapItem const> (key, std::move(s));
|
||||
|
||||
// VFALCO Should just terminate the app
|
||||
// with a fatal error here.
|
||||
|
||||
if (! txMap().addGiveItem (std::move(item), true, true))
|
||||
{
|
||||
WriteLog (lsFATAL, Ledger)
|
||||
<< "Attempt to add transaction+MD to ledger that already had it";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const temp = std::move(*metaData);
|
||||
if (! txMap().addGiveItem
|
||||
(std::move(item), true, true))
|
||||
LogicError("duplicate_tx: " + to_string(key));
|
||||
}
|
||||
else
|
||||
{
|
||||
// low-level - just add to table
|
||||
auto item = std::make_shared<
|
||||
SHAMapItem const> (key, txn->peekData ());
|
||||
|
||||
if (! txMap().addGiveItem (std::move(item), true, false))
|
||||
{
|
||||
WriteLog (lsWARNING, Ledger)
|
||||
<< "Attempt to add transaction to ledger that already had it";
|
||||
return false;
|
||||
}
|
||||
SHAMapItem const>(key, txn->peekData());
|
||||
if (! txMap().addGiveItem(
|
||||
std::move(item), true, false))
|
||||
LogicError("duplicate_tx: " + to_string(key));
|
||||
}
|
||||
|
||||
// VFALCO TODO We could touch only the txMap
|
||||
touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
@@ -1074,7 +1072,7 @@ void Ledger::visitStateItems (std::function<void (SLE::ref)> function) const
|
||||
if (mHash.isNonZero ())
|
||||
{
|
||||
getApp().getInboundLedgers().acquire(
|
||||
mHash, seq_, InboundLedger::fcGENERIC);
|
||||
mHash, info_.seq, InboundLedger::fcGENERIC);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
@@ -1164,10 +1162,10 @@ bool Ledger::assertSane ()
|
||||
// VFALCO TODO Document this skip list concept
|
||||
void Ledger::updateSkipList ()
|
||||
{
|
||||
if (seq_ == 0) // genesis ledger has no previous ledger
|
||||
if (info_.seq == 0) // genesis ledger has no previous ledger
|
||||
return;
|
||||
|
||||
std::uint32_t prevIndex = seq_ - 1;
|
||||
std::uint32_t prevIndex = info_.seq - 1;
|
||||
|
||||
// update record of every 256th ledger
|
||||
if ((prevIndex & 0xff) == 0)
|
||||
@@ -1287,6 +1285,7 @@ qualityDirDescriber (
|
||||
sle->setFieldU64 (sfExchangeRate, uRate);
|
||||
if (isNew)
|
||||
{
|
||||
// VFALCO NO! This shouldn't be done here!
|
||||
getApp().getOrderBookDB().addOrderBook(
|
||||
{{uTakerPaysCurrency, uTakerPaysIssuer},
|
||||
{uTakerGetsCurrency, uTakerGetsIssuer}});
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
#ifndef RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
|
||||
#define RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
|
||||
|
||||
#include <ripple/shamap/SHAMap.h>
|
||||
#include <ripple/app/tx/Transaction.h>
|
||||
#include <ripple/app/tx/TransactionMeta.h>
|
||||
#include <ripple/app/ledger/TxMeta.h>
|
||||
#include <ripple/ledger/SLECache.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/app/tx/Transaction.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
#include <ripple/protocol/Book.h>
|
||||
#include <ripple/shamap/SHAMap.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <mutex>
|
||||
@@ -118,24 +118,18 @@ public:
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ViewInfo const&
|
||||
info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
Fees const&
|
||||
fees() const override
|
||||
{
|
||||
return fees_;
|
||||
}
|
||||
|
||||
LedgerIndex
|
||||
seq() const override
|
||||
{
|
||||
return seq_;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
time() const override
|
||||
{
|
||||
return mParentCloseTime;
|
||||
}
|
||||
|
||||
bool
|
||||
exists (Keylet const& k) const override;
|
||||
|
||||
@@ -161,10 +155,13 @@ public:
|
||||
mTotCoins -= feeDrops;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
txCount() const override;
|
||||
|
||||
bool
|
||||
txExists (uint256 const& key) const override;
|
||||
|
||||
bool
|
||||
void
|
||||
txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
@@ -187,9 +184,9 @@ public:
|
||||
mValidHash = false;
|
||||
}
|
||||
|
||||
void setClosed ()
|
||||
void setClosed()
|
||||
{
|
||||
mClosed = true;
|
||||
info_.open = false;
|
||||
}
|
||||
|
||||
void setValidated()
|
||||
@@ -204,10 +201,10 @@ public:
|
||||
|
||||
void setImmutable ();
|
||||
|
||||
// VFALCO Rename to closed
|
||||
// DEPRECATED use closed()
|
||||
bool isClosed () const
|
||||
{
|
||||
return mClosed;
|
||||
return closed();
|
||||
}
|
||||
|
||||
bool isAccepted () const
|
||||
@@ -225,10 +222,13 @@ public:
|
||||
return mImmutable;
|
||||
}
|
||||
|
||||
// Indicates that all ledger entries
|
||||
// are available locally. For example,
|
||||
// all in the NodeStore and memory.
|
||||
void setFull ()
|
||||
{
|
||||
txMap_->setLedgerSeq (seq_);
|
||||
stateMap_->setLedgerSeq (seq_);
|
||||
txMap_->setLedgerSeq (info_.seq);
|
||||
stateMap_->setLedgerSeq (info_.seq);
|
||||
}
|
||||
|
||||
// ledger signature operations
|
||||
@@ -266,20 +266,22 @@ public:
|
||||
mTotCoins = totCoins;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
std::uint32_t getCloseTimeNC () const
|
||||
{
|
||||
return mCloseTime;
|
||||
return info_.closeTime;
|
||||
}
|
||||
|
||||
// DEPRECATED Use parentCloseTime()
|
||||
std::uint32_t getParentCloseTimeNC () const
|
||||
{
|
||||
return mParentCloseTime;
|
||||
return info_.parentCloseTime;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// DEPRECATED Use seq()
|
||||
std::uint32_t getLedgerSeq () const
|
||||
{
|
||||
return seq_;
|
||||
return info_.seq;
|
||||
}
|
||||
|
||||
int getCloseResolution () const
|
||||
@@ -293,10 +295,10 @@ public:
|
||||
}
|
||||
|
||||
// close time functions
|
||||
void setCloseTime (std::uint32_t ct)
|
||||
void setCloseTime (std::uint32_t when)
|
||||
{
|
||||
assert (!mImmutable);
|
||||
mCloseTime = ct;
|
||||
info_.closeTime = when;
|
||||
}
|
||||
|
||||
void setCloseTime (boost::posix_time::ptime);
|
||||
@@ -383,6 +385,7 @@ public:
|
||||
return mBaseFee;
|
||||
}
|
||||
|
||||
// DEPRECATED use fees()
|
||||
std::uint64_t getReserve (int increments) const
|
||||
{
|
||||
// Returns the required reserve in drops
|
||||
@@ -391,6 +394,7 @@ public:
|
||||
+ mReserveBase;
|
||||
}
|
||||
|
||||
// DEPRECATED use fees()
|
||||
std::uint64_t getReserveInc () const
|
||||
{
|
||||
deprecatedUpdateCachedFees ();
|
||||
@@ -444,20 +448,12 @@ private:
|
||||
uint256 mTransHash;
|
||||
uint256 mAccountHash;
|
||||
std::uint64_t mTotCoins;
|
||||
std::uint32_t seq_;
|
||||
|
||||
// when this ledger closed
|
||||
std::uint32_t mCloseTime;
|
||||
|
||||
// when the previous ledger closed
|
||||
std::uint32_t mParentCloseTime;
|
||||
|
||||
// the resolution for this ledger close time (2-120 seconds)
|
||||
int mCloseResolution;
|
||||
|
||||
// flags indicating how this ledger close took place
|
||||
std::uint32_t mCloseFlags;
|
||||
bool mClosed = false;
|
||||
bool mValidated = false;
|
||||
bool mValidHash = false;
|
||||
bool mAccepted = false;
|
||||
@@ -470,6 +466,7 @@ private:
|
||||
std::mutex mutable mutex_;
|
||||
|
||||
Fees fees_;
|
||||
ViewInfo info_;
|
||||
|
||||
// Ripple cost of the reference transaction
|
||||
std::uint64_t mutable mBaseFee = 0;
|
||||
@@ -561,13 +558,13 @@ getTransaction (Ledger const& ledger,
|
||||
bool
|
||||
getTransaction (Ledger const& ledger,
|
||||
uint256 const& transID, Transaction::pointer & txn,
|
||||
TransactionMetaSet::pointer & txMeta,
|
||||
TxMeta::pointer & txMeta,
|
||||
TransactionMaster& cache);
|
||||
|
||||
bool
|
||||
getTransactionMeta (Ledger const&,
|
||||
uint256 const& transID,
|
||||
TransactionMetaSet::pointer & txMeta);
|
||||
TxMeta::pointer & txMeta);
|
||||
|
||||
// VFALCO NOTE This is called from only one place
|
||||
bool
|
||||
|
||||
@@ -80,10 +80,9 @@ public:
|
||||
*/
|
||||
void applyTransactions (
|
||||
SHAMap const* set,
|
||||
Ledger::ref applyLedger,
|
||||
BasicView& applyView,
|
||||
Ledger::ref checkLedger,
|
||||
CanonicalTXSet& retriableTransactions,
|
||||
bool openLgr,
|
||||
bool enableTesting = false);
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -133,7 +133,7 @@ static
|
||||
void
|
||||
log_one(Ledger::pointer ledger, uint256 const& tx, char const* msg)
|
||||
{
|
||||
TransactionMetaSet::pointer metaData;
|
||||
TxMeta::pointer metaData;
|
||||
getTransactionMeta(*ledger, tx, metaData);
|
||||
|
||||
if (metaData != nullptr)
|
||||
@@ -154,9 +154,9 @@ void
|
||||
log_metadata_difference(Ledger::pointer builtLedger, Ledger::pointer validLedger,
|
||||
uint256 const& tx)
|
||||
{
|
||||
TransactionMetaSet::pointer validMetaData;
|
||||
TxMeta::pointer validMetaData;
|
||||
getTransactionMeta(*validLedger, tx, validMetaData);
|
||||
TransactionMetaSet::pointer builtMetaData;
|
||||
TxMeta::pointer builtMetaData;
|
||||
getTransactionMeta(*builtLedger, tx, builtMetaData);
|
||||
assert(validMetaData != nullptr || builtMetaData != nullptr);
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ void fillJson (Object& json, LedgerFill const& fill)
|
||||
SerialIter tsit (make_Slice(vl));
|
||||
STTx txn (tsit);
|
||||
|
||||
TransactionMetaSet meta (
|
||||
TxMeta meta (
|
||||
item->getTag (), ledger.getLedgerSeq(), sit.getVL ());
|
||||
|
||||
auto&& txJson = appendObject (txns);
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
#ifndef RIPPLE_LEDGER_METAVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_METAVIEW_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/TransactionMeta.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/app/ledger/TxMeta.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/basics/UnorderedContainers.h>
|
||||
#include <ripple/protocol/Keylet.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <list>
|
||||
@@ -35,6 +36,25 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Shallow-copy construction tag.
|
||||
|
||||
When a MetaView is shallow-copied, the SLEs and
|
||||
Serializers are shared between instances. It is
|
||||
only safe to use BasicView interfaces, using
|
||||
View members results in undefined behavior.
|
||||
*/
|
||||
struct shallow_copy_t {};
|
||||
extern shallow_copy_t const shallow_copy;
|
||||
|
||||
/** Open ledger construction tag.
|
||||
|
||||
Views constructed with this tag will have the
|
||||
rules of open ledgers applied during transaction
|
||||
processing.
|
||||
*/
|
||||
struct open_ledger_t {};
|
||||
extern open_ledger_t const open_ledger;
|
||||
|
||||
/** A MetaView can produce tx metadata and is attached to a parent.
|
||||
|
||||
It's a view into a ledger used while a transaction is processing.
|
||||
@@ -70,122 +90,88 @@ private:
|
||||
|
||||
// Note that this class needs to be
|
||||
// somewhat light-weight copy constructible.
|
||||
BasicView const* parent_;
|
||||
BasicView const& base_;
|
||||
ViewFlags flags_ = tapNONE;
|
||||
LedgerIndex seq_;
|
||||
std::uint32_t time_; // should be Clock::time_point
|
||||
ViewInfo info_;
|
||||
tx_list txs_;
|
||||
item_list items_;
|
||||
TransactionMetaSet meta_;
|
||||
std::uint32_t destroyedCoins_ = 0;
|
||||
boost::optional<STAmount> deliverAmount_;
|
||||
|
||||
public:
|
||||
MetaView() = delete;
|
||||
MetaView(MetaView const&) = delete;
|
||||
MetaView& operator= (MetaView const&) = delete;
|
||||
|
||||
/** Create a shallow copy of a MetaView.
|
||||
|
||||
The SLEs and Serializers in the created copy
|
||||
Effects:
|
||||
Duplicates the information in the
|
||||
passed MetaView.
|
||||
|
||||
The SLEs and Serializers in the copy
|
||||
are shared with the other view.
|
||||
The copy has the same Info values.
|
||||
|
||||
It is only safe to use the BasicView modification
|
||||
functions. Using View modification functions will
|
||||
break invariants.
|
||||
|
||||
The seq, time, and flags are copied from `other`.
|
||||
|
||||
@note This is used to apply new transactions to
|
||||
the open MetaView.
|
||||
*/
|
||||
// VFALCO Refactor to disallow at compile time,
|
||||
// breaking invariants on a shallow copy.
|
||||
//
|
||||
MetaView (MetaView const& other) = default;
|
||||
MetaView (shallow_copy_t,
|
||||
MetaView const& other);
|
||||
|
||||
/** Create a MetaView with a BasicView as its parent.
|
||||
/** Create a MetaView representing an open ledger.
|
||||
|
||||
Preconditions:
|
||||
|
||||
`prev` cannot represent an open ledger.
|
||||
|
||||
Effects:
|
||||
The sequence number and time are set
|
||||
from the passed parameters.
|
||||
|
||||
The sequence number is set to the
|
||||
sequence number of parent plus one.
|
||||
|
||||
The parentCloseTime is set to the
|
||||
closeTime of parent.
|
||||
|
||||
It is only safe to use the BasicView modification
|
||||
functions. Using View modification functions will
|
||||
break invariants.
|
||||
|
||||
@note This is for converting a closed ledger
|
||||
into an open ledger.
|
||||
|
||||
@note A pointer is used to prevent confusion
|
||||
with copy construction.
|
||||
@param parent A view representing the previous
|
||||
ledger that this open ledger follows.
|
||||
*/
|
||||
// VFALCO Refactor to disallow at compile time,
|
||||
// breaking invariants on a shallow copy.
|
||||
//
|
||||
MetaView (BasicView const* parent,
|
||||
LedgerIndex seq, std::uint32_t time,
|
||||
MetaView (open_ledger_t,
|
||||
BasicView const& parent);
|
||||
|
||||
/** Create a nested MetaView.
|
||||
|
||||
Effects:
|
||||
|
||||
The ViewInfo is copied from the base.
|
||||
*/
|
||||
MetaView (BasicView const& base,
|
||||
ViewFlags flags);
|
||||
|
||||
/** Create a MetaView with a BasicView as its parent.
|
||||
|
||||
Effects:
|
||||
The sequence number and time are inherited
|
||||
from the parent.
|
||||
|
||||
The MetaSet is prepared to produce metadata
|
||||
for a transaction with the specified key.
|
||||
|
||||
@note This is for applying a particular transaction
|
||||
and computing its metadata, or for applying
|
||||
a transaction without extracting metadata. For
|
||||
example, to calculate changes in a sandbox
|
||||
and then throw the sandbox away.
|
||||
|
||||
@note A pointer is used to prevent confusion
|
||||
with copy construction.
|
||||
*/
|
||||
MetaView (BasicView const* parent,
|
||||
ViewFlags flags,
|
||||
boost::optional<uint256
|
||||
> const& key = boost::none);
|
||||
|
||||
/** Create a MetaView with a View as its parent.
|
||||
|
||||
Effects:
|
||||
The sequence number, time, and flags
|
||||
are inherited from the parent.
|
||||
|
||||
@note This is for stacking view for the purpose of
|
||||
performing calculations or applying to an
|
||||
underlying MetaView associated with a particular
|
||||
transation.
|
||||
|
||||
@note A pointer is used to prevent confusion
|
||||
with copy construction.
|
||||
*/
|
||||
MetaView (View const* parent);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// BasicView
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ViewInfo const&
|
||||
info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
Fees const&
|
||||
fees() const override
|
||||
{
|
||||
return parent_->fees();
|
||||
}
|
||||
|
||||
LedgerIndex
|
||||
seq() const override
|
||||
{
|
||||
return seq_;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
time() const override
|
||||
{
|
||||
return time_;
|
||||
return base_.fees();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -213,10 +199,13 @@ public:
|
||||
void
|
||||
destroyCoins (std::uint64_t feeDrops) override;
|
||||
|
||||
std::size_t
|
||||
txCount() const override;
|
||||
|
||||
bool
|
||||
txExists (uint256 const& key) const override;
|
||||
|
||||
bool
|
||||
void
|
||||
txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
@@ -251,44 +240,77 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Apply changes to the parent View.
|
||||
/** Apply changes to the base View.
|
||||
|
||||
`to` must contain contents identical to the parent
|
||||
view passed upon construction, else undefined
|
||||
behavior will result.
|
||||
`to` must contain contents identical to the
|
||||
parent view passed upon construction, else
|
||||
undefined behavior will result.
|
||||
|
||||
After a call to apply(), the only valid operation that
|
||||
may be performed on this is a call to the destructor.
|
||||
After a call to apply(), the only valid operation
|
||||
on the object is a call to the destructor.
|
||||
*/
|
||||
void
|
||||
apply (BasicView& to);
|
||||
apply (BasicView& to,
|
||||
beast::Journal j = {});
|
||||
|
||||
/** Apply the results of a transaction to the base view.
|
||||
|
||||
`to` must contain contents identical to the
|
||||
parent view passed upon construction, else
|
||||
undefined behavior will result.
|
||||
|
||||
After a call to apply(), the only valid operation
|
||||
on the object is a call to the destructor.
|
||||
|
||||
Effects:
|
||||
|
||||
The transaction is inserted to the tx map.
|
||||
|
||||
If the base view represents a closed ledger,
|
||||
the transaction metadata is computed and
|
||||
inserted with the transaction.
|
||||
|
||||
The metadata is computed by recording the
|
||||
differences between the base view and the
|
||||
modifications in this view.
|
||||
|
||||
@param view The view to apply to.
|
||||
@param tx The transaction that was processed.
|
||||
@param ter The result of applying the transaction.
|
||||
@param j Where to log.
|
||||
*/
|
||||
void
|
||||
apply (BasicView& to, STTx const& tx,
|
||||
TER result, beast::Journal j);
|
||||
|
||||
// For diagnostics
|
||||
Json::Value getJson (int) const;
|
||||
|
||||
void calcRawMeta (Serializer&, TER result, std::uint32_t index);
|
||||
|
||||
void setDeliveredAmount (STAmount const& amt)
|
||||
{
|
||||
meta_.setDeliveredAmount (amt);
|
||||
deliverAmount_ = amt;
|
||||
}
|
||||
|
||||
private:
|
||||
static
|
||||
bool
|
||||
threadTx (TxMeta& meta,
|
||||
std::shared_ptr<SLE> const& to,
|
||||
Mods& mods);
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
getForMod (uint256 const& key,
|
||||
Mods& mods);
|
||||
Mods& mods, beast::Journal j);
|
||||
|
||||
bool
|
||||
threadTx (AccountID const& to,
|
||||
Mods& mods);
|
||||
threadTx (TxMeta& meta,
|
||||
AccountID const& to, Mods& mods,
|
||||
beast::Journal j);
|
||||
|
||||
bool
|
||||
threadTx (std::shared_ptr<SLE> const& to,
|
||||
Mods& mods);
|
||||
|
||||
bool
|
||||
threadOwners (std::shared_ptr<
|
||||
SLE const> const& sle, Mods& mods);
|
||||
threadOwners (TxMeta& meta, std::shared_ptr<
|
||||
SLE const> const& sle, Mods& mods,
|
||||
beast::Journal j);
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -28,26 +28,27 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class TransactionMetaSet
|
||||
// VFALCO Move to ripple/app/ledger/detail, rename to TxMeta
|
||||
class TxMeta
|
||||
{
|
||||
public:
|
||||
using pointer = std::shared_ptr<TransactionMetaSet>;
|
||||
using pointer = std::shared_ptr<TxMeta>;
|
||||
using ref = const pointer&;
|
||||
|
||||
private:
|
||||
struct CtorHelper{};
|
||||
template<class T>
|
||||
TransactionMetaSet (uint256 const& txID, std::uint32_t ledger, T const& data,
|
||||
TxMeta (uint256 const& txID, std::uint32_t ledger, T const& data,
|
||||
CtorHelper);
|
||||
public:
|
||||
TransactionMetaSet ()
|
||||
TxMeta ()
|
||||
: mLedger (0)
|
||||
, mIndex (static_cast<std::uint32_t> (-1))
|
||||
, mResult (255)
|
||||
{
|
||||
}
|
||||
|
||||
TransactionMetaSet (uint256 const& txID, std::uint32_t ledger, std::uint32_t index)
|
||||
TxMeta (uint256 const& txID, std::uint32_t ledger, std::uint32_t index)
|
||||
: mTransactionID (txID)
|
||||
, mLedger (ledger)
|
||||
, mIndex (static_cast<std::uint32_t> (-1))
|
||||
@@ -55,15 +56,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
TransactionMetaSet (uint256 const& txID, std::uint32_t ledger, Blob const&);
|
||||
TransactionMetaSet (uint256 const& txID, std::uint32_t ledger, std::string const&);
|
||||
TxMeta (uint256 const& txID, std::uint32_t ledger, Blob const&);
|
||||
TxMeta (uint256 const& txID, std::uint32_t ledger, std::string const&);
|
||||
|
||||
void init (uint256 const& transactionID, std::uint32_t ledger);
|
||||
void clear ()
|
||||
{
|
||||
mNodes.clear ();
|
||||
}
|
||||
void swap (TransactionMetaSet&) noexcept;
|
||||
void swap (TxMeta&) noexcept;
|
||||
|
||||
uint256 const& getTxID ()
|
||||
{
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/ledger/LedgerTiming.h>
|
||||
#include <ripple/app/ledger/LedgerToJson.h>
|
||||
#include <ripple/app/ledger/MetaView.h>
|
||||
#include <ripple/app/ledger/impl/DisputedTx.h>
|
||||
#include <ripple/app/ledger/impl/LedgerConsensusImp.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
@@ -31,7 +32,7 @@
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/misc/Validations.h>
|
||||
#include <ripple/app/tx/TransactionAcquire.h>
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
@@ -979,15 +980,27 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
|
||||
// Build the new last closed ledger
|
||||
auto newLCL = std::make_shared<Ledger> (false, *mPreviousLedger);
|
||||
newLCL->setClosed (); // so applyTransactions sees a closed ledger
|
||||
|
||||
// Set up to write SHAMap changes to our database,
|
||||
// perform updates, extract changes
|
||||
WriteLog (lsDEBUG, LedgerConsensus)
|
||||
<< "Applying consensus set transactions to the"
|
||||
<< " last closed ledger";
|
||||
applyTransactions (set.get(), newLCL, newLCL, retriableTransactions, false);
|
||||
{
|
||||
MetaView accum(*newLCL, tapNONE);
|
||||
assert(accum.closed());
|
||||
applyTransactions (set.get(), accum,
|
||||
newLCL, retriableTransactions);
|
||||
accum.apply(*newLCL,
|
||||
deprecatedLogs().journal("LedgerConsensus"));
|
||||
}
|
||||
|
||||
// retriableTransactions will include any transactions that
|
||||
// made it into the consensus set but failed during application
|
||||
// to the ledger.
|
||||
|
||||
newLCL->updateSkipList ();
|
||||
newLCL->setClosed ();
|
||||
|
||||
int asf = newLCL->stateMap().flushDirty (
|
||||
hotACCOUNT_NODE, newLCL->getLedgerSeq());
|
||||
@@ -1057,8 +1070,20 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
|
||||
// Build new open ledger
|
||||
auto newOL = std::make_shared<Ledger> (true, *newLCL);
|
||||
MetaView accum(*newOL, tapNONE);
|
||||
assert(accum.open());
|
||||
|
||||
// Apply disputed transactions that didn't get in
|
||||
//
|
||||
// The first crack of transactions to get into the new
|
||||
// open ledger goes to transactions proposed by a validator
|
||||
// we trust but not included in the consensus set.
|
||||
//
|
||||
// These are done first because they are the most likely
|
||||
// to receive agreement during consensus. They are also
|
||||
// ordered logically "sooner" than transactions not mentioned
|
||||
// in the previous consensus round.
|
||||
//
|
||||
bool anyDisputes = false;
|
||||
for (auto& it : mDisputes)
|
||||
{
|
||||
@@ -1075,6 +1100,7 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
auto txn = std::make_shared<STTx>(sit);
|
||||
|
||||
retriableTransactions.push_back (txn);
|
||||
|
||||
anyDisputes = true;
|
||||
}
|
||||
catch (...)
|
||||
@@ -1087,7 +1113,8 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
|
||||
if (anyDisputes)
|
||||
{
|
||||
applyTransactions (nullptr, newOL, newLCL, retriableTransactions, true);
|
||||
applyTransactions (nullptr,
|
||||
accum, newLCL, retriableTransactions);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1102,17 +1129,16 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
WriteLog (lsDEBUG, LedgerConsensus)
|
||||
<< "Applying transactions from current open ledger";
|
||||
applyTransactions (&oldOL->txMap(),
|
||||
newOL, newLCL, retriableTransactions, true);
|
||||
accum, newLCL, retriableTransactions);
|
||||
}
|
||||
|
||||
// Apply local transactions
|
||||
TransactionEngine engine (newOL);
|
||||
|
||||
for (auto it : m_localTX.getTxSet ())
|
||||
{
|
||||
try
|
||||
{
|
||||
engine.applyTransaction (*it.second, tapOPEN_LEDGER);
|
||||
apply (accum, *it.second, tapNONE, getConfig(),
|
||||
deprecatedLogs().journal("LedgerConsensus"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -1123,6 +1149,9 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
}
|
||||
}
|
||||
|
||||
accum.apply(*newOL,
|
||||
deprecatedLogs().journal("LedgerConsensus"));
|
||||
|
||||
// We have a new Last Closed Ledger and new Open Ledger
|
||||
ledgerMaster_.pushLedger (newLCL, newOL);
|
||||
}
|
||||
@@ -1715,20 +1744,18 @@ make_LedgerConsensus (ConsensusImp& consensus, int previousProposers,
|
||||
|
||||
@param engine The transaction engine containing the ledger.
|
||||
@param txn The transaction to be applied to ledger.
|
||||
@param openLedger true if ledger is open
|
||||
@param retryAssured true if the transaction should be retried on failure.
|
||||
@return One of resultSuccess, resultFail or resultRetry.
|
||||
*/
|
||||
static
|
||||
int applyTransaction (
|
||||
TransactionEngine& engine,
|
||||
std::shared_ptr<STTx const> const& txn,
|
||||
bool openLedger,
|
||||
int
|
||||
applyTransaction (BasicView& view,
|
||||
STTx const& txn,
|
||||
bool retryAssured,
|
||||
bool enableTesting)
|
||||
{
|
||||
// Returns false if the transaction has need not be retried.
|
||||
ViewFlags parms = openLedger ? tapOPEN_LEDGER : tapNONE;
|
||||
ViewFlags parms = tapNONE;
|
||||
|
||||
if (enableTesting)
|
||||
parms = parms | tapENABLE_TESTING;
|
||||
@@ -1738,21 +1765,22 @@ int applyTransaction (
|
||||
parms = static_cast<ViewFlags> (parms | tapRETRY);
|
||||
}
|
||||
|
||||
if ((getApp().getHashRouter ().getFlags (txn->getTransactionID ())
|
||||
if ((getApp().getHashRouter ().getFlags (txn.getTransactionID ())
|
||||
& SF_SIGGOOD) == SF_SIGGOOD)
|
||||
{
|
||||
parms = static_cast<ViewFlags>
|
||||
(parms | tapNO_CHECK_SIGN);
|
||||
}
|
||||
WriteLog (lsDEBUG, LedgerConsensus) << "TXN "
|
||||
<< txn->getTransactionID ()
|
||||
<< (openLedger ? " open" : " closed")
|
||||
<< txn.getTransactionID ()
|
||||
//<< (engine.view().open() ? " open" : " closed") // because of the optional in engine
|
||||
<< (retryAssured ? "/retry" : "/final");
|
||||
WriteLog (lsTRACE, LedgerConsensus) << txn->getJson (0);
|
||||
WriteLog (lsTRACE, LedgerConsensus) << txn.getJson (0);
|
||||
|
||||
try
|
||||
{
|
||||
auto result = engine.applyTransaction (*txn, parms);
|
||||
auto const result = apply(view, txn, parms, getConfig(),
|
||||
deprecatedLogs().journal("LedgerConsensus"));
|
||||
|
||||
if (result.second)
|
||||
{
|
||||
@@ -1783,14 +1811,11 @@ int applyTransaction (
|
||||
|
||||
void applyTransactions (
|
||||
SHAMap const* set,
|
||||
Ledger::ref applyLedger,
|
||||
BasicView& applyView,
|
||||
Ledger::ref checkLedger,
|
||||
CanonicalTXSet& retriableTransactions,
|
||||
bool openLgr,
|
||||
bool enableTesting)
|
||||
{
|
||||
TransactionEngine engine (applyLedger);
|
||||
|
||||
if (set)
|
||||
{
|
||||
for (auto const item : *set)
|
||||
@@ -1805,9 +1830,11 @@ void applyTransactions (
|
||||
try
|
||||
{
|
||||
SerialIter sit (item->slice());
|
||||
auto txn = std::make_shared<STTx>(sit);
|
||||
auto const txn =
|
||||
std::make_shared<STTx const>(sit);
|
||||
|
||||
if (applyTransaction (engine, txn, openLgr, true, enableTesting) == LedgerConsensusImp::resultRetry)
|
||||
if (applyTransaction(applyView, *txn, true, enableTesting) ==
|
||||
LedgerConsensusImp::resultRetry)
|
||||
{
|
||||
// On failure, stash the failed transaction for
|
||||
// later retry.
|
||||
@@ -1836,8 +1863,8 @@ void applyTransactions (
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (applyTransaction (engine, it->second,
|
||||
openLgr, certainRetry, enableTesting))
|
||||
switch (applyTransaction (applyView,
|
||||
*it->second, certainRetry, enableTesting))
|
||||
{
|
||||
case LedgerConsensusImp::resultSuccess:
|
||||
it = retriableTransactions.erase (it);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <ripple/app/ledger/OrderBookDB.h>
|
||||
#include <ripple/app/ledger/PendingSaves.h>
|
||||
#include <ripple/app/ledger/impl/LedgerCleaner.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/IHashRouter.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
@@ -31,7 +32,6 @@
|
||||
#include <ripple/app/misc/SHAMapStore.h>
|
||||
#include <ripple/app/misc/Validations.h>
|
||||
#include <ripple/app/paths/PathRequests.h>
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/RangeSet.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
@@ -352,20 +352,20 @@ public:
|
||||
// Start with a mutable snapshot of the open ledger
|
||||
auto const ledger =
|
||||
mCurrentLedger.getMutable();
|
||||
TransactionEngine engine (ledger);
|
||||
|
||||
int recovers = 0;
|
||||
|
||||
for (auto const& it : mHeldTransactions)
|
||||
{
|
||||
try
|
||||
{
|
||||
ViewFlags tepFlags = tapOPEN_LEDGER;
|
||||
ViewFlags tepFlags = tapNONE;
|
||||
|
||||
if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD))
|
||||
tepFlags = static_cast<ViewFlags> (tepFlags | tapNO_CHECK_SIGN);
|
||||
|
||||
auto ret = engine.applyTransaction (*it.second, tepFlags);
|
||||
auto const ret = apply(
|
||||
*ledger, *it.second, tepFlags, getConfig(),
|
||||
deprecatedLogs().journal("LedgerMaster"));
|
||||
|
||||
if (ret.second)
|
||||
++recovers;
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/ledger/MetaView.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/ledger/CachedView.h>
|
||||
#include <ripple/app/ledger/MetaView.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
@@ -42,34 +43,39 @@ namespace ripple {
|
||||
#define DIR_NODE_MAX 32
|
||||
#endif
|
||||
|
||||
MetaView::MetaView (BasicView const* parent,
|
||||
LedgerIndex seq, std::uint32_t time,
|
||||
shallow_copy_t const shallow_copy {};
|
||||
open_ledger_t const open_ledger {};
|
||||
|
||||
MetaView::MetaView (shallow_copy_t,
|
||||
MetaView const& other)
|
||||
: base_ (other.base_)
|
||||
, flags_ (other.flags_)
|
||||
, info_ (other.info_)
|
||||
, txs_ (other.txs_)
|
||||
, items_ (other.items_)
|
||||
, destroyedCoins_(
|
||||
other.destroyedCoins_)
|
||||
{
|
||||
}
|
||||
|
||||
MetaView::MetaView (open_ledger_t,
|
||||
BasicView const& parent)
|
||||
: base_ (parent)
|
||||
, flags_ (tapNONE)
|
||||
, info_ (parent.info())
|
||||
{
|
||||
assert(! parent.open());
|
||||
info_.open = true;
|
||||
info_.seq = parent.info().seq + 1;
|
||||
info_.parentCloseTime =
|
||||
parent.info().closeTime;
|
||||
}
|
||||
|
||||
MetaView::MetaView (BasicView const& base,
|
||||
ViewFlags flags)
|
||||
: parent_ (parent)
|
||||
: base_ (base)
|
||||
, flags_ (flags)
|
||||
, seq_ (parent->seq())
|
||||
, time_ (parent->time())
|
||||
{
|
||||
}
|
||||
|
||||
MetaView::MetaView (BasicView const* parent,
|
||||
ViewFlags flags, boost::optional<
|
||||
uint256> const& key)
|
||||
: parent_ (parent)
|
||||
, flags_ (flags)
|
||||
, seq_ (parent->seq())
|
||||
, time_ (parent->time())
|
||||
{
|
||||
// VFALCO This needs to be refactored
|
||||
if (key)
|
||||
meta_.init (*key, seq_);
|
||||
}
|
||||
|
||||
MetaView::MetaView (View const* parent)
|
||||
: parent_ (parent)
|
||||
, flags_ (parent->flags())
|
||||
, seq_ (parent->seq())
|
||||
, time_ (parent->time())
|
||||
, info_ (base.info())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +87,7 @@ MetaView::exists (Keylet const& k) const
|
||||
assert(k.key.isNonZero());
|
||||
auto const iter = items_.find(k.key);
|
||||
if (iter == items_.end())
|
||||
return parent_->exists(k);
|
||||
return base_.exists(k);
|
||||
if (iter->second.first == taaDELETE)
|
||||
return false;
|
||||
if (! k.check(*iter->second.second))
|
||||
@@ -99,11 +105,11 @@ MetaView::succ (uint256 const& key,
|
||||
{
|
||||
boost::optional<uint256> next = key;
|
||||
item_list::const_iterator iter;
|
||||
// Find parent successor that is
|
||||
// Find base successor that is
|
||||
// not also deleted in our list
|
||||
do
|
||||
{
|
||||
next = parent_->succ(*next, last);
|
||||
next = base_.succ(*next, last);
|
||||
if (! next)
|
||||
break;
|
||||
iter = items_.find(*next);
|
||||
@@ -141,7 +147,7 @@ MetaView::read (Keylet const& k) const
|
||||
if (iter == items_.end())
|
||||
{
|
||||
auto const sle =
|
||||
parent_->read(k);
|
||||
base_.read(k);
|
||||
if (! sle)
|
||||
return nullptr;
|
||||
return sle;
|
||||
@@ -163,13 +169,13 @@ MetaView::unchecked_erase (uint256 const& key)
|
||||
if (iter == items_.end() ||
|
||||
iter->first != key)
|
||||
{
|
||||
assert(parent_->exists(
|
||||
assert(base_.exists(
|
||||
keylet::unchecked(key)));
|
||||
using namespace std;
|
||||
items_.emplace_hint(iter, piecewise_construct,
|
||||
forward_as_tuple(key), forward_as_tuple(
|
||||
taaDELETE, make_shared<SLE>(
|
||||
*parent_->read(keylet::unchecked(key)))));
|
||||
*base_.read(keylet::unchecked(key)))));
|
||||
return true;
|
||||
}
|
||||
if (iter->second.first == taaCREATE)
|
||||
@@ -192,7 +198,7 @@ MetaView::unchecked_insert(
|
||||
iter->first != sle->key())
|
||||
{
|
||||
// VFALCO return Keylet from SLE
|
||||
assert(! parent_->exists(Keylet{
|
||||
assert(! base_.exists(Keylet{
|
||||
sle->getType(), sle->key()}));
|
||||
using namespace std;
|
||||
items_.emplace_hint(iter, piecewise_construct,
|
||||
@@ -217,7 +223,7 @@ MetaView::unchecked_insert(
|
||||
break;
|
||||
};
|
||||
// VFALCO return Keylet from SLE
|
||||
assert(parent_->exists(
|
||||
assert(base_.exists(
|
||||
Keylet{sle->getType(), sle->key()}));
|
||||
iter->second.first = taaMODIFY;
|
||||
iter->second.second = std::move(sle);
|
||||
@@ -232,7 +238,7 @@ MetaView::unchecked_replace (std::shared_ptr<SLE>&& sle)
|
||||
iter->first != sle->key())
|
||||
{
|
||||
// VFALCO return Keylet from SLE
|
||||
assert(parent_->exists(Keylet{
|
||||
assert(base_.exists(Keylet{
|
||||
sle->getType(), sle->key()}));
|
||||
using namespace std;
|
||||
items_.emplace_hint(iter, piecewise_construct,
|
||||
@@ -255,29 +261,33 @@ MetaView::destroyCoins (std::uint64_t feeDrops)
|
||||
destroyedCoins_ += feeDrops;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
MetaView::txCount() const
|
||||
{
|
||||
return base_.txCount() + txs_.size();
|
||||
}
|
||||
|
||||
bool
|
||||
MetaView::txExists (uint256 const& key) const
|
||||
{
|
||||
if (txs_.count(key) > 0)
|
||||
return true;
|
||||
return parent_->txExists(key);
|
||||
return base_.txExists(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MetaView::txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData)
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
Serializer const> const& metaData)
|
||||
{
|
||||
bool already = txs_.count(key);
|
||||
if (! already)
|
||||
already = parent_->txExists(key);
|
||||
if (already)
|
||||
return false;
|
||||
if (txs_.count(key) ||
|
||||
base_.txExists(key))
|
||||
LogicError("duplicate_tx: " + to_string(key));
|
||||
txs_.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(
|
||||
txn, metaData));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
@@ -301,7 +311,7 @@ MetaView::peek (Keylet const& k)
|
||||
iter->first != k.key)
|
||||
{
|
||||
auto const sle =
|
||||
parent_->read(k);
|
||||
base_.read(k);
|
||||
if (! sle)
|
||||
return nullptr;
|
||||
// Make our own copy
|
||||
@@ -349,7 +359,7 @@ MetaView::insert (std::shared_ptr<SLE> const& sle)
|
||||
iter->first != sle->key())
|
||||
{
|
||||
// VFALCO return Keylet from SLE
|
||||
assert(! parent_->exists(
|
||||
assert(! base_.exists(
|
||||
Keylet{sle->getType(), sle->key()}));
|
||||
items_.emplace_hint(iter, std::piecewise_construct,
|
||||
std::forward_as_tuple(sle->getIndex()),
|
||||
@@ -372,7 +382,7 @@ MetaView::insert (std::shared_ptr<SLE> const& sle)
|
||||
break;
|
||||
}
|
||||
// Existed in parent, deleted here
|
||||
assert(parent_->exists(
|
||||
assert(base_.exists(
|
||||
Keylet{sle->getType(), sle->key()}));
|
||||
iter->second.first = taaMODIFY;
|
||||
iter->second.second = sle;
|
||||
@@ -386,7 +396,7 @@ MetaView::update (std::shared_ptr<SLE> const& sle)
|
||||
iter->first != sle->key())
|
||||
{
|
||||
// VFALCO return Keylet from SLE
|
||||
assert(parent_->exists(
|
||||
assert(base_.exists(
|
||||
Keylet{sle->getType(), sle->key()}));
|
||||
items_.emplace_hint(iter, std::piecewise_construct,
|
||||
std::forward_as_tuple(sle->key()),
|
||||
@@ -404,9 +414,11 @@ MetaView::update (std::shared_ptr<SLE> const& sle)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void MetaView::apply (BasicView& to)
|
||||
void MetaView::apply(
|
||||
BasicView& to, beast::Journal j)
|
||||
{
|
||||
assert(&to == parent_);
|
||||
assert(&to == &base_);
|
||||
assert(to.info().open == info_.open);
|
||||
// Write back the account states
|
||||
for (auto& item : items_)
|
||||
{
|
||||
@@ -521,23 +533,212 @@ Json::Value MetaView::getJson (int) const
|
||||
|
||||
ret[jss::nodes] = nodes;
|
||||
|
||||
ret[jss::metaData] = meta_.getJson (0);
|
||||
// VFALCO The meta only exists during apply() now
|
||||
//ret[jss::metaData] = meta.getJson (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
MetaView::apply (BasicView& to,
|
||||
STTx const& tx, TER ter, beast::Journal j)
|
||||
{
|
||||
auto const sTx =
|
||||
std::make_shared<Serializer>();
|
||||
tx.add(*sTx);
|
||||
|
||||
std::shared_ptr<Serializer> sMeta;
|
||||
|
||||
if (closed())
|
||||
{
|
||||
TxMeta meta;
|
||||
// VFALCO Shouldn't TxMeta ctor do this?
|
||||
meta.init (tx.getTransactionID(), seq());
|
||||
if (deliverAmount_)
|
||||
meta.setDeliveredAmount(
|
||||
*deliverAmount_);
|
||||
|
||||
Mods newMod;
|
||||
for (auto& it : items_)
|
||||
{
|
||||
auto type = &sfGeneric;
|
||||
switch (it.second.first)
|
||||
{
|
||||
case taaMODIFY:
|
||||
#ifdef META_DEBUG
|
||||
JLOG(j.trace) << "modify " << it.first;
|
||||
#endif
|
||||
type = &sfModifiedNode;
|
||||
break;
|
||||
|
||||
case taaDELETE:
|
||||
#ifdef META_DEBUG
|
||||
JLOG(j.trace) << "delete " << it.first;
|
||||
#endif
|
||||
type = &sfDeletedNode;
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
#ifdef META_DEBUG
|
||||
JLOG(j.trace) << "insert " << it.first;
|
||||
#endif
|
||||
type = &sfCreatedNode;
|
||||
break;
|
||||
|
||||
default: // ignore these
|
||||
break;
|
||||
}
|
||||
if (type == &sfGeneric)
|
||||
continue;
|
||||
auto const origNode =
|
||||
base_.read(keylet::unchecked(it.first));
|
||||
auto curNode = it.second.second;
|
||||
if ((type == &sfModifiedNode) && (*curNode == *origNode))
|
||||
continue;
|
||||
std::uint16_t nodeType = curNode
|
||||
? curNode->getFieldU16 (sfLedgerEntryType)
|
||||
: origNode->getFieldU16 (sfLedgerEntryType);
|
||||
meta.setAffectedNode (it.first, *type, nodeType);
|
||||
if (type == &sfDeletedNode)
|
||||
{
|
||||
assert (origNode && curNode);
|
||||
threadOwners (meta, origNode, newMod, j);
|
||||
|
||||
STObject prevs (sfPreviousFields);
|
||||
for (auto const& obj : *origNode)
|
||||
{
|
||||
// go through the original node for
|
||||
// modified fields saved on modification
|
||||
if (obj.getFName().shouldMeta(
|
||||
SField::sMD_ChangeOrig) &&
|
||||
! curNode->hasMatchingEntry (obj))
|
||||
prevs.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!prevs.empty ())
|
||||
meta.getAffectedNode(it.first).emplace_back(std::move(prevs));
|
||||
|
||||
STObject finals (sfFinalFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// go through the final node for final fields
|
||||
if (obj.getFName().shouldMeta(
|
||||
SField::sMD_Always | SField::sMD_DeleteFinal))
|
||||
finals.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!finals.empty ())
|
||||
meta.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||
}
|
||||
else if (type == &sfModifiedNode)
|
||||
{
|
||||
assert (curNode && origNode);
|
||||
|
||||
if (curNode->isThreadedType ()) // thread transaction to node it modified
|
||||
threadTx (meta, curNode, newMod);
|
||||
|
||||
STObject prevs (sfPreviousFields);
|
||||
for (auto const& obj : *origNode)
|
||||
{
|
||||
// search the original node for values saved on modify
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
||||
prevs.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!prevs.empty ())
|
||||
meta.getAffectedNode (it.first).emplace_back (std::move(prevs));
|
||||
|
||||
STObject finals (sfFinalFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// search the final node for values saved always
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))
|
||||
finals.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!finals.empty ())
|
||||
meta.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||
}
|
||||
else if (type == &sfCreatedNode) // if created, thread to owner(s)
|
||||
{
|
||||
assert (curNode && !origNode);
|
||||
threadOwners (meta, curNode, newMod, j);
|
||||
|
||||
if (curNode->isThreadedType ()) // always thread to self
|
||||
threadTx (meta, curNode, newMod);
|
||||
|
||||
STObject news (sfNewFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// save non-default values
|
||||
if (!obj.isDefault () &&
|
||||
obj.getFName().shouldMeta(
|
||||
SField::sMD_Create | SField::sMD_Always))
|
||||
news.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!news.empty ())
|
||||
meta.getAffectedNode (it.first).emplace_back (std::move(news));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
// add any new modified nodes to the modification set
|
||||
for (auto& it : newMod)
|
||||
update (it.second);
|
||||
|
||||
sMeta = std::make_shared<Serializer>();
|
||||
meta.addRaw (*sMeta, ter, txCount());
|
||||
|
||||
// VFALCO For diagnostics do we want to show
|
||||
// metadata even when the base view is open?
|
||||
JLOG(j.trace) <<
|
||||
"metadata " << meta.getJson (0);
|
||||
}
|
||||
|
||||
txInsert (tx.getTransactionID(),
|
||||
sTx, sMeta);
|
||||
|
||||
apply(to);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
MetaView::threadTx (TxMeta& meta,
|
||||
std::shared_ptr<SLE> const& to,
|
||||
Mods& mods)
|
||||
{
|
||||
uint256 prevTxID;
|
||||
std::uint32_t prevLgrID;
|
||||
if (! to->thread(meta.getTxID(),
|
||||
meta.getLgrSeq(), prevTxID, prevLgrID))
|
||||
return false;
|
||||
if (prevTxID.isZero () ||
|
||||
TxMeta::thread(
|
||||
meta.getAffectedNode(to,
|
||||
sfModifiedNode), prevTxID,
|
||||
prevLgrID))
|
||||
return true;
|
||||
assert (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
MetaView::getForMod (uint256 const& key,
|
||||
Mods& mods)
|
||||
Mods& mods, beast::Journal j)
|
||||
{
|
||||
auto iter = items_.find (key);
|
||||
if (iter != items_.end ())
|
||||
{
|
||||
if (iter->second.first == taaDELETE)
|
||||
{
|
||||
WriteLog (lsFATAL, View) <<
|
||||
JLOG(j.fatal) <<
|
||||
"Trying to thread to deleted node";
|
||||
return nullptr;
|
||||
}
|
||||
@@ -554,7 +755,7 @@ MetaView::getForMod (uint256 const& key,
|
||||
}
|
||||
}
|
||||
// VFALCO NOTE Should this be read() or peek()?
|
||||
auto const csle = parent_->read(
|
||||
auto const csle = base_.read(
|
||||
keylet::unchecked(key));
|
||||
if (! csle)
|
||||
return nullptr;
|
||||
@@ -566,50 +767,33 @@ MetaView::getForMod (uint256 const& key,
|
||||
}
|
||||
|
||||
bool
|
||||
MetaView::threadTx (AccountID const& to,
|
||||
Mods& mods)
|
||||
MetaView::threadTx (TxMeta& meta,
|
||||
AccountID const& to, Mods& mods,
|
||||
beast::Journal j)
|
||||
{
|
||||
auto const sle = getForMod(
|
||||
keylet::account(to).key, mods);
|
||||
keylet::account(to).key, mods, j);
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) <<
|
||||
JLOG(j.trace) <<
|
||||
"Thread to " << toBase58(to);
|
||||
#endif
|
||||
assert(sle);
|
||||
if (! sle)
|
||||
{
|
||||
WriteLog (lsFATAL, View) <<
|
||||
JLOG(j.fatal) <<
|
||||
"Threading to non-existent account: " <<
|
||||
toBase58(to);
|
||||
return false;
|
||||
}
|
||||
|
||||
return threadTx (sle, mods);
|
||||
return threadTx (meta, sle, mods);
|
||||
}
|
||||
|
||||
bool
|
||||
MetaView::threadTx(
|
||||
std::shared_ptr<SLE> const& to,
|
||||
Mods& mods)
|
||||
{
|
||||
uint256 prevTxID;
|
||||
std::uint32_t prevLgrID;
|
||||
if (! to->thread(meta_.getTxID(),
|
||||
meta_.getLgrSeq(), prevTxID, prevLgrID))
|
||||
return false;
|
||||
if (prevTxID.isZero () ||
|
||||
TransactionMetaSet::thread(
|
||||
meta_.getAffectedNode(to,
|
||||
sfModifiedNode), prevTxID,
|
||||
prevLgrID))
|
||||
return true;
|
||||
assert (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MetaView::threadOwners(std::shared_ptr<
|
||||
SLE const> const& sle, Mods& mods)
|
||||
MetaView::threadOwners (TxMeta& meta,
|
||||
std::shared_ptr<
|
||||
SLE const> const& sle, Mods& mods,
|
||||
beast::Journal j)
|
||||
{
|
||||
// thread new or modified sle to owner or owners
|
||||
// VFALCO Why not isFieldPresent?
|
||||
@@ -618,163 +802,24 @@ MetaView::threadOwners(std::shared_ptr<
|
||||
{
|
||||
// thread to owner's account
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) << "Thread to single owner";
|
||||
JLOG(j.trace) << "Thread to single owner";
|
||||
#endif
|
||||
return threadTx (sle->getAccountID(sfAccount), mods);
|
||||
return threadTx (meta, sle->getAccountID(
|
||||
sfAccount), mods, j);
|
||||
}
|
||||
else if (sle->getType() == ltRIPPLE_STATE)
|
||||
{
|
||||
// thread to owner's accounts
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) << "Thread to two owners";
|
||||
JLOG(j.trace) << "Thread to two owners";
|
||||
#endif
|
||||
return
|
||||
threadTx(sle->getFieldAmount(sfLowLimit).getIssuer(), mods) &&
|
||||
threadTx(sle->getFieldAmount(sfHighLimit).getIssuer(), mods);
|
||||
threadTx (meta, sle->getFieldAmount(
|
||||
sfLowLimit).getIssuer(), mods, j) &&
|
||||
threadTx (meta, sle->getFieldAmount(
|
||||
sfHighLimit).getIssuer(), mods, j);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
MetaView::calcRawMeta (Serializer& s,
|
||||
TER result, std::uint32_t index)
|
||||
{
|
||||
// calculate the raw meta data and return it. This must be called before the set is committed
|
||||
|
||||
// Entries modified only as a result of building the transaction metadata
|
||||
Mods newMod;
|
||||
|
||||
for (auto& it : items_)
|
||||
{
|
||||
auto type = &sfGeneric;
|
||||
|
||||
switch (it.second.first)
|
||||
{
|
||||
case taaMODIFY:
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) << "Modified Node " << it.first;
|
||||
#endif
|
||||
type = &sfModifiedNode;
|
||||
break;
|
||||
|
||||
case taaDELETE:
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) << "Deleted Node " << it.first;
|
||||
#endif
|
||||
type = &sfDeletedNode;
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
#ifdef META_DEBUG
|
||||
WriteLog (lsTRACE, View) << "Created Node " << it.first;
|
||||
#endif
|
||||
type = &sfCreatedNode;
|
||||
break;
|
||||
|
||||
default: // ignore these
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == &sfGeneric)
|
||||
continue;
|
||||
|
||||
auto const origNode =
|
||||
parent_->read(keylet::unchecked(it.first));
|
||||
auto curNode = it.second.second;
|
||||
|
||||
if ((type == &sfModifiedNode) && (*curNode == *origNode))
|
||||
continue;
|
||||
|
||||
std::uint16_t nodeType = curNode
|
||||
? curNode->getFieldU16 (sfLedgerEntryType)
|
||||
: origNode->getFieldU16 (sfLedgerEntryType);
|
||||
|
||||
meta_.setAffectedNode (it.first, *type, nodeType);
|
||||
|
||||
if (type == &sfDeletedNode)
|
||||
{
|
||||
assert (origNode && curNode);
|
||||
threadOwners (origNode, newMod); // thread transaction to owners
|
||||
|
||||
STObject prevs (sfPreviousFields);
|
||||
for (auto const& obj : *origNode)
|
||||
{
|
||||
// go through the original node for modified fields saved on modification
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
||||
prevs.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!prevs.empty ())
|
||||
meta_.getAffectedNode (it.first).emplace_back (std::move(prevs));
|
||||
|
||||
STObject finals (sfFinalFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// go through the final node for final fields
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_DeleteFinal))
|
||||
finals.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!finals.empty ())
|
||||
meta_.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||
}
|
||||
else if (type == &sfModifiedNode)
|
||||
{
|
||||
assert (curNode && origNode);
|
||||
|
||||
if (curNode->isThreadedType ()) // thread transaction to node it modified
|
||||
threadTx (curNode, newMod);
|
||||
|
||||
STObject prevs (sfPreviousFields);
|
||||
for (auto const& obj : *origNode)
|
||||
{
|
||||
// search the original node for values saved on modify
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))
|
||||
prevs.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!prevs.empty ())
|
||||
meta_.getAffectedNode (it.first).emplace_back (std::move(prevs));
|
||||
|
||||
STObject finals (sfFinalFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// search the final node for values saved always
|
||||
if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))
|
||||
finals.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!finals.empty ())
|
||||
meta_.getAffectedNode (it.first).emplace_back (std::move(finals));
|
||||
}
|
||||
else if (type == &sfCreatedNode) // if created, thread to owner(s)
|
||||
{
|
||||
assert (curNode && !origNode);
|
||||
threadOwners (curNode, newMod);
|
||||
|
||||
if (curNode->isThreadedType ()) // always thread to self
|
||||
threadTx (curNode, newMod);
|
||||
|
||||
STObject news (sfNewFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
// save non-default values
|
||||
if (!obj.isDefault () && obj.getFName ().shouldMeta (SField::sMD_Create | SField::sMD_Always))
|
||||
news.emplace_back (obj);
|
||||
}
|
||||
|
||||
if (!news.empty ())
|
||||
meta_.getAffectedNode (it.first).emplace_back (std::move(news));
|
||||
}
|
||||
else assert (false);
|
||||
}
|
||||
|
||||
// add any new modified nodes to the modification set
|
||||
for (auto& it : newMod)
|
||||
update (it.second);
|
||||
|
||||
meta_.addRaw (s, result, index);
|
||||
WriteLog (lsTRACE, View) << "Metadata:" << meta_.getJson (0);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/TransactionMeta.h>
|
||||
#include <ripple/app/ledger/TxMeta.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/STAccount.h>
|
||||
@@ -29,7 +29,7 @@ namespace ripple {
|
||||
// VFALCO TODO rename class to TransactionMeta
|
||||
|
||||
template<class T>
|
||||
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||
TxMeta::TxMeta (uint256 const& txid,
|
||||
std::uint32_t ledger, T const& data, CtorHelper)
|
||||
: mTransactionID (txid)
|
||||
, mLedger (ledger)
|
||||
@@ -46,21 +46,21 @@ TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||
setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
|
||||
}
|
||||
|
||||
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||
TxMeta::TxMeta (uint256 const& txid,
|
||||
std::uint32_t ledger,
|
||||
Blob const& vec)
|
||||
: TransactionMetaSet (txid, ledger, vec, CtorHelper ())
|
||||
: TxMeta (txid, ledger, vec, CtorHelper ())
|
||||
{
|
||||
}
|
||||
|
||||
TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
|
||||
TxMeta::TxMeta (uint256 const& txid,
|
||||
std::uint32_t ledger,
|
||||
std::string const& data)
|
||||
: TransactionMetaSet (txid, ledger, data, CtorHelper ())
|
||||
: TxMeta (txid, ledger, data, CtorHelper ())
|
||||
{
|
||||
}
|
||||
|
||||
bool TransactionMetaSet::isNodeAffected (uint256 const& node) const
|
||||
bool TxMeta::isNodeAffected (uint256 const& node) const
|
||||
{
|
||||
for (auto const& n : mNodes)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ bool TransactionMetaSet::isNodeAffected (uint256 const& node) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void TransactionMetaSet::setAffectedNode (uint256 const& node, SField const& type,
|
||||
void TxMeta::setAffectedNode (uint256 const& node, SField const& type,
|
||||
std::uint16_t nodeType)
|
||||
{
|
||||
// make sure the node exists and force its type
|
||||
@@ -94,7 +94,7 @@ void TransactionMetaSet::setAffectedNode (uint256 const& node, SField const& typ
|
||||
}
|
||||
|
||||
boost::container::flat_set<AccountID>
|
||||
TransactionMetaSet::getAffectedAccounts() const
|
||||
TxMeta::getAffectedAccounts() const
|
||||
{
|
||||
boost::container::flat_set<AccountID> list;
|
||||
list.reserve (10);
|
||||
@@ -137,7 +137,7 @@ TransactionMetaSet::getAffectedAccounts() const
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionMetaSet) << "limit is not amount " << field.getJson (0);
|
||||
WriteLog (lsFATAL, TxMeta) << "limit is not amount " << field.getJson (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ TransactionMetaSet::getAffectedAccounts() const
|
||||
return list;
|
||||
}
|
||||
|
||||
STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField const& type)
|
||||
STObject& TxMeta::getAffectedNode (SLE::ref node, SField const& type)
|
||||
{
|
||||
assert (&type);
|
||||
uint256 index = node->getIndex ();
|
||||
@@ -167,7 +167,7 @@ STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField const& type
|
||||
return obj;
|
||||
}
|
||||
|
||||
STObject& TransactionMetaSet::getAffectedNode (uint256 const& node)
|
||||
STObject& TxMeta::getAffectedNode (uint256 const& node)
|
||||
{
|
||||
for (auto& n : mNodes)
|
||||
{
|
||||
@@ -178,7 +178,7 @@ STObject& TransactionMetaSet::getAffectedNode (uint256 const& node)
|
||||
throw std::runtime_error ("Affected node not found");
|
||||
}
|
||||
|
||||
const STObject& TransactionMetaSet::peekAffectedNode (uint256 const& node) const
|
||||
const STObject& TxMeta::peekAffectedNode (uint256 const& node) const
|
||||
{
|
||||
for (auto const& n : mNodes)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ const STObject& TransactionMetaSet::peekAffectedNode (uint256 const& node) const
|
||||
throw std::runtime_error ("Affected node not found");
|
||||
}
|
||||
|
||||
void TransactionMetaSet::init (uint256 const& id, std::uint32_t ledger)
|
||||
void TxMeta::init (uint256 const& id, std::uint32_t ledger)
|
||||
{
|
||||
mTransactionID = id;
|
||||
mLedger = ledger;
|
||||
@@ -197,13 +197,13 @@ void TransactionMetaSet::init (uint256 const& id, std::uint32_t ledger)
|
||||
mDelivered = boost::optional <STAmount> ();
|
||||
}
|
||||
|
||||
void TransactionMetaSet::swap (TransactionMetaSet& s) noexcept
|
||||
void TxMeta::swap (TxMeta& s) noexcept
|
||||
{
|
||||
assert ((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger));
|
||||
mNodes.swap (s.mNodes);
|
||||
}
|
||||
|
||||
bool TransactionMetaSet::thread (STObject& node, uint256 const& prevTxID, std::uint32_t prevLgrID)
|
||||
bool TxMeta::thread (STObject& node, uint256 const& prevTxID, std::uint32_t prevLgrID)
|
||||
{
|
||||
if (node.getFieldIndex (sfPreviousTxnID) == -1)
|
||||
{
|
||||
@@ -223,7 +223,7 @@ static bool compare (const STObject& o1, const STObject& o2)
|
||||
return o1.getFieldH256 (sfLedgerIndex) < o2.getFieldH256 (sfLedgerIndex);
|
||||
}
|
||||
|
||||
STObject TransactionMetaSet::getAsObject () const
|
||||
STObject TxMeta::getAsObject () const
|
||||
{
|
||||
STObject metaData (sfTransactionMetaData);
|
||||
assert (mResult != 255);
|
||||
@@ -235,7 +235,7 @@ STObject TransactionMetaSet::getAsObject () const
|
||||
return metaData;
|
||||
}
|
||||
|
||||
void TransactionMetaSet::addRaw (Serializer& s, TER result, std::uint32_t index)
|
||||
void TxMeta::addRaw (Serializer& s, TER result, std::uint32_t index)
|
||||
{
|
||||
mResult = static_cast<int> (result);
|
||||
mIndex = index;
|
||||
@@ -152,7 +152,7 @@ class MetaView_test
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
wipe(*env.ledger);
|
||||
MetaView v(env.ledger.get(), tapNONE);
|
||||
MetaView v(*env.ledger, tapNONE);
|
||||
succ(v, 0, boost::none);
|
||||
v.insert(sle(1));
|
||||
expect(v.exists(k(1)));
|
||||
@@ -189,7 +189,7 @@ class MetaView_test
|
||||
v0.unchecked_insert(sle(4));
|
||||
v0.unchecked_insert(sle(7));
|
||||
{
|
||||
MetaView v1(&v0, tapNONE);
|
||||
MetaView v1(v0, tapNONE);
|
||||
v1.insert(sle(3));
|
||||
v1.insert(sle(5));
|
||||
v1.insert(sle(6));
|
||||
@@ -252,7 +252,7 @@ class MetaView_test
|
||||
v0.unchecked_insert(sle(4, 4));
|
||||
|
||||
{
|
||||
MetaView v1(&v0, tapNONE);
|
||||
MetaView v1(v0, tapNONE);
|
||||
v1.erase(v1.peek(k(2)));
|
||||
v1.insert(sle(3, 3));
|
||||
auto s = v1.peek(k(4));
|
||||
@@ -263,7 +263,7 @@ class MetaView_test
|
||||
expect(seq(v1.read(k(3))) == 3);
|
||||
expect(seq(v1.read(k(4))) == 5);
|
||||
{
|
||||
MetaView v2(&v1);
|
||||
MetaView v2(v1, tapNONE);
|
||||
auto s = v2.peek(k(3));
|
||||
seq(s, 6);
|
||||
v2.update(s);
|
||||
@@ -280,7 +280,7 @@ class MetaView_test
|
||||
expect(seq(v1.read(k(4))) == 5);
|
||||
|
||||
{
|
||||
MetaView v2(&v1);
|
||||
MetaView v2(v1, tapNONE);
|
||||
auto s = v2.peek(k(3));
|
||||
seq(s, 6);
|
||||
v2.update(s);
|
||||
@@ -311,36 +311,41 @@ class MetaView_test
|
||||
{
|
||||
Env env(*this);
|
||||
wipe(*env.ledger);
|
||||
MetaView v0(env.ledger.get(), tapNONE);
|
||||
MetaView v0(*env.ledger, tapNONE);
|
||||
expect(v0.seq() != 98);
|
||||
expect(v0.seq() == env.ledger->seq());
|
||||
expect(v0.time() != 99);
|
||||
expect(v0.time() == env.ledger->time());
|
||||
expect(v0.parentCloseTime() != 99);
|
||||
expect(v0.parentCloseTime() ==
|
||||
env.ledger->parentCloseTime());
|
||||
expect(v0.flags() == tapNONE);
|
||||
{
|
||||
// Shallow copy
|
||||
MetaView v1(v0);
|
||||
MetaView v1(shallow_copy, v0);
|
||||
expect (v1.seq() == v0.seq());
|
||||
expect (v1.time() == v1.time());
|
||||
expect (v1.parentCloseTime() ==
|
||||
v1.parentCloseTime());
|
||||
expect (v1.flags() == tapNONE);
|
||||
|
||||
MetaView v2(&v1, tapNO_CHECK_SIGN);
|
||||
expect(v2.time() == v1.time());
|
||||
MetaView v2(v1, tapNO_CHECK_SIGN);
|
||||
expect(v2.parentCloseTime() ==
|
||||
v1.parentCloseTime());
|
||||
expect(v2.seq() == v1.seq());
|
||||
expect(v2.flags() == tapNO_CHECK_SIGN);
|
||||
MetaView v3(&v2);
|
||||
MetaView v3(v2, tapNONE);
|
||||
expect(v3.seq() == v2.seq());
|
||||
expect(v3.time() == v2.time());
|
||||
expect(v3.flags() == v2.flags());
|
||||
expect(v3.parentCloseTime() ==
|
||||
v2.parentCloseTime());
|
||||
expect(v3.flags() == tapNONE);
|
||||
}
|
||||
{
|
||||
PaymentView v1(&v0, tapNO_CHECK_SIGN);
|
||||
PaymentView v1(v0, tapNO_CHECK_SIGN);
|
||||
expect(v1.seq() == v0.seq());
|
||||
expect(v1.time() == v0.time());
|
||||
expect(v1.parentCloseTime() ==
|
||||
v0.parentCloseTime());
|
||||
expect(v1.flags() == tapNO_CHECK_SIGN);
|
||||
PaymentView v2(&v1);
|
||||
expect(v2.seq() == v1.seq());
|
||||
expect(v2.time() == v1.time());
|
||||
expect(v2.parentCloseTime() ==
|
||||
v1.parentCloseTime());
|
||||
expect(v2.flags() == v1.flags());
|
||||
}
|
||||
}
|
||||
@@ -359,9 +364,9 @@ class MetaView_test
|
||||
wipe(*env.ledger);
|
||||
BasicView& v0 = *env.ledger;
|
||||
v0.unchecked_insert(sle(1));
|
||||
MetaView v1(&v0, tapNONE);
|
||||
MetaView v1(v0, tapNONE);
|
||||
{
|
||||
MetaView v2(&v1);
|
||||
MetaView v2(v1, tapNONE);
|
||||
v2.erase(v2.peek(k(1)));
|
||||
v2.apply(v1);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/ledger/tests/common_ledger.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/protocol/RippleAddress.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
@@ -127,9 +128,9 @@ parseTransaction(TestAccount& account, Json::Value const& tx_json, bool sign)
|
||||
void
|
||||
applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check)
|
||||
{
|
||||
TransactionEngine engine(ledger);
|
||||
auto r = engine.applyTransaction(tx,
|
||||
tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN));
|
||||
auto const r = apply (*ledger, tx,
|
||||
check ? tapNONE : tapNO_CHECK_SIGN, getConfig(),
|
||||
beast::Journal{});
|
||||
if (r.first != tesSUCCESS)
|
||||
throw std::runtime_error("r != tesSUCCESS");
|
||||
if (!r.second)
|
||||
@@ -441,9 +442,11 @@ close_and_advance(Ledger::pointer& ledger, std::shared_ptr<Ledger const>& LCL)
|
||||
// that other Ledger constructor can take a const Ledger.
|
||||
Ledger oldLCL(*LCL, false);
|
||||
Ledger::pointer newLCL = std::make_shared<Ledger>(false, oldLCL);
|
||||
MetaView accum(*newLCL, tapNONE);
|
||||
// Set up to write SHAMap changes to our database,
|
||||
// perform updates, extract changes
|
||||
applyTransactions(&set, newLCL, newLCL, retriableTransactions, false);
|
||||
applyTransactions(&set, accum, newLCL, retriableTransactions);
|
||||
accum.apply(*newLCL, {});
|
||||
newLCL->updateSkipList();
|
||||
newLCL->setClosed();
|
||||
newLCL->stateMap().flushDirty(
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
#include <ripple/websocket/MakeServer.h>
|
||||
#include <ripple/crypto/RandomNumbers.h>
|
||||
#include <beast/asio/io_latency_probe.h>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <beast/module/core/text/LexicalCast.h>
|
||||
#include <beast/module/core/thread/DeadlineTimer.h>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace ripple {
|
||||
@@ -1337,11 +1337,9 @@ bool ApplicationImp::loadOldLedger (
|
||||
txn->getJson(0);
|
||||
Serializer s;
|
||||
txn->getSTransaction()->add(s);
|
||||
if (! cur->txInsert(item->getTag(),
|
||||
std::make_shared<Serializer const>(std::move(s)),
|
||||
nullptr))
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Unable to add transaction " << item->getTag();
|
||||
cur->txInsert(item->getTag(),
|
||||
std::make_shared<Serializer const>(
|
||||
std::move(s)), nullptr);
|
||||
getApp().getHashRouter().setFlag (item->getTag(), SF_SIGGOOD);
|
||||
}
|
||||
|
||||
@@ -1485,7 +1483,7 @@ static void addTxnSeqField ()
|
||||
}
|
||||
else
|
||||
{
|
||||
TransactionMetaSet m (transID, 0, txnMeta);
|
||||
TxMeta m (transID, 0, txnMeta);
|
||||
txIDs.push_back (std::make_pair (transID, m.getIndex ()));
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace ripple {
|
||||
// VFALCO TODO rename to SortedTxSet
|
||||
class CanonicalTXSet
|
||||
{
|
||||
public:
|
||||
private:
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
std::uint32_t mSeq;
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator = std::map <Key, std::shared_ptr<STTx const>>::iterator;
|
||||
using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::const_iterator;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <ripple/app/ledger/Consensus.h>
|
||||
#include <ripple/app/ledger/LedgerConsensus.h>
|
||||
#include <ripple/app/ledger/AcceptedLedger.h>
|
||||
#include <ripple/app/ledger/MetaView.h>
|
||||
#include <ripple/ledger/CachedView.h>
|
||||
#include <ripple/app/ledger/InboundLedger.h>
|
||||
#include <ripple/app/ledger/InboundLedgers.h>
|
||||
@@ -38,7 +39,7 @@
|
||||
#include <ripple/app/misc/Validations.h>
|
||||
#include <ripple/app/misc/impl/AccountTxPaging.h>
|
||||
#include <ripple/app/misc/UniqueNodeList.h>
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/tx/TransactionMaster.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/Time.h>
|
||||
@@ -251,19 +252,6 @@ public:
|
||||
*/
|
||||
void apply (std::unique_lock<std::mutex>& batchLock);
|
||||
|
||||
/**
|
||||
* Apply each transaction to open ledger.
|
||||
*
|
||||
* @param ledger Open ledger.
|
||||
* @param engine Engine that applies transactions to open ledger.
|
||||
* @param transactions Batch of transactions to apply.
|
||||
* @return Whether any transactions in batch succeeded.
|
||||
*/
|
||||
bool batchApply (
|
||||
Ledger::pointer& ledger,
|
||||
TransactionEngine& engine,
|
||||
std::vector<TransactionStatus>& transactions);
|
||||
|
||||
//
|
||||
// Owner functions.
|
||||
//
|
||||
@@ -987,14 +975,35 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
|
||||
batchLock.unlock();
|
||||
|
||||
{
|
||||
Ledger::pointer ledger;
|
||||
TransactionEngine engine;
|
||||
|
||||
{
|
||||
bool applied = false;
|
||||
boost::optional<MetaView> accum;
|
||||
auto lock = beast::make_lock(getApp().getMasterMutex());
|
||||
|
||||
if (batchApply (ledger, engine, transactions))
|
||||
{
|
||||
std::lock_guard <std::recursive_mutex> lock (
|
||||
m_ledgerMaster.peekMutex());
|
||||
ledger = m_ledgerMaster.getCurrentLedgerHolder().getMutable();
|
||||
accum.emplace(*ledger, tapNONE);
|
||||
for (TransactionStatus& e : transactions)
|
||||
{
|
||||
ViewFlags flags = tapNONE;
|
||||
flags = flags | tapNO_CHECK_SIGN;
|
||||
if (e.admin)
|
||||
flags = flags | tapADMIN;
|
||||
std::tie (e.result, e.applied) =
|
||||
ripple::apply (*accum,
|
||||
*e.transaction->getSTransaction(), flags,
|
||||
getConfig(), deprecatedLogs().journal(
|
||||
"NetworkOPs"));
|
||||
applied |= e.applied;
|
||||
}
|
||||
}
|
||||
|
||||
if (applied)
|
||||
{
|
||||
accum->apply(*ledger,
|
||||
deprecatedLogs().journal("NetworkOPs"));
|
||||
ledger->setImmutable();
|
||||
m_ledgerMaster.getCurrentLedgerHolder().set (ledger);
|
||||
}
|
||||
@@ -1101,28 +1110,6 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
|
||||
mDispatchState = DispatchState::none;
|
||||
}
|
||||
|
||||
bool NetworkOPsImp::batchApply (Ledger::pointer& ledger,
|
||||
TransactionEngine& engine,
|
||||
std::vector<TransactionStatus>& transactions)
|
||||
{
|
||||
bool applied = false;
|
||||
std::lock_guard <std::recursive_mutex> lock (m_ledgerMaster.peekMutex());
|
||||
|
||||
ledger = m_ledgerMaster.getCurrentLedgerHolder().getMutable();
|
||||
engine.setLedger (ledger);
|
||||
|
||||
for (TransactionStatus& e : transactions)
|
||||
{
|
||||
std::tie (e.result, e.applied) = engine.applyTransaction (
|
||||
*e.transaction->getSTransaction(),
|
||||
e.admin ? (tapOPEN_LEDGER | tapNO_CHECK_SIGN | tapADMIN) : (
|
||||
tapOPEN_LEDGER | tapNO_CHECK_SIGN));
|
||||
applied |= e.applied;
|
||||
}
|
||||
|
||||
return applied;
|
||||
}
|
||||
|
||||
//
|
||||
// Owner functions
|
||||
//
|
||||
@@ -1793,7 +1780,7 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs (
|
||||
ledger->pendSaveValidated(false, false);
|
||||
}
|
||||
|
||||
ret.emplace_back (txn, std::make_shared<TransactionMetaSet> (
|
||||
ret.emplace_back (txn, std::make_shared<TxMeta> (
|
||||
txn->getID (), txn->getLedger (), txnMeta));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ public:
|
||||
virtual std::size_t getLocalTxCount () = 0;
|
||||
|
||||
// client information retrieval functions
|
||||
using AccountTx = std::pair<Transaction::pointer, TransactionMetaSet::pointer>;
|
||||
using AccountTx = std::pair<Transaction::pointer, TxMeta::pointer>;
|
||||
using AccountTxs = std::vector<AccountTx>;
|
||||
|
||||
virtual AccountTxs getAccountTxs (
|
||||
|
||||
@@ -46,7 +46,7 @@ convertBlobsToTxResult (
|
||||
tr->setStatus (Transaction::sqlTransactionStatus(status));
|
||||
tr->setLedger (ledger_index);
|
||||
|
||||
auto metaset = std::make_shared<TransactionMetaSet> (
|
||||
auto metaset = std::make_shared<TxMeta> (
|
||||
tr->getID (), tr->getLedger (), rawMeta);
|
||||
|
||||
to.emplace_back(std::move(tr), metaset);
|
||||
|
||||
@@ -525,8 +525,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
if (valid)
|
||||
{
|
||||
boost::optional<PaymentView> sandbox;
|
||||
sandbox.emplace(cache->getLedger().get(),
|
||||
tapOPEN_LEDGER);
|
||||
sandbox.emplace(*cache->getLedger(),
|
||||
tapNONE);
|
||||
|
||||
auto& sourceAccount = !isXRP (currIssuer.account)
|
||||
? currIssuer.account
|
||||
@@ -552,8 +552,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
m_journal.debug
|
||||
<< iIdentifier << " Trying with an extra path element";
|
||||
spsPaths.push_back (fullLiquidityPath);
|
||||
sandbox.emplace(cache->getLedger().get(),
|
||||
tapOPEN_LEDGER);
|
||||
sandbox.emplace(*cache->getLedger(),
|
||||
tapNONE);
|
||||
rc = path::RippleCalc::rippleCalculate (
|
||||
*sandbox,
|
||||
saMaxAmount,
|
||||
|
||||
@@ -378,7 +378,7 @@ TER Pathfinder::getPathLiquidity (
|
||||
path::RippleCalc::Input rcInput;
|
||||
rcInput.defaultPathsAllowed = false;
|
||||
|
||||
PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER);
|
||||
PaymentView sandbox (*mLedger, tapNONE);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -443,7 +443,7 @@ void Pathfinder::computePathRanks (int maxPaths)
|
||||
// Must subtract liquidity in default path from remaining amount.
|
||||
try
|
||||
{
|
||||
PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER);
|
||||
PaymentView sandbox (*mLedger, tapNONE);
|
||||
|
||||
path::RippleCalc::Input rcInput;
|
||||
rcInput.partialPaymentAllowed = true;
|
||||
|
||||
@@ -212,7 +212,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
|
||||
|
||||
if (node().sleOffer->isFieldPresent (sfExpiration) &&
|
||||
(node().sleOffer->getFieldU32 (sfExpiration) <=
|
||||
view().time()))
|
||||
view().parentCloseTime()))
|
||||
{
|
||||
// Offer is expired.
|
||||
WriteLog (lsTRACE, RippleCalc)
|
||||
|
||||
@@ -73,14 +73,14 @@ public:
|
||||
/** @{ */
|
||||
explicit
|
||||
PaymentView (PaymentView const* parent)
|
||||
: ViewWrapper (parent)
|
||||
: ViewWrapper (*parent, parent->flags())
|
||||
, pv_ (parent)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
PaymentView (PaymentView* parent)
|
||||
: ViewWrapper (parent)
|
||||
: ViewWrapper (*parent, parent->flags())
|
||||
, pv_ (parent)
|
||||
{
|
||||
}
|
||||
|
||||
56
src/ripple/app/tx/apply.h
Normal file
56
src/ripple/app/tx/apply.h
Normal file
@@ -0,0 +1,56 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_APPLY_H_INCLUDED
|
||||
#define RIPPLE_TX_APPLY_H_INCLUDED
|
||||
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/TER.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Apply a transaction to a BasicView.
|
||||
|
||||
Throws:
|
||||
|
||||
Exceptions are thrown on broken invariants. Callers
|
||||
should catch these exceptions to protect the ledger
|
||||
and the running process.
|
||||
|
||||
std::logic_error
|
||||
(any)
|
||||
|
||||
@return A pair with the TER and a bool indicating
|
||||
whether or not the transaction was applied.
|
||||
*/
|
||||
// VFALCO Some call sites use try/catch some don't.
|
||||
std::pair<TER, bool>
|
||||
apply (BasicView& view,
|
||||
STTx const& tx, ViewFlags flags,
|
||||
Config const& config,
|
||||
beast::Journal journal);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
55
src/ripple/app/tx/impl/ApplyContext.cpp
Normal file
55
src/ripple/app/tx/impl/ApplyContext.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
ApplyContext::ApplyContext(
|
||||
BasicView& base, STTx const& tx_,
|
||||
ViewFlags flags, Config const& config_,
|
||||
beast::Journal journal_)
|
||||
: tx (tx_)
|
||||
, config (config_)
|
||||
, journal(journal_)
|
||||
, base_ (base)
|
||||
, flags_(flags)
|
||||
{
|
||||
view_.emplace(base_, flags_);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyContext::discard()
|
||||
{
|
||||
view_.emplace(base_, flags_);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyContext::apply(TER ter)
|
||||
{
|
||||
view_->apply(base_, tx, ter, journal);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
@@ -17,11 +17,13 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_TX_TRANSACTIONENGINE_H_INCLUDED
|
||||
#define RIPPLE_APP_TX_TRANSACTIONENGINE_H_INCLUDED
|
||||
#ifndef RIPPLE_TX_APPLYCONTEXT_H_INCLUDED
|
||||
#define RIPPLE_TX_APPLYCONTEXT_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/ledger/MetaView.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <utility>
|
||||
|
||||
@@ -29,71 +31,54 @@ namespace ripple {
|
||||
|
||||
// tx_enable_test
|
||||
|
||||
// One instance per ledger.
|
||||
// Only one transaction applied at a time.
|
||||
class TransactionEngine
|
||||
/** State information when applying a tx. */
|
||||
class ApplyContext
|
||||
{
|
||||
boost::optional<MetaView> mNodes;
|
||||
|
||||
void txnWrite();
|
||||
|
||||
protected:
|
||||
Ledger::pointer mLedger;
|
||||
int mTxnSeq = 0;
|
||||
|
||||
public:
|
||||
TransactionEngine() = default;
|
||||
|
||||
explicit
|
||||
TransactionEngine (Ledger::ref ledger)
|
||||
: mLedger (ledger)
|
||||
{
|
||||
assert (mLedger);
|
||||
}
|
||||
ApplyContext (BasicView& base,
|
||||
STTx const& tx, ViewFlags flags,
|
||||
Config const& config,
|
||||
beast::Journal = {});
|
||||
|
||||
STTx const& tx;
|
||||
Config const& config;
|
||||
beast::Journal const journal;
|
||||
|
||||
View&
|
||||
view ()
|
||||
view()
|
||||
{
|
||||
return *mNodes;
|
||||
return *view_;
|
||||
}
|
||||
|
||||
Ledger::ref
|
||||
getLedger()
|
||||
View const&
|
||||
view() const
|
||||
{
|
||||
return mLedger;
|
||||
}
|
||||
|
||||
void
|
||||
setLedger (Ledger::ref ledger)
|
||||
{
|
||||
assert (ledger);
|
||||
mLedger = ledger;
|
||||
return *view_;
|
||||
}
|
||||
|
||||
/** Sets the DeliveredAmount field in the metadata */
|
||||
void
|
||||
deliverAmount (STAmount const& delivered)
|
||||
{
|
||||
mNodes->setDeliveredAmount(delivered);
|
||||
view_->setDeliveredAmount(delivered);
|
||||
}
|
||||
|
||||
std::pair<TER, bool>
|
||||
applyTransaction (STTx const&, ViewFlags);
|
||||
/** Discard changes and start fresh. */
|
||||
void
|
||||
discard();
|
||||
|
||||
bool
|
||||
checkInvariants (TER result, STTx const& txn, ViewFlags params);
|
||||
/** Apply the transaction result to the base. */
|
||||
void
|
||||
apply (TER);
|
||||
|
||||
private:
|
||||
BasicView& base_;
|
||||
ViewFlags flags_;
|
||||
beast::Journal j_;
|
||||
boost::optional<MetaView> view_;
|
||||
};
|
||||
|
||||
inline ViewFlags operator| (const ViewFlags& l1, const ViewFlags& l2)
|
||||
{
|
||||
return static_cast<ViewFlags> (static_cast<int> (l1) | static_cast<int> (l2));
|
||||
}
|
||||
|
||||
inline ViewFlags operator& (const ViewFlags& l1, const ViewFlags& l2)
|
||||
{
|
||||
return static_cast<ViewFlags> (static_cast<int> (l1) & static_cast<int> (l2));
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
@@ -18,37 +18,21 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/CancelOffer.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CancelOffer
|
||||
: public Transactor
|
||||
TER
|
||||
CancelOffer::preCheck ()
|
||||
{
|
||||
public:
|
||||
CancelOffer (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CancelOffer"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
std::uint32_t const uTxFlags (mTxn.getFlags ());
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
@@ -57,48 +41,39 @@ public:
|
||||
|
||||
if (!uOfferSequence)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"No sequence specified.";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
CancelOffer::doApply ()
|
||||
{
|
||||
std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
|
||||
|
||||
if (mTxnAccount->getFieldU32 (sfSequence) - 1 <= uOfferSequence)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Sequence " << uOfferSequence << " is invalid.";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
uint256 const offerIndex (getOfferIndex (mTxnAccountID, uOfferSequence));
|
||||
|
||||
auto sleOffer = mEngine->view().peek (
|
||||
auto sleOffer = view().peek (
|
||||
keylet::offer(offerIndex));
|
||||
|
||||
if (sleOffer)
|
||||
{
|
||||
m_journal.debug << "Trying to cancel offer #" << uOfferSequence;
|
||||
return offerDelete (mEngine->view(), sleOffer);
|
||||
j_.debug << "Trying to cancel offer #" << uOfferSequence;
|
||||
return offerDelete (view(), sleOffer);
|
||||
}
|
||||
|
||||
m_journal.debug << "Offer #" << uOfferSequence << " can't be found.";
|
||||
j_.debug << "Offer #" << uOfferSequence << " can't be found.";
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_CancelOffer (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return CancelOffer (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
48
src/ripple/app/tx/impl/CancelOffer.h
Normal file
48
src/ripple/app/tx/impl/CancelOffer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CANCELOFFER_H_INCLUDED
|
||||
#define RIPPLE_TX_CANCELOFFER_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CancelOffer
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
CancelOffer (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override;
|
||||
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,38 +18,32 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/CancelTicket.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CancelTicket
|
||||
: public Transactor
|
||||
TER
|
||||
CancelTicket::preCheck()
|
||||
{
|
||||
public:
|
||||
CancelTicket (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CancelTicket"))
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_TICKETS
|
||||
if (! (view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
CancelTicket::doApply ()
|
||||
{
|
||||
assert (mTxnAccount);
|
||||
|
||||
uint256 const ticketId = mTxn.getFieldH256 (sfTicketID);
|
||||
|
||||
// VFALCO This is highly suspicious, we're requiring that the
|
||||
// transaction provide the return value of getTicketIndex?
|
||||
SLE::pointer sleTicket = mEngine->view().peek (keylet::ticket(ticketId));
|
||||
SLE::pointer sleTicket = view().peek (keylet::ticket(ticketId));
|
||||
|
||||
if (!sleTicket)
|
||||
return tecNO_ENTRY;
|
||||
@@ -69,7 +63,7 @@ public:
|
||||
{
|
||||
std::uint32_t const expiration = sleTicket->getFieldU32 (sfExpiration);
|
||||
|
||||
if (mEngine->view().time() >= expiration)
|
||||
if (view().parentCloseTime() >= expiration)
|
||||
authorized = true;
|
||||
}
|
||||
|
||||
@@ -78,29 +72,14 @@ public:
|
||||
|
||||
std::uint64_t const hint (sleTicket->getFieldU64 (sfOwnerNode));
|
||||
|
||||
TER const result = dirDelete (mEngine->view (), false, hint,
|
||||
TER const result = dirDelete (ctx_.view (), false, hint,
|
||||
getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0));
|
||||
|
||||
adjustOwnerCount(mEngine->view(), mEngine->view().peek(
|
||||
adjustOwnerCount(view(), view().peek(
|
||||
keylet::account(ticket_owner)), -1);
|
||||
mEngine->view ().erase (sleTicket);
|
||||
ctx_.view ().erase (sleTicket);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_CancelTicket (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_TICKETS
|
||||
if (! (engine->view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
return CancelTicket (txn, params, engine).apply();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
46
src/ripple/app/tx/impl/CancelTicket.h
Normal file
46
src/ripple/app/tx/impl/CancelTicket.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2014 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CANCELTICKET_H_INCLUDED
|
||||
#define RIPPLE_TX_CANCELTICKET_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CancelTicket
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
CancelTicket (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck() override;
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,33 +18,18 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Change.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/AmendmentTable.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Change
|
||||
: public Transactor
|
||||
TER
|
||||
Change::doApply()
|
||||
{
|
||||
public:
|
||||
Change (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Change"))
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
if (mTxn.getTxnType () == ttAMENDMENT)
|
||||
return applyAmendment ();
|
||||
|
||||
@@ -52,80 +37,84 @@ public:
|
||||
return applyFee ();
|
||||
|
||||
return temUNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
TER checkSign () override
|
||||
{
|
||||
TER
|
||||
Change::checkSign()
|
||||
{
|
||||
if (mTxn.getAccountID (sfAccount).isNonZero ())
|
||||
{
|
||||
m_journal.warning << "Bad source account";
|
||||
j_.warning << "Bad source account";
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
|
||||
if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ())
|
||||
{
|
||||
m_journal.warning << "Bad signature";
|
||||
j_.warning << "Bad signature";
|
||||
return temBAD_SIGNATURE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
TER checkSeq () override
|
||||
{
|
||||
TER
|
||||
Change::checkSeq()
|
||||
{
|
||||
if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID))
|
||||
{
|
||||
m_journal.warning << "Bad sequence";
|
||||
j_.warning << "Bad sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
TER payFee () override
|
||||
{
|
||||
TER
|
||||
Change::payFee()
|
||||
{
|
||||
if (mTxn.getTransactionFee () != STAmount ())
|
||||
{
|
||||
m_journal.warning << "Non-zero fee";
|
||||
j_.warning << "Non-zero fee";
|
||||
return temBAD_FEE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
TER
|
||||
Change::preCheck()
|
||||
{
|
||||
mTxnAccountID = mTxn.getAccountID(sfAccount);
|
||||
|
||||
if (mTxnAccountID.isNonZero ())
|
||||
{
|
||||
m_journal.warning << "Bad source id";
|
||||
j_.warning << "Bad source id";
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
|
||||
if (mParams & tapOPEN_LEDGER)
|
||||
if (view().open())
|
||||
{
|
||||
m_journal.warning << "Change transaction against open ledger";
|
||||
j_.warning << "Change transaction against open ledger";
|
||||
return temINVALID;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TER applyAmendment ()
|
||||
{
|
||||
TER
|
||||
Change::applyAmendment()
|
||||
{
|
||||
uint256 amendment (mTxn.getFieldH256 (sfAmendment));
|
||||
|
||||
auto const k = keylet::amendments();
|
||||
|
||||
SLE::pointer amendmentObject =
|
||||
mEngine->view().peek (k);
|
||||
view().peek (k);
|
||||
|
||||
if (!amendmentObject)
|
||||
{
|
||||
amendmentObject = std::make_shared<SLE>(k);
|
||||
mEngine->view().insert(amendmentObject);
|
||||
view().insert(amendmentObject);
|
||||
}
|
||||
|
||||
STVector256 amendments =
|
||||
@@ -137,7 +126,7 @@ private:
|
||||
|
||||
amendments.push_back (amendment);
|
||||
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
||||
mEngine->view().update (amendmentObject);
|
||||
view().update (amendmentObject);
|
||||
|
||||
getApp().getAmendmentTable ().enable (amendment);
|
||||
|
||||
@@ -145,22 +134,23 @@ private:
|
||||
getApp().getOPs ().setAmendmentBlocked ();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
TER applyFee ()
|
||||
{
|
||||
TER
|
||||
Change::applyFee()
|
||||
{
|
||||
auto const k = keylet::fees();
|
||||
|
||||
SLE::pointer feeObject = mEngine->view().peek (k);
|
||||
SLE::pointer feeObject = view().peek (k);
|
||||
|
||||
if (!feeObject)
|
||||
{
|
||||
feeObject = std::make_shared<SLE>(k);
|
||||
mEngine->view().insert(feeObject);
|
||||
view().insert(feeObject);
|
||||
}
|
||||
|
||||
// VFALCO-FIXME this generates errors
|
||||
// m_journal.trace <<
|
||||
// j_.trace <<
|
||||
// "Previous fee object: " << feeObject->getJson (0);
|
||||
|
||||
feeObject->setFieldU64 (
|
||||
@@ -172,30 +162,13 @@ private:
|
||||
feeObject->setFieldU32 (
|
||||
sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
|
||||
|
||||
mEngine->view().update (feeObject);
|
||||
view().update (feeObject);
|
||||
|
||||
// VFALCO-FIXME this generates errors
|
||||
// m_journal.trace <<
|
||||
// j_.trace <<
|
||||
// "New fee object: " << feeObject->getJson (0);
|
||||
m_journal.warning << "Fees have been changed";
|
||||
j_.warning << "Fees have been changed";
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// VFALCO TODO Can this be removed?
|
||||
bool mustHaveValidAccount () override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TER
|
||||
transact_Change (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return Change (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
63
src/ripple/app/tx/impl/Change.h
Normal file
63
src/ripple/app/tx/impl/Change.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CHANGE_H_INCLUDED
|
||||
#define RIPPLE_TX_CHANGE_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/AmendmentTable.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Change
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
Change (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply () override;
|
||||
TER checkSign () override;
|
||||
TER checkSeq () override;
|
||||
TER payFee () override;
|
||||
TER preCheck () override;
|
||||
|
||||
private:
|
||||
TER applyAmendment ();
|
||||
|
||||
TER applyFee ();
|
||||
|
||||
// VFALCO TODO Can this be removed?
|
||||
bool mustHaveValidAccount () override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,9 +18,10 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/CreateOffer.h>
|
||||
#include <ripple/app/tx/impl/OfferStream.h>
|
||||
#include <ripple/app/tx/impl/Taker.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
@@ -31,42 +32,34 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateOffer
|
||||
: public Transactor
|
||||
TER
|
||||
CreateOffer::checkAcceptAsset(IssueRef issue) const
|
||||
{
|
||||
private:
|
||||
// What kind of offer we are placing
|
||||
CrossType cross_type_;
|
||||
|
||||
/** Determine if we are authorized to hold the asset we want to get */
|
||||
TER
|
||||
checkAcceptAsset(IssueRef issue) const
|
||||
{
|
||||
// Only valid for custom currencies
|
||||
assert (!isXRP (issue.currency));
|
||||
|
||||
auto const issuerAccount = mEngine->view().read(
|
||||
auto const issuerAccount = ctx_.view().read(
|
||||
keylet::account(issue.account));
|
||||
|
||||
if (!issuerAccount)
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
if (j_.warning) j_.warning <<
|
||||
"delay: can't receive IOUs from non-existent issuer: " <<
|
||||
to_string (issue.account);
|
||||
|
||||
return (mParams & tapRETRY)
|
||||
return (view().flags() & tapRETRY)
|
||||
? terNO_ACCOUNT
|
||||
: tecNO_ISSUER;
|
||||
}
|
||||
|
||||
if (issuerAccount->getFieldU32 (sfFlags) & lsfRequireAuth)
|
||||
{
|
||||
auto const trustLine = mEngine->view().read(
|
||||
auto const trustLine = ctx_.view().read(
|
||||
keylet::line(mTxnAccountID, issue.account, issue.currency));
|
||||
|
||||
if (!trustLine)
|
||||
{
|
||||
return (mParams & tapRETRY)
|
||||
return (view().flags() & tapRETRY)
|
||||
? terNO_LINE
|
||||
: tecNO_LINE;
|
||||
}
|
||||
@@ -81,35 +74,33 @@ private:
|
||||
|
||||
if (!is_authorized)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"delay: can't receive IOUs from issuer without auth.";
|
||||
|
||||
return (mParams & tapRETRY)
|
||||
return (view().flags() & tapRETRY)
|
||||
? terNO_AUTH
|
||||
: tecNO_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
dry_offer (View& view, Offer const& offer)
|
||||
{
|
||||
bool
|
||||
CreateOffer::dry_offer (View& view, Offer const& offer)
|
||||
{
|
||||
if (offer.fully_consumed ())
|
||||
return true;
|
||||
auto const amount = accountFunds(view, offer.owner(),
|
||||
offer.amount().out, fhZERO_IF_FROZEN, getConfig());
|
||||
offer.amount().out, fhZERO_IF_FROZEN, ctx_.config);
|
||||
return (amount <= zero);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
std::pair<bool, Quality>
|
||||
select_path (
|
||||
std::pair<bool, Quality>
|
||||
CreateOffer::select_path (
|
||||
bool have_direct, OfferStream const& direct,
|
||||
bool have_bridge, OfferStream const& leg1, OfferStream const& leg2)
|
||||
{
|
||||
{
|
||||
// If we don't have any viable path, why are we here?!
|
||||
assert (have_direct || have_bridge);
|
||||
|
||||
@@ -133,15 +124,15 @@ private:
|
||||
// Either there was no direct offer, or it didn't have a better quality
|
||||
// than the bridge.
|
||||
return std::make_pair (false, bridged_quality);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<TER, Amounts>
|
||||
bridged_cross (
|
||||
std::pair<TER, Amounts>
|
||||
CreateOffer::bridged_cross (
|
||||
Taker& taker,
|
||||
View& view,
|
||||
View& view_cancel,
|
||||
Clock::time_point const when)
|
||||
{
|
||||
{
|
||||
auto const& taker_amount = taker.original_offer ();
|
||||
|
||||
assert (!isXRP (taker_amount.in) && !isXRP (taker_amount.out));
|
||||
@@ -150,13 +141,13 @@ private:
|
||||
throw std::logic_error ("Bridging with XRP and an endpoint.");
|
||||
|
||||
OfferStream offers_direct (view, view_cancel,
|
||||
Book (taker.issue_in (), taker.issue_out ()), when, m_journal);
|
||||
Book (taker.issue_in (), taker.issue_out ()), when, ctx_.config, j_);
|
||||
|
||||
OfferStream offers_leg1 (view, view_cancel,
|
||||
Book (taker.issue_in (), xrpIssue ()), when, m_journal);
|
||||
Book (taker.issue_in (), xrpIssue ()), when, ctx_.config, j_);
|
||||
|
||||
OfferStream offers_leg2 (view, view_cancel,
|
||||
Book (xrpIssue (), taker.issue_out ()), when, m_journal);
|
||||
Book (xrpIssue (), taker.issue_out ()), when, ctx_.config, j_);
|
||||
|
||||
TER cross_result = tesSUCCESS;
|
||||
|
||||
@@ -191,23 +182,23 @@ private:
|
||||
|
||||
if (use_direct)
|
||||
{
|
||||
if (m_journal.debug)
|
||||
if (j_.debug)
|
||||
{
|
||||
m_journal.debug << count << " Direct:";
|
||||
m_journal.debug << " offer: " << offers_direct.tip ();
|
||||
m_journal.debug << " in: " << offers_direct.tip ().amount().in;
|
||||
m_journal.debug << " out: " << offers_direct.tip ().amount ().out;
|
||||
m_journal.debug << " owner: " << offers_direct.tip ().owner ();
|
||||
m_journal.debug << " funds: " << accountFunds(view,
|
||||
j_.debug << count << " Direct:";
|
||||
j_.debug << " offer: " << offers_direct.tip ();
|
||||
j_.debug << " in: " << offers_direct.tip ().amount().in;
|
||||
j_.debug << " out: " << offers_direct.tip ().amount ().out;
|
||||
j_.debug << " owner: " << offers_direct.tip ().owner ();
|
||||
j_.debug << " funds: " << accountFunds(view,
|
||||
offers_direct.tip ().owner (),
|
||||
offers_direct.tip ().amount ().out,
|
||||
fhIGNORE_FREEZE,
|
||||
getConfig());
|
||||
ctx_.config);
|
||||
}
|
||||
|
||||
cross_result = taker.cross(offers_direct.tip ());
|
||||
|
||||
m_journal.debug << "Direct Result: " << transToken (cross_result);
|
||||
j_.debug << "Direct Result: " << transToken (cross_result);
|
||||
|
||||
if (dry_offer (view, offers_direct.tip ()))
|
||||
{
|
||||
@@ -217,36 +208,36 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_journal.debug)
|
||||
if (j_.debug)
|
||||
{
|
||||
auto const owner1_funds_before = accountFunds(view,
|
||||
offers_leg1.tip ().owner (),
|
||||
offers_leg1.tip ().amount ().out,
|
||||
fhIGNORE_FREEZE,
|
||||
getConfig());
|
||||
ctx_.config);
|
||||
|
||||
auto const owner2_funds_before = accountFunds(view,
|
||||
offers_leg2.tip ().owner (),
|
||||
offers_leg2.tip ().amount ().out,
|
||||
fhIGNORE_FREEZE,
|
||||
getConfig());
|
||||
ctx_.config);
|
||||
|
||||
m_journal.debug << count << " Bridge:";
|
||||
m_journal.debug << " offer1: " << offers_leg1.tip ();
|
||||
m_journal.debug << " in: " << offers_leg1.tip ().amount().in;
|
||||
m_journal.debug << " out: " << offers_leg1.tip ().amount ().out;
|
||||
m_journal.debug << " owner: " << offers_leg1.tip ().owner ();
|
||||
m_journal.debug << " funds: " << owner1_funds_before;
|
||||
m_journal.debug << " offer2: " << offers_leg2.tip ();
|
||||
m_journal.debug << " in: " << offers_leg2.tip ().amount ().in;
|
||||
m_journal.debug << " out: " << offers_leg2.tip ().amount ().out;
|
||||
m_journal.debug << " owner: " << offers_leg2.tip ().owner ();
|
||||
m_journal.debug << " funds: " << owner2_funds_before;
|
||||
j_.debug << count << " Bridge:";
|
||||
j_.debug << " offer1: " << offers_leg1.tip ();
|
||||
j_.debug << " in: " << offers_leg1.tip ().amount().in;
|
||||
j_.debug << " out: " << offers_leg1.tip ().amount ().out;
|
||||
j_.debug << " owner: " << offers_leg1.tip ().owner ();
|
||||
j_.debug << " funds: " << owner1_funds_before;
|
||||
j_.debug << " offer2: " << offers_leg2.tip ();
|
||||
j_.debug << " in: " << offers_leg2.tip ().amount ().in;
|
||||
j_.debug << " out: " << offers_leg2.tip ().amount ().out;
|
||||
j_.debug << " owner: " << offers_leg2.tip ().owner ();
|
||||
j_.debug << " funds: " << owner2_funds_before;
|
||||
}
|
||||
|
||||
cross_result = taker.cross(offers_leg1.tip (), offers_leg2.tip ());
|
||||
|
||||
m_journal.debug << "Bridge Result: " << transToken (cross_result);
|
||||
j_.debug << "Bridge Result: " << transToken (cross_result);
|
||||
|
||||
if (dry_offer (view, offers_leg1.tip ()))
|
||||
{
|
||||
@@ -268,7 +259,7 @@ private:
|
||||
|
||||
if (taker.done())
|
||||
{
|
||||
m_journal.debug << "The taker reports he's done during crossing!";
|
||||
j_.debug << "The taker reports he's done during crossing!";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -281,19 +272,19 @@ private:
|
||||
}
|
||||
|
||||
return std::make_pair(cross_result, taker.remaining_offer ());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<TER, Amounts>
|
||||
direct_cross (
|
||||
std::pair<TER, Amounts>
|
||||
CreateOffer::direct_cross (
|
||||
Taker& taker,
|
||||
View& view,
|
||||
View& view_cancel,
|
||||
Clock::time_point const when)
|
||||
{
|
||||
{
|
||||
OfferStream offers (
|
||||
view, view_cancel,
|
||||
Book (taker.issue_in (), taker.issue_out ()),
|
||||
when, m_journal);
|
||||
when, ctx_.config, j_);
|
||||
|
||||
TER cross_result (tesSUCCESS);
|
||||
int count = 0;
|
||||
@@ -313,20 +304,20 @@ private:
|
||||
|
||||
count++;
|
||||
|
||||
if (m_journal.debug)
|
||||
if (j_.debug)
|
||||
{
|
||||
m_journal.debug << count << " Direct:";
|
||||
m_journal.debug << " offer: " << offer;
|
||||
m_journal.debug << " in: " << offer.amount ().in;
|
||||
m_journal.debug << " out: " << offer.amount ().out;
|
||||
m_journal.debug << " owner: " << offer.owner ();
|
||||
m_journal.debug << " funds: " << accountFunds(view,
|
||||
offer.owner (), offer.amount ().out, fhIGNORE_FREEZE, getConfig());
|
||||
j_.debug << count << " Direct:";
|
||||
j_.debug << " offer: " << offer;
|
||||
j_.debug << " in: " << offer.amount ().in;
|
||||
j_.debug << " out: " << offer.amount ().out;
|
||||
j_.debug << " owner: " << offer.owner ();
|
||||
j_.debug << " funds: " << accountFunds(view,
|
||||
offer.owner (), offer.amount ().out, fhIGNORE_FREEZE, ctx_.config);
|
||||
}
|
||||
|
||||
cross_result = taker.cross (offer);
|
||||
|
||||
m_journal.debug << "Direct Result: " << transToken (cross_result);
|
||||
j_.debug << "Direct Result: " << transToken (cross_result);
|
||||
|
||||
if (dry_offer (view, offer))
|
||||
{
|
||||
@@ -342,7 +333,7 @@ private:
|
||||
|
||||
if (taker.done())
|
||||
{
|
||||
m_journal.debug << "The taker reports he's done during crossing!";
|
||||
j_.debug << "The taker reports he's done during crossing!";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -355,15 +346,14 @@ private:
|
||||
}
|
||||
|
||||
return std::make_pair(cross_result, taker.remaining_offer ());
|
||||
}
|
||||
}
|
||||
|
||||
// Step through the stream for as long as possible, skipping any offers
|
||||
// that are from the taker or which cross the taker's threshold.
|
||||
// Return false if the is no offer in the book, true otherwise.
|
||||
static
|
||||
bool
|
||||
step_account (OfferStream& stream, Taker const& taker)
|
||||
{
|
||||
// Step through the stream for as long as possible, skipping any offers
|
||||
// that are from the taker or which cross the taker's threshold.
|
||||
// Return false if the is no offer in the book, true otherwise.
|
||||
bool
|
||||
CreateOffer::step_account (OfferStream& stream, Taker const& taker)
|
||||
{
|
||||
while (stream.step ())
|
||||
{
|
||||
auto const& offer = stream.tip ();
|
||||
@@ -379,25 +369,25 @@ private:
|
||||
|
||||
// We ran out of offers. Can't advance.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill offer as much as possible by consuming offers already on the books,
|
||||
// and adjusting account balances accordingly.
|
||||
//
|
||||
// Charges fees on top to taker.
|
||||
std::pair<TER, Amounts>
|
||||
cross (
|
||||
// Fill offer as much as possible by consuming offers already on the books,
|
||||
// and adjusting account balances accordingly.
|
||||
//
|
||||
// Charges fees on top to taker.
|
||||
std::pair<TER, Amounts>
|
||||
CreateOffer::cross (
|
||||
View& view,
|
||||
View& cancel_view,
|
||||
Amounts const& taker_amount)
|
||||
{
|
||||
{
|
||||
Clock::time_point const when =
|
||||
mEngine->view().time();
|
||||
ctx_.view().parentCloseTime();
|
||||
|
||||
beast::WrappedSink takerSink (m_journal, "Taker ");
|
||||
beast::WrappedSink takerSink (j_, "Taker ");
|
||||
|
||||
Taker taker (cross_type_, view, mTxnAccountID, taker_amount,
|
||||
mTxn.getFlags(), beast::Journal (takerSink));
|
||||
mTxn.getFlags(), ctx_.config, beast::Journal (takerSink));
|
||||
|
||||
try
|
||||
{
|
||||
@@ -408,58 +398,50 @@ private:
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
m_journal.error << "Exception during offer crossing: " << e.what ();
|
||||
j_.error << "Exception during offer crossing: " << e.what ();
|
||||
return std::make_pair (tecINTERNAL, taker.remaining_offer ());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
m_journal.error << "Exception during offer crossing.";
|
||||
j_.error << "Exception during offer crossing.";
|
||||
return std::make_pair (tecINTERNAL, taker.remaining_offer ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
format_amount (STAmount const& amount)
|
||||
{
|
||||
std::string
|
||||
CreateOffer::format_amount (STAmount const& amount)
|
||||
{
|
||||
std::string txt = amount.getText ();
|
||||
txt += "/";
|
||||
txt += to_string (amount.issue().currency);
|
||||
return txt;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
CreateOffer (
|
||||
CrossType cross_type,
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CreateOffer"))
|
||||
, cross_type_ (cross_type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** Returns the reserve the account would have if an offer was added. */
|
||||
STAmount
|
||||
getAccountReserve (SLE::pointer account)
|
||||
{
|
||||
return STAmount (mEngine->view().fees().accountReserve(
|
||||
STAmount
|
||||
CreateOffer::getAccountReserve (SLE::pointer account)
|
||||
{
|
||||
return STAmount (ctx_.view().fees().accountReserve(
|
||||
account->getFieldU32 (sfOwnerCount) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
TER
|
||||
CreateOffer::preCheck ()
|
||||
{
|
||||
cross_type_ = CrossType::IouToIou;
|
||||
bool const pays_xrp =
|
||||
mTxn.getFieldAmount (sfTakerPays).native ();
|
||||
bool const gets_xrp =
|
||||
mTxn.getFieldAmount (sfTakerGets).native ();
|
||||
if (pays_xrp && !gets_xrp)
|
||||
cross_type_ = CrossType::IouToXrp;
|
||||
else if (gets_xrp && !pays_xrp)
|
||||
cross_type_ = CrossType::XrpToIou;
|
||||
|
||||
TER
|
||||
preCheck () override
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfOfferCreateMask)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
@@ -469,7 +451,7 @@ public:
|
||||
|
||||
if (bImmediateOrCancel && bFillOrKill)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"Malformed transaction: both IoC and FoK set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
@@ -478,7 +460,7 @@ public:
|
||||
|
||||
if (bHaveExpiration && (mTxn.getFieldU32 (sfExpiration) == 0))
|
||||
{
|
||||
if (m_journal.debug) m_journal.warning <<
|
||||
if (j_.debug) j_.warning <<
|
||||
"Malformed offer: bad expiration";
|
||||
return temBAD_EXPIRATION;
|
||||
}
|
||||
@@ -487,7 +469,7 @@ public:
|
||||
|
||||
if (bHaveCancel && (mTxn.getFieldU32 (sfOfferSequence) == 0))
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"Malformed offer: bad cancel sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
@@ -500,13 +482,13 @@ public:
|
||||
|
||||
if (saTakerPays.native () && saTakerGets.native ())
|
||||
{
|
||||
if (m_journal.debug) m_journal.warning <<
|
||||
if (j_.debug) j_.warning <<
|
||||
"Malformed offer: XRP for XRP";
|
||||
return temBAD_OFFER;
|
||||
}
|
||||
if (saTakerPays <= zero || saTakerGets <= zero)
|
||||
{
|
||||
if (m_journal.debug) m_journal.warning <<
|
||||
if (j_.debug) j_.warning <<
|
||||
"Malformed offer: bad amount";
|
||||
return temBAD_OFFER;
|
||||
}
|
||||
@@ -519,14 +501,14 @@ public:
|
||||
|
||||
if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"Malformed offer: redundant offer";
|
||||
return temREDUNDANT;
|
||||
}
|
||||
// We don't allow a non-native currency to use the currency code XRP.
|
||||
if (badCurrency() == uPaysCurrency || badCurrency() == uGetsCurrency)
|
||||
{
|
||||
if (m_journal.debug) m_journal.warning <<
|
||||
if (j_.debug) j_.warning <<
|
||||
"Malformed offer: Bad currency.";
|
||||
return temBAD_CURRENCY;
|
||||
}
|
||||
@@ -534,17 +516,17 @@ public:
|
||||
if (saTakerPays.native () != !uPaysIssuerID ||
|
||||
saTakerGets.native () != !uGetsIssuerID)
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
if (j_.warning) j_.warning <<
|
||||
"Malformed offer: bad issuer";
|
||||
return temBAD_ISSUER;
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<TER, bool>
|
||||
applyGuts (View& view, View& view_cancel)
|
||||
{
|
||||
std::pair<TER, bool>
|
||||
CreateOffer::applyGuts (View& view, View& view_cancel)
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
bool const bPassive (uTxFlags & tfPassive);
|
||||
@@ -591,15 +573,15 @@ public:
|
||||
|
||||
if (isGlobalFrozen (view, uPaysIssuerID) || isGlobalFrozen (view, uGetsIssuerID))
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
if (j_.warning) j_.warning <<
|
||||
"Offer involves frozen asset";
|
||||
|
||||
result = tecFROZEN;
|
||||
}
|
||||
else if (accountFunds(view, mTxnAccountID, saTakerGets,
|
||||
fhZERO_IF_FROZEN, getConfig()) <= zero)
|
||||
fhZERO_IF_FROZEN, ctx_.config) <= zero)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"delay: Offers must be at least partially funded.";
|
||||
|
||||
result = tecUNFUNDED_OFFER;
|
||||
@@ -608,7 +590,7 @@ public:
|
||||
// before the transaction sequence number.
|
||||
else if (bHaveCancel && (uAccountSequenceNext - 1 <= uCancelSequence))
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
if (j_.debug) j_.debug <<
|
||||
"uAccountSequenceNext=" << uAccountSequenceNext <<
|
||||
" uOfferSequence=" << uCancelSequence;
|
||||
|
||||
@@ -617,7 +599,7 @@ public:
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
{
|
||||
m_journal.debug << "final result: " << transToken (result);
|
||||
j_.debug << "final result: " << transToken (result);
|
||||
return { result, true };
|
||||
}
|
||||
|
||||
@@ -632,7 +614,7 @@ public:
|
||||
// to fail to delete it.
|
||||
if (sleCancel)
|
||||
{
|
||||
m_journal.debug << "Create cancels order " << uCancelSequence;
|
||||
j_.debug << "Create cancels order " << uCancelSequence;
|
||||
result = offerDelete (view, sleCancel);
|
||||
}
|
||||
}
|
||||
@@ -641,7 +623,7 @@ public:
|
||||
// because we definitively know the time that it closed but we do not
|
||||
// know the closing time of the ledger that is under construction.
|
||||
if (bHaveExpiration &&
|
||||
(mEngine->view().time() >= uExpiration))
|
||||
(ctx_.view().parentCloseTime() >= uExpiration))
|
||||
{
|
||||
return { tesSUCCESS, true };
|
||||
}
|
||||
@@ -650,7 +632,8 @@ public:
|
||||
if (result == tesSUCCESS && !saTakerPays.native ())
|
||||
result = checkAcceptAsset (Issue (uPaysCurrency, uPaysIssuerID));
|
||||
|
||||
bool const bOpenLedger (mParams & tapOPEN_LEDGER);
|
||||
bool const bOpenLedger =
|
||||
ctx_.view().open();
|
||||
bool crossed = false;
|
||||
|
||||
if (result == tesSUCCESS)
|
||||
@@ -663,27 +646,27 @@ public:
|
||||
// empty (fully crossed), or something in-between.
|
||||
Amounts place_offer;
|
||||
|
||||
m_journal.debug << "Attempting cross: " <<
|
||||
j_.debug << "Attempting cross: " <<
|
||||
to_string (taker_amount.in.issue ()) << " -> " <<
|
||||
to_string (taker_amount.out.issue ());
|
||||
|
||||
if (m_journal.trace)
|
||||
if (j_.trace)
|
||||
{
|
||||
m_journal.debug << " mode: " <<
|
||||
j_.debug << " mode: " <<
|
||||
(bPassive ? "passive " : "") <<
|
||||
(bSell ? "sell" : "buy");
|
||||
m_journal.trace <<" in: " << format_amount (taker_amount.in);
|
||||
m_journal.trace << " out: " << format_amount (taker_amount.out);
|
||||
j_.trace <<" in: " << format_amount (taker_amount.in);
|
||||
j_.trace << " out: " << format_amount (taker_amount.out);
|
||||
}
|
||||
|
||||
std::tie(result, place_offer) = cross (view, view_cancel, taker_amount);
|
||||
assert (result != tefINTERNAL);
|
||||
|
||||
if (m_journal.trace)
|
||||
if (j_.trace)
|
||||
{
|
||||
m_journal.trace << "Cross result: " << transToken (result);
|
||||
m_journal.trace << " in: " << format_amount (place_offer.in);
|
||||
m_journal.trace << " out: " << format_amount (place_offer.out);
|
||||
j_.trace << "Cross result: " << transToken (result);
|
||||
j_.trace << " in: " << format_amount (place_offer.in);
|
||||
j_.trace << " out: " << format_amount (place_offer.out);
|
||||
}
|
||||
|
||||
if (result == tecFAILED_PROCESSING && bOpenLedger)
|
||||
@@ -691,7 +674,7 @@ public:
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
{
|
||||
m_journal.debug << "final result: " << transToken (result);
|
||||
j_.debug << "final result: " << transToken (result);
|
||||
return { result, true };
|
||||
}
|
||||
|
||||
@@ -705,7 +688,7 @@ public:
|
||||
// never be negative. If it is, something went very very wrong.
|
||||
if (place_offer.in < zero || place_offer.out < zero)
|
||||
{
|
||||
m_journal.fatal << "Cross left offer negative!" <<
|
||||
j_.fatal << "Cross left offer negative!" <<
|
||||
" in: " << format_amount (place_offer.in) <<
|
||||
" out: " << format_amount (place_offer.out);
|
||||
return { tefINTERNAL, true };
|
||||
@@ -713,7 +696,7 @@ public:
|
||||
|
||||
if (place_offer.in == zero || place_offer.out == zero)
|
||||
{
|
||||
m_journal.debug << "Offer fully crossed!";
|
||||
j_.debug << "Offer fully crossed!";
|
||||
return { result, true };
|
||||
}
|
||||
|
||||
@@ -728,22 +711,22 @@ public:
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
{
|
||||
m_journal.debug << "final result: " << transToken (result);
|
||||
j_.debug << "final result: " << transToken (result);
|
||||
return { result, true };
|
||||
}
|
||||
|
||||
if (m_journal.trace)
|
||||
if (j_.trace)
|
||||
{
|
||||
m_journal.trace << "Place" << (crossed ? " remaining " : " ") << "offer:";
|
||||
m_journal.trace << " Pays: " << saTakerPays.getFullText ();
|
||||
m_journal.trace << " Gets: " << saTakerGets.getFullText ();
|
||||
j_.trace << "Place" << (crossed ? " remaining " : " ") << "offer:";
|
||||
j_.trace << " Pays: " << saTakerPays.getFullText ();
|
||||
j_.trace << " Gets: " << saTakerGets.getFullText ();
|
||||
}
|
||||
|
||||
// For 'fill or kill' offers, failure to fully cross means that the
|
||||
// entire operation should be aborted, with only fees paid.
|
||||
if (bFillOrKill)
|
||||
{
|
||||
m_journal.trace << "Fill or Kill: offer killed";
|
||||
j_.trace << "Fill or Kill: offer killed";
|
||||
return { tesSUCCESS, false };
|
||||
}
|
||||
|
||||
@@ -751,7 +734,7 @@ public:
|
||||
// placed - it gets cancelled and the operation succeeds.
|
||||
if (bImmediateOrCancel)
|
||||
{
|
||||
m_journal.trace << "Immediate or cancel: offer cancelled";
|
||||
j_.trace << "Immediate or cancel: offer cancelled";
|
||||
return { tesSUCCESS, true };
|
||||
}
|
||||
|
||||
@@ -764,7 +747,7 @@ public:
|
||||
result = tecINSUF_RESERVE_OFFER;
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
m_journal.debug << "final result: " << transToken (result);
|
||||
j_.debug << "final result: " << transToken (result);
|
||||
|
||||
return { result, true };
|
||||
}
|
||||
@@ -788,7 +771,7 @@ public:
|
||||
// Update owner count.
|
||||
adjustOwnerCount(view, sleCreator, 1);
|
||||
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"adding to book: " << to_string (saTakerPays.issue ()) <<
|
||||
" : " << to_string (saTakerGets.issue ());
|
||||
|
||||
@@ -827,46 +810,26 @@ public:
|
||||
}
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
m_journal.debug << "final result: " << transToken (result);
|
||||
j_.debug << "final result: " << transToken (result);
|
||||
|
||||
return { result, true };
|
||||
}
|
||||
|
||||
TER
|
||||
doApply() override
|
||||
{
|
||||
// This is the ledger view that we work against. Transactions are applied
|
||||
// as we go on processing transactions.
|
||||
MetaView view (&mEngine->view());
|
||||
// This is a checkpoint with just the fees paid. If something goes wrong
|
||||
// with this transaction, we roll back to this ledger.
|
||||
MetaView viewCancel (&mEngine->view());
|
||||
auto const result = applyGuts(view, viewCancel);
|
||||
if (result.second)
|
||||
view.apply(mEngine->view());
|
||||
else
|
||||
viewCancel.apply(mEngine->view());
|
||||
return result.first;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TER
|
||||
transact_CreateOffer (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
CreateOffer::doApply()
|
||||
{
|
||||
CrossType cross_type = CrossType::IouToIou;
|
||||
|
||||
bool const pays_xrp = txn.getFieldAmount (sfTakerPays).native ();
|
||||
bool const gets_xrp = txn.getFieldAmount (sfTakerGets).native ();
|
||||
|
||||
if (pays_xrp && !gets_xrp)
|
||||
cross_type = CrossType::IouToXrp;
|
||||
else if (gets_xrp && !pays_xrp)
|
||||
cross_type = CrossType::XrpToIou;
|
||||
|
||||
return CreateOffer (cross_type, txn, params, engine).apply ();
|
||||
// This is the ledger view that we work against. Transactions are applied
|
||||
// as we go on processing transactions.
|
||||
MetaView view (ctx_.view(), ctx_.view().flags());
|
||||
// This is a checkpoint with just the fees paid. If something goes wrong
|
||||
// with this transaction, we roll back to this ledger.
|
||||
MetaView viewCancel (ctx_.view(), ctx_.view().flags());
|
||||
auto const result = applyGuts(view, viewCancel);
|
||||
if (result.second)
|
||||
view.apply(ctx_.view());
|
||||
else
|
||||
viewCancel.apply(ctx_.view());
|
||||
return result.first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
119
src/ripple/app/tx/impl/CreateOffer.h
Normal file
119
src/ripple/app/tx/impl/CreateOffer.h
Normal file
@@ -0,0 +1,119 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CREATEOFFER_H_INCLUDED
|
||||
#define RIPPLE_TX_CREATEOFFER_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/tx/impl/OfferStream.h>
|
||||
#include <ripple/app/tx/impl/Taker.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <beast/cxx14/memory.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/WrappedSink.h>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateOffer
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
CreateOffer (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns the reserve the account would have if an offer was added. */
|
||||
// VFALCO This function is not needed just inline the behavior
|
||||
STAmount
|
||||
getAccountReserve (SLE::pointer account); // const?
|
||||
|
||||
TER
|
||||
preCheck () override;
|
||||
|
||||
std::pair<TER, bool>
|
||||
applyGuts (View& view, View& view_cancel);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
private:
|
||||
/** Determine if we are authorized to hold the asset we want to get */
|
||||
TER
|
||||
checkAcceptAsset(IssueRef issue) const;
|
||||
|
||||
bool
|
||||
dry_offer (View& view, Offer const& offer);
|
||||
|
||||
static
|
||||
std::pair<bool, Quality>
|
||||
select_path (
|
||||
bool have_direct, OfferStream const& direct,
|
||||
bool have_bridge, OfferStream const& leg1, OfferStream const& leg2);
|
||||
|
||||
std::pair<TER, Amounts>
|
||||
bridged_cross (
|
||||
Taker& taker,
|
||||
View& view,
|
||||
View& view_cancel,
|
||||
Clock::time_point const when);
|
||||
|
||||
std::pair<TER, Amounts>
|
||||
direct_cross (
|
||||
Taker& taker,
|
||||
View& view,
|
||||
View& view_cancel,
|
||||
Clock::time_point const when);
|
||||
|
||||
// Step through the stream for as long as possible, skipping any offers
|
||||
// that are from the taker or which cross the taker's threshold.
|
||||
// Return false if the is no offer in the book, true otherwise.
|
||||
static
|
||||
bool
|
||||
step_account (OfferStream& stream, Taker const& taker);
|
||||
|
||||
// Fill offer as much as possible by consuming offers already on the books,
|
||||
// and adjusting account balances accordingly.
|
||||
//
|
||||
// Charges fees on top to taker.
|
||||
std::pair<TER, Amounts>
|
||||
cross (
|
||||
View& view,
|
||||
View& cancel_view,
|
||||
Amounts const& taker_amount);
|
||||
|
||||
static
|
||||
std::string
|
||||
format_amount (STAmount const& amount);
|
||||
|
||||
private:
|
||||
// What kind of offer we are placing
|
||||
CrossType cross_type_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,55 +18,44 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/tx/impl/CreateTicket.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateTicket
|
||||
: public Transactor
|
||||
TER
|
||||
CreateTicket::preCheck ()
|
||||
{
|
||||
public:
|
||||
CreateTicket (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CreateTicket"))
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_TICKETS
|
||||
if (! (view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
TER
|
||||
preCheck () override
|
||||
{
|
||||
if (mTxn.isFieldPresent (sfExpiration))
|
||||
{
|
||||
if (mTxn.getFieldU32 (sfExpiration) == 0)
|
||||
{
|
||||
m_journal.warning <<
|
||||
j_.warning <<
|
||||
"Malformed transaction: bad expiration";
|
||||
return temBAD_EXPIRATION;
|
||||
}
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the reserve the account would have if an offer was added. */
|
||||
STAmount
|
||||
getAccountReserve (SLE::pointer account)
|
||||
{
|
||||
return STAmount (mEngine->view().fees().accountReserve(
|
||||
STAmount
|
||||
CreateTicket::getAccountReserve (SLE::pointer account)
|
||||
{
|
||||
return STAmount (view().fees().accountReserve(
|
||||
account->getFieldU32 (sfOwnerCount) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
CreateTicket::doApply ()
|
||||
{
|
||||
assert (mTxnAccount);
|
||||
|
||||
// A ticket counts against the reserve of the issuing account, but we
|
||||
@@ -81,7 +70,7 @@ public:
|
||||
{
|
||||
expiration = mTxn.getFieldU32 (sfExpiration);
|
||||
|
||||
if (mEngine->view().time() >= expiration)
|
||||
if (view().parentCloseTime() >= expiration)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -91,13 +80,13 @@ public:
|
||||
sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ());
|
||||
if (expiration != 0)
|
||||
sleTicket->setFieldU32 (sfExpiration, expiration);
|
||||
mEngine->view().insert (sleTicket);
|
||||
view().insert (sleTicket);
|
||||
|
||||
if (mTxn.isFieldPresent (sfTarget))
|
||||
{
|
||||
AccountID const target_account (mTxn.getAccountID (sfTarget));
|
||||
|
||||
SLE::pointer sleTarget = mEngine->view().peek (keylet::account(target_account));
|
||||
SLE::pointer sleTarget = view().peek (keylet::account(target_account));
|
||||
|
||||
// Destination account does not exist.
|
||||
if (!sleTarget)
|
||||
@@ -116,13 +105,13 @@ public:
|
||||
ownerDirDescriber(p, b, mTxnAccountID);
|
||||
};
|
||||
|
||||
TER result = dirAdd(mEngine->view(),
|
||||
TER result = dirAdd(view(),
|
||||
hint,
|
||||
getOwnerDirIndex (mTxnAccountID),
|
||||
sleTicket->getIndex (),
|
||||
describer);
|
||||
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Creating ticket " << to_string (sleTicket->getIndex ()) <<
|
||||
": " << transHuman (result);
|
||||
|
||||
@@ -132,23 +121,9 @@ public:
|
||||
sleTicket->setFieldU64(sfOwnerNode, hint);
|
||||
|
||||
// If we succeeded, the new entry counts agains the creator's reserve.
|
||||
adjustOwnerCount(mEngine->view(), mTxnAccount, 1);
|
||||
adjustOwnerCount(view(), mTxnAccount, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_CreateTicket (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_TICKETS
|
||||
if (! (engine->view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
return CreateTicket (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
54
src/ripple/app/tx/impl/CreateTicket.h
Normal file
54
src/ripple/app/tx/impl/CreateTicket.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2014 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CREATETICKET_H_INCLUDED
|
||||
#define RIPPLE_TX_CREATETICKET_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateTicket
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
CreateTicket (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER
|
||||
preCheck () override;
|
||||
|
||||
/** Returns the reserve the account would have if an offer was added. */
|
||||
// VFALCO Not needed, just inline the behavior.
|
||||
STAmount
|
||||
getAccountReserve (SLE::pointer account);
|
||||
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,13 +23,15 @@
|
||||
namespace ripple {
|
||||
|
||||
OfferStream::OfferStream (View& view, View& view_cancel,
|
||||
BookRef book, Clock::time_point when, beast::Journal journal)
|
||||
: m_journal (journal)
|
||||
BookRef book, Clock::time_point when,
|
||||
Config const& config, beast::Journal journal)
|
||||
: j_ (journal)
|
||||
, m_view (view)
|
||||
, m_view_cancel (view_cancel)
|
||||
, m_book (book)
|
||||
, m_when (when)
|
||||
, m_tip (view, book)
|
||||
, config_ (config)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@ OfferStream::erase (View& view)
|
||||
|
||||
if (p == nullptr)
|
||||
{
|
||||
if (m_journal.error) m_journal.error <<
|
||||
if (j_.error) j_.error <<
|
||||
"Missing directory " << m_tip.dir() <<
|
||||
" for offer " << m_tip.index();
|
||||
return;
|
||||
@@ -57,7 +59,7 @@ OfferStream::erase (View& view)
|
||||
|
||||
if (it == v.end())
|
||||
{
|
||||
if (m_journal.error) m_journal.error <<
|
||||
if (j_.error) j_.error <<
|
||||
"Missing offer " << m_tip.index() <<
|
||||
" for directory " << m_tip.dir();
|
||||
return;
|
||||
@@ -67,7 +69,7 @@ OfferStream::erase (View& view)
|
||||
p->setFieldV256 (sfIndexes, v);
|
||||
view.update (p);
|
||||
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Missing offer " << m_tip.index() <<
|
||||
" removed from directory " << m_tip.dir();
|
||||
}
|
||||
@@ -99,7 +101,7 @@ OfferStream::step ()
|
||||
if (entry->isFieldPresent (sfExpiration) &&
|
||||
entry->getFieldU32 (sfExpiration) <= m_when)
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Removing expired offer " << entry->getIndex();
|
||||
offerDelete (view_cancel(),
|
||||
view_cancel().peek(
|
||||
@@ -114,7 +116,7 @@ OfferStream::step ()
|
||||
// Remove if either amount is zero
|
||||
if (amount.empty())
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
if (j_.warning) j_.warning <<
|
||||
"Removing bad offer " << entry->getIndex();
|
||||
offerDelete (view_cancel(),
|
||||
view_cancel().peek(
|
||||
@@ -128,7 +130,7 @@ OfferStream::step ()
|
||||
// looking up the funds twice?
|
||||
auto const owner_funds = accountFunds(view(),
|
||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN,
|
||||
getConfig());
|
||||
config_);
|
||||
|
||||
// Check for unfunded offer
|
||||
if (owner_funds <= zero)
|
||||
@@ -138,18 +140,18 @@ OfferStream::step ()
|
||||
// offer is "found unfunded" versus "became unfunded"
|
||||
auto const original_funds = accountFunds(view_cancel(),
|
||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN,
|
||||
getConfig());
|
||||
config_);
|
||||
|
||||
if (original_funds == owner_funds)
|
||||
{
|
||||
offerDelete (view_cancel(), view_cancel().peek(
|
||||
keylet::offer(entry->key())));
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Removing unfunded offer " << entry->getIndex();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Removing became unfunded offer " << entry->getIndex();
|
||||
}
|
||||
m_offer = Offer{};
|
||||
|
||||
@@ -50,20 +50,23 @@ namespace ripple {
|
||||
class OfferStream
|
||||
{
|
||||
private:
|
||||
beast::Journal m_journal;
|
||||
beast::Journal j_;
|
||||
std::reference_wrapper <View> m_view;
|
||||
std::reference_wrapper <View> m_view_cancel;
|
||||
Book m_book;
|
||||
Clock::time_point m_when;
|
||||
BookTip m_tip;
|
||||
Offer m_offer;
|
||||
Config const& config_;
|
||||
|
||||
void
|
||||
erase (View& view);
|
||||
|
||||
public:
|
||||
OfferStream (View& view, View& view_cancel, BookRef book,
|
||||
Clock::time_point when, beast::Journal journal);
|
||||
OfferStream (View& view, View& view_cancel,
|
||||
BookRef book, Clock::time_point when,
|
||||
Config const& config,
|
||||
beast::Journal journal);
|
||||
|
||||
View&
|
||||
view () noexcept
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Payment.h>
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
@@ -27,36 +27,14 @@ namespace ripple {
|
||||
|
||||
// See https://ripple.com/wiki/Transaction_Format#Payment_.280.29
|
||||
|
||||
class Payment
|
||||
: public Transactor
|
||||
TER
|
||||
Payment::preCheck ()
|
||||
{
|
||||
/* The largest number of paths we allow */
|
||||
static std::size_t const MaxPathSize = 6;
|
||||
|
||||
/* The longest path we allow */
|
||||
static std::size_t const MaxPathLength = 8;
|
||||
|
||||
public:
|
||||
Payment (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Payment"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfPaymentMask)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
@@ -94,25 +72,25 @@ public:
|
||||
|
||||
if (!uDstAccountID)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Payment destination account not specified.";
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
if (bMax && maxSourceAmount <= zero)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"bad max amount: " << maxSourceAmount.getFullText ();
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
if (saDstAmount <= zero)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: "<<
|
||||
j_.trace << "Malformed transaction: "<<
|
||||
"bad dst amount: " << saDstAmount.getFullText ();
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
|
||||
{
|
||||
m_journal.trace <<"Malformed transaction: " <<
|
||||
j_.trace <<"Malformed transaction: " <<
|
||||
"Bad currency.";
|
||||
return temBAD_CURRENCY;
|
||||
}
|
||||
@@ -120,7 +98,7 @@ public:
|
||||
{
|
||||
// You're signing yourself a payment.
|
||||
// If bPaths is true, you might be trying some arbitrage.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Redundant payment from " << to_string (mTxnAccountID) <<
|
||||
" to self without path for " << to_string (uDstCurrency);
|
||||
return temREDUNDANT;
|
||||
@@ -128,44 +106,45 @@ public:
|
||||
if (bXRPDirect && bMax)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"SendMax specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_MAX;
|
||||
}
|
||||
if (bXRPDirect && bPaths)
|
||||
{
|
||||
// XRP is sent without paths.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Paths specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_PATHS;
|
||||
}
|
||||
if (bXRPDirect && partialPaymentAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Partial payment specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_PARTIAL;
|
||||
}
|
||||
if (bXRPDirect && limitQuality)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"Limit quality specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_LIMIT;
|
||||
}
|
||||
if (bXRPDirect && !defaultPathsAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace << "Malformed transaction: " <<
|
||||
j_.trace << "Malformed transaction: " <<
|
||||
"No ripple direct specified for XRP to XRP.";
|
||||
return temBAD_SEND_XRP_NO_DIRECT;
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
Payment::doApply ()
|
||||
{
|
||||
// Ripple if source or destination is non-native or if there are paths.
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
|
||||
@@ -186,31 +165,32 @@ public:
|
||||
saDstAmount.mantissa(), saDstAmount.exponent (),
|
||||
saDstAmount < zero);
|
||||
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"maxSourceAmount=" << maxSourceAmount.getFullText () <<
|
||||
" saDstAmount=" << saDstAmount.getFullText ();
|
||||
|
||||
// Open a ledger for editing.
|
||||
auto const k = keylet::account(uDstAccountID);
|
||||
SLE::pointer sleDst = mEngine->view().peek (k);
|
||||
SLE::pointer sleDst = view().peek (k);
|
||||
|
||||
if (!sleDst)
|
||||
{
|
||||
// Destination account does not exist.
|
||||
if (!saDstAmount.native ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return tecNO_DST;
|
||||
}
|
||||
else if (mParams & tapOPEN_LEDGER && partialPaymentAllowed)
|
||||
else if (view().open()
|
||||
&& partialPaymentAllowed)
|
||||
{
|
||||
// You cannot fund an account with a partial payment.
|
||||
// Make retry work smaller, by rejecting this.
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Partial payment not allowed to create account.";
|
||||
|
||||
|
||||
@@ -218,11 +198,11 @@ public:
|
||||
// transaction would succeed.
|
||||
return telNO_DST_PARTIAL;
|
||||
}
|
||||
else if (saDstAmount < STAmount (mEngine->view().fees().accountReserve(0)))
|
||||
else if (saDstAmount < STAmount (view().fees().accountReserve(0)))
|
||||
{
|
||||
// getReserve() is the minimum amount that an account can have.
|
||||
// Reserve is not scaled by load.
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Destination account does not exist. " <<
|
||||
"Insufficent payment to create account.";
|
||||
|
||||
@@ -236,7 +216,7 @@ public:
|
||||
sleDst = std::make_shared<SLE>(k);
|
||||
sleDst->setAccountID (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
mEngine->view().insert(sleDst);
|
||||
view().insert(sleDst);
|
||||
}
|
||||
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
||||
!mTxn.isFieldPresent (sfDestinationTag))
|
||||
@@ -246,7 +226,7 @@ public:
|
||||
|
||||
// We didn't make this test for a newly-formed account because there's
|
||||
// no way for this field to be set.
|
||||
m_journal.trace << "Malformed transaction: DestinationTag required.";
|
||||
j_.trace << "Malformed transaction: DestinationTag required.";
|
||||
|
||||
return tecDST_TAG_NEEDED;
|
||||
}
|
||||
@@ -255,7 +235,7 @@ public:
|
||||
// Tell the engine that we are intending to change the the destination
|
||||
// account. The source account gets always charged a fee so it's always
|
||||
// marked as modified.
|
||||
mEngine->view().update (sleDst);
|
||||
view().update (sleDst);
|
||||
}
|
||||
|
||||
TER terResult;
|
||||
@@ -278,7 +258,7 @@ public:
|
||||
rcInput.defaultPathsAllowed = defaultPathsAllowed;
|
||||
rcInput.limitQuality = limitQuality;
|
||||
rcInput.deleteUnfundedOffers = true;
|
||||
rcInput.isLedgerOpen = static_cast<bool>(mParams & tapOPEN_LEDGER);
|
||||
rcInput.isLedgerOpen = view().open();
|
||||
|
||||
bool pathTooBig = spsPaths.size () > MaxPathSize;
|
||||
|
||||
@@ -294,9 +274,9 @@ public:
|
||||
{
|
||||
path::RippleCalc::Output rc;
|
||||
{
|
||||
PaymentView view (&mEngine->view());
|
||||
PaymentView pv (view(), view().flags());
|
||||
rc = path::RippleCalc::rippleCalculate (
|
||||
view,
|
||||
pv,
|
||||
maxSourceAmount,
|
||||
saDstAmount,
|
||||
uDstAccountID,
|
||||
@@ -306,13 +286,13 @@ public:
|
||||
// VFALCO NOTE We might not need to apply, depending
|
||||
// on the TER. But always applying *should*
|
||||
// be safe.
|
||||
view.apply(mEngine->view());
|
||||
pv.apply(view());
|
||||
}
|
||||
|
||||
// TODO: is this right? If the amount is the correct amount, was
|
||||
// the delivered amount previously set?
|
||||
if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount)
|
||||
mEngine->deliverAmount (rc.actualAmountOut);
|
||||
ctx_.deliverAmount (rc.actualAmountOut);
|
||||
|
||||
terResult = rc.result ();
|
||||
}
|
||||
@@ -324,7 +304,7 @@ public:
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Caught throw: " << e.what ();
|
||||
|
||||
terResult = tefEXCEPTION;
|
||||
@@ -340,7 +320,7 @@ public:
|
||||
|
||||
// This is the total reserve in drops.
|
||||
auto const uReserve =
|
||||
mEngine->view().fees().accountReserve(uOwnerCount);
|
||||
view().fees().accountReserve(uOwnerCount);
|
||||
|
||||
// mPriorBalance is the balance on the sending account BEFORE the
|
||||
// fees were charged. We want to make sure we have enough reserve
|
||||
@@ -352,7 +332,7 @@ public:
|
||||
{
|
||||
// Vote no. However the transaction might succeed, if applied in
|
||||
// a different order.
|
||||
m_journal.trace << "Delay transaction: Insufficient funds: " <<
|
||||
j_.trace << "Delay transaction: Insufficient funds: " <<
|
||||
" " << mPriorBalance.getText () <<
|
||||
" / " << (saDstAmount + mmm).getText () <<
|
||||
" (" << uReserve << ")";
|
||||
@@ -381,7 +361,7 @@ public:
|
||||
|
||||
if (transResultInfo (terResult, strToken, strHuman))
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
strToken << ": " << strHuman;
|
||||
}
|
||||
else
|
||||
@@ -390,16 +370,6 @@ public:
|
||||
}
|
||||
|
||||
return terResult;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_Payment (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return Payment(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
55
src/ripple/app/tx/impl/Payment.h
Normal file
55
src/ripple/app/tx/impl/Payment.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_PAYMENT_H_INCLUDED
|
||||
#define RIPPLE_TX_PAYMENT_H_INCLUDED
|
||||
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// See https://ripple.com/wiki/Transaction_Format#Payment_.280.29
|
||||
|
||||
class Payment
|
||||
: public Transactor
|
||||
{
|
||||
/* The largest number of paths we allow */
|
||||
static std::size_t const MaxPathSize = 6;
|
||||
|
||||
/* The longest path we allow */
|
||||
static std::size_t const MaxPathLength = 8;
|
||||
|
||||
public:
|
||||
template <class... Args>
|
||||
Payment (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override;
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/SetAccount.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
@@ -27,33 +27,14 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetAccount
|
||||
: public Transactor
|
||||
TER
|
||||
SetAccount::preCheck ()
|
||||
{
|
||||
static std::size_t const DOMAIN_BYTES_MAX = 256;
|
||||
static std::size_t const PUBLIC_BYTES_MAX = 33;
|
||||
|
||||
public:
|
||||
SetAccount (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetAccount"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfAccountSetMask)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Invalid flags set.";
|
||||
j_.trace << "Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
@@ -62,7 +43,7 @@ public:
|
||||
|
||||
if ((uSetFlag != 0) && (uSetFlag == uClearFlag))
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Set and clear same flag.";
|
||||
j_.trace << "Malformed transaction: Set and clear same flag.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
@@ -74,7 +55,7 @@ public:
|
||||
|
||||
if (bSetRequireAuth && bClearRequireAuth)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
j_.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
@@ -86,7 +67,7 @@ public:
|
||||
|
||||
if (bSetRequireDest && bClearRequireDest)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
j_.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
@@ -98,7 +79,7 @@ public:
|
||||
|
||||
if (bSetDisallowXRP && bClearDisallowXRP)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
j_.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
@@ -109,16 +90,17 @@ public:
|
||||
|
||||
if (uRate && (uRate < QUALITY_ONE))
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Bad transfer rate.";
|
||||
j_.trace << "Malformed transaction: Bad transfer rate.";
|
||||
return temBAD_TRANSFER_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
SetAccount::doApply ()
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
|
||||
@@ -140,20 +122,20 @@ public:
|
||||
//
|
||||
if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
if (! dirIsEmpty (mEngine->view(),
|
||||
if (! dirIsEmpty (view(),
|
||||
keylet::ownerDir(mTxnAccountID)))
|
||||
{
|
||||
m_journal.trace << "Retry: Owner directory not empty.";
|
||||
return (mParams & tapRETRY) ? terOWNERS : tecOWNERS;
|
||||
j_.trace << "Retry: Owner directory not empty.";
|
||||
return (view().flags() & tapRETRY) ? terOWNERS : tecOWNERS;
|
||||
}
|
||||
|
||||
m_journal.trace << "Set RequireAuth.";
|
||||
j_.trace << "Set RequireAuth.";
|
||||
uFlagsOut |= lsfRequireAuth;
|
||||
}
|
||||
|
||||
if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
m_journal.trace << "Clear RequireAuth.";
|
||||
j_.trace << "Clear RequireAuth.";
|
||||
uFlagsOut &= ~lsfRequireAuth;
|
||||
}
|
||||
|
||||
@@ -162,13 +144,13 @@ public:
|
||||
//
|
||||
if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Set lsfRequireDestTag.";
|
||||
j_.trace << "Set lsfRequireDestTag.";
|
||||
uFlagsOut |= lsfRequireDestTag;
|
||||
}
|
||||
|
||||
if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Clear lsfRequireDestTag.";
|
||||
j_.trace << "Clear lsfRequireDestTag.";
|
||||
uFlagsOut &= ~lsfRequireDestTag;
|
||||
}
|
||||
|
||||
@@ -177,13 +159,13 @@ public:
|
||||
//
|
||||
if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Set lsfDisallowXRP.";
|
||||
j_.trace << "Set lsfDisallowXRP.";
|
||||
uFlagsOut |= lsfDisallowXRP;
|
||||
}
|
||||
|
||||
if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisallowXRP.";
|
||||
j_.trace << "Clear lsfDisallowXRP.";
|
||||
uFlagsOut &= ~lsfDisallowXRP;
|
||||
}
|
||||
|
||||
@@ -194,20 +176,20 @@ public:
|
||||
{
|
||||
if (!mSigMaster)
|
||||
{
|
||||
m_journal.trace << "Must use master key to disable master key.";
|
||||
j_.trace << "Must use master key to disable master key.";
|
||||
return tecNEED_MASTER_KEY;
|
||||
}
|
||||
|
||||
if (!mTxnAccount->isFieldPresent (sfRegularKey))
|
||||
return tecNO_REGULAR_KEY;
|
||||
|
||||
m_journal.trace << "Set lsfDisableMaster.";
|
||||
j_.trace << "Set lsfDisableMaster.";
|
||||
uFlagsOut |= lsfDisableMaster;
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisableMaster.";
|
||||
j_.trace << "Clear lsfDisableMaster.";
|
||||
uFlagsOut &= ~lsfDisableMaster;
|
||||
}
|
||||
|
||||
@@ -230,18 +212,18 @@ public:
|
||||
{
|
||||
if (!mSigMaster && !(uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Can't use regular key to set NoFreeze.";
|
||||
j_.trace << "Can't use regular key to set NoFreeze.";
|
||||
return tecNEED_MASTER_KEY;
|
||||
}
|
||||
|
||||
m_journal.trace << "Set NoFreeze flag";
|
||||
j_.trace << "Set NoFreeze flag";
|
||||
uFlagsOut |= lsfNoFreeze;
|
||||
}
|
||||
|
||||
// Anyone may set global freeze
|
||||
if (uSetFlag == asfGlobalFreeze)
|
||||
{
|
||||
m_journal.trace << "Set GlobalFreeze flag";
|
||||
j_.trace << "Set GlobalFreeze flag";
|
||||
uFlagsOut |= lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
@@ -251,7 +233,7 @@ public:
|
||||
if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
|
||||
((uFlagsOut & lsfNoFreeze) == 0))
|
||||
{
|
||||
m_journal.trace << "Clear GlobalFreeze flag";
|
||||
j_.trace << "Clear GlobalFreeze flag";
|
||||
uFlagsOut &= ~lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
@@ -260,13 +242,13 @@ public:
|
||||
//
|
||||
if ((uSetFlag == asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Set AccountTxnID";
|
||||
j_.trace << "Set AccountTxnID";
|
||||
mTxnAccount->makeFieldPresent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Clear AccountTxnID";
|
||||
j_.trace << "Clear AccountTxnID";
|
||||
mTxnAccount->makeFieldAbsent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
@@ -279,12 +261,12 @@ public:
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
m_journal.trace << "unset email hash";
|
||||
j_.trace << "unset email hash";
|
||||
mTxnAccount->makeFieldAbsent (sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set email hash";
|
||||
j_.trace << "set email hash";
|
||||
mTxnAccount->setFieldH128 (sfEmailHash, uHash);
|
||||
}
|
||||
}
|
||||
@@ -298,12 +280,12 @@ public:
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
m_journal.trace << "unset wallet locator";
|
||||
j_.trace << "unset wallet locator";
|
||||
mTxnAccount->makeFieldAbsent (sfWalletLocator);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set wallet locator";
|
||||
j_.trace << "set wallet locator";
|
||||
mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
|
||||
}
|
||||
}
|
||||
@@ -317,18 +299,18 @@ public:
|
||||
|
||||
if (messageKey.size () > PUBLIC_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "message key too long";
|
||||
j_.trace << "message key too long";
|
||||
return telBAD_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
if (messageKey.empty ())
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
j_.debug << "set message key";
|
||||
mTxnAccount->makeFieldAbsent (sfMessageKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
j_.debug << "set message key";
|
||||
mTxnAccount->setFieldVL (sfMessageKey, messageKey);
|
||||
}
|
||||
}
|
||||
@@ -342,18 +324,18 @@ public:
|
||||
|
||||
if (domain.size () > DOMAIN_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "domain too long";
|
||||
j_.trace << "domain too long";
|
||||
return telBAD_DOMAIN;
|
||||
}
|
||||
|
||||
if (domain.empty ())
|
||||
{
|
||||
m_journal.trace << "unset domain";
|
||||
j_.trace << "unset domain";
|
||||
mTxnAccount->makeFieldAbsent (sfDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set domain";
|
||||
j_.trace << "set domain";
|
||||
mTxnAccount->setFieldVL (sfDomain, domain);
|
||||
}
|
||||
}
|
||||
@@ -367,12 +349,12 @@ public:
|
||||
|
||||
if (uRate == 0 || uRate == QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "unset transfer rate";
|
||||
j_.trace << "unset transfer rate";
|
||||
mTxnAccount->makeFieldAbsent (sfTransferRate);
|
||||
}
|
||||
else if (uRate > QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "set transfer rate";
|
||||
j_.trace << "set transfer rate";
|
||||
mTxnAccount->setFieldU32 (sfTransferRate, uRate);
|
||||
}
|
||||
}
|
||||
@@ -381,16 +363,6 @@ public:
|
||||
mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_SetAccount (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return SetAccount(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
52
src/ripple/app/tx/impl/SetAccount.h
Normal file
52
src/ripple/app/tx/impl/SetAccount.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_SETACCOUNT_H_INCLUDED
|
||||
#define RIPPLE_TX_SETACCOUNT_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetAccount
|
||||
: public Transactor
|
||||
{
|
||||
static std::size_t const DOMAIN_BYTES_MAX = 256;
|
||||
static std::size_t const PUBLIC_BYTES_MAX = 33;
|
||||
|
||||
public:
|
||||
template <class... Args>
|
||||
SetAccount (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override;
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -18,18 +18,16 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/SetRegularKey.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetRegularKey
|
||||
: public Transactor
|
||||
std::uint64_t
|
||||
SetRegularKey::calculateBaseFee ()
|
||||
{
|
||||
std::uint64_t calculateBaseFee () override
|
||||
{
|
||||
if ( mTxnAccount
|
||||
&& (! (mTxnAccount->getFlags () & lsfPasswordSpent))
|
||||
&& (calcAccountID(mSigningPubKey) == mTxnAccountID))
|
||||
@@ -39,39 +37,27 @@ class SetRegularKey
|
||||
}
|
||||
|
||||
return Transactor::calculateBaseFee ();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
SetRegularKey (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetRegularKey"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
TER
|
||||
SetRegularKey::preCheck ()
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
SetRegularKey::doApply ()
|
||||
{
|
||||
if (mFeeDue == zero)
|
||||
mTxnAccount->setFlag (lsfPasswordSpent);
|
||||
|
||||
@@ -88,16 +74,6 @@ public:
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_SetRegularKey (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return SetRegularKey(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
50
src/ripple/app/tx/impl/SetRegularKey.h
Normal file
50
src/ripple/app/tx/impl/SetRegularKey.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_SETREGULARKEY_H_INCLUDED
|
||||
#define RIPPLE_TX_SETREGULARKEY_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetRegularKey
|
||||
: public Transactor
|
||||
{
|
||||
std::uint64_t calculateBaseFee () override;
|
||||
|
||||
public:
|
||||
template <class... Args>
|
||||
SetRegularKey (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override;
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/tx/impl/SetSignerList.h>
|
||||
#include <ripple/app/tx/impl/SignerEntries.h>
|
||||
#include <ripple/protocol/STObject.h>
|
||||
#include <ripple/protocol/STArray.h>
|
||||
@@ -31,62 +32,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/**
|
||||
See the README.md for an overview of the SetSignerList transaction that
|
||||
this class implements.
|
||||
*/
|
||||
class SetSignerList final
|
||||
: public Transactor
|
||||
{
|
||||
private:
|
||||
// Values determined during preCheck for use later.
|
||||
enum Operation {unknown, set, destroy};
|
||||
Operation do_ {unknown};
|
||||
std::uint32_t quorum_ {0};
|
||||
std::vector<SignerEntries::SignerEntry> signers_;
|
||||
|
||||
public:
|
||||
SetSignerList (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetSignerList"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Applies the transaction if it is well formed and the ledger state permits.
|
||||
*/
|
||||
TER doApply () override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
Check anything that can be checked without the ledger.
|
||||
*/
|
||||
TER preCheck () override;
|
||||
|
||||
private:
|
||||
// signers are not const because method (intentionally) sorts vector.
|
||||
TER validateQuorumAndSignerEntries (
|
||||
std::uint32_t quorum,
|
||||
std::vector<SignerEntries::SignerEntry>& signers) const;
|
||||
|
||||
// Methods called by doApply()
|
||||
TER replaceSignerList (uint256 const& index);
|
||||
TER destroySignerList (uint256 const& index);
|
||||
|
||||
void writeSignersToLedger (SLE::pointer ledgerEntry);
|
||||
|
||||
static std::size_t ownerCountDelta (std::size_t entryCount);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
TER
|
||||
SetSignerList::doApply ()
|
||||
{
|
||||
@@ -116,6 +61,11 @@ SetSignerList::doApply ()
|
||||
TER
|
||||
SetSignerList::preCheck()
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_MULTI_SIGN
|
||||
if (! (view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
|
||||
// We need the account ID later, so do this check first.
|
||||
preCheckAccount ();
|
||||
|
||||
@@ -127,7 +77,7 @@ SetSignerList::preCheck()
|
||||
if (quorum_ && hasSignerEntries)
|
||||
{
|
||||
SignerEntries::Decoded signers (
|
||||
SignerEntries::deserialize (mTxn, m_journal, "transaction"));
|
||||
SignerEntries::deserialize (mTxn, j_, "transaction"));
|
||||
|
||||
if (signers.ter != tesSUCCESS)
|
||||
return signers.ter;
|
||||
@@ -150,7 +100,7 @@ SetSignerList::preCheck()
|
||||
else
|
||||
{
|
||||
// Neither a set nor a destroy. Malformed.
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: Invalid signer set list format.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
@@ -169,7 +119,7 @@ SetSignerList::validateQuorumAndSignerEntries (
|
||||
if ((signerCount < SignerEntries::minEntries)
|
||||
|| (signerCount > SignerEntries::maxEntries))
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Too many or too few signers in signer list.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
@@ -180,7 +130,7 @@ SetSignerList::validateQuorumAndSignerEntries (
|
||||
if (std::adjacent_find (
|
||||
signers.begin (), signers.end ()) != signers.end ())
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Duplicate signers in signer list";
|
||||
return temBAD_SIGNER;
|
||||
}
|
||||
@@ -194,7 +144,7 @@ SetSignerList::validateQuorumAndSignerEntries (
|
||||
|
||||
if (signer.account == mTxnAccountID)
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"A signer may not self reference account.";
|
||||
return temBAD_SIGNER;
|
||||
}
|
||||
@@ -204,7 +154,7 @@ SetSignerList::validateQuorumAndSignerEntries (
|
||||
}
|
||||
if ((quorum <= 0) || (allSignersWeight < quorum))
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Quorum is unreachable";
|
||||
return temBAD_QUORUM;
|
||||
}
|
||||
@@ -225,7 +175,7 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ());
|
||||
|
||||
auto const newReserve =
|
||||
mEngine->view().fees().accountReserve(
|
||||
view().fees().accountReserve(
|
||||
oldOwnerCount + addedOwnerCount);
|
||||
|
||||
// We check the reserve against the starting balance because we want to
|
||||
@@ -236,7 +186,7 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
|
||||
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
|
||||
auto signerList = std::make_shared<SLE>(ltSIGNER_LIST, index);
|
||||
mEngine->view().insert (signerList);
|
||||
view().insert (signerList);
|
||||
writeSignersToLedger (signerList);
|
||||
|
||||
// Lambda for call to dirAdd.
|
||||
@@ -247,10 +197,10 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
|
||||
// Add the signer list to the account's directory.
|
||||
std::uint64_t hint;
|
||||
TER result = dirAdd(mEngine->view (),
|
||||
TER result = dirAdd(ctx_.view (),
|
||||
hint, getOwnerDirIndex (mTxnAccountID), index, describer);
|
||||
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Create signer list for account " <<
|
||||
mTxnAccountID << ": " << transHuman (result);
|
||||
|
||||
@@ -260,7 +210,7 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
signerList->setFieldU64 (sfOwnerNode, hint);
|
||||
|
||||
// If we succeeded, the new entry counts against the creator's reserve.
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
mTxnAccount, addedOwnerCount);
|
||||
|
||||
return result;
|
||||
@@ -271,7 +221,7 @@ SetSignerList::destroySignerList (uint256 const& index)
|
||||
{
|
||||
// See if there's an ltSIGNER_LIST for this account.
|
||||
SLE::pointer signerList =
|
||||
mEngine->view().peek (keylet::signers(index));
|
||||
view().peek (keylet::signers(index));
|
||||
|
||||
// If the signer list doesn't exist we've already succeeded in deleting it.
|
||||
if (!signerList)
|
||||
@@ -282,7 +232,7 @@ SetSignerList::destroySignerList (uint256 const& index)
|
||||
std::uint32_t removeFromOwnerCount = 0;
|
||||
auto const k = keylet::signers(mTxnAccountID);
|
||||
SLE::pointer accountSignersList =
|
||||
mEngine->view().peek (k);
|
||||
view().peek (k);
|
||||
if (accountSignersList)
|
||||
{
|
||||
STArray const& actualList =
|
||||
@@ -293,14 +243,14 @@ SetSignerList::destroySignerList (uint256 const& index)
|
||||
// Remove the node from the account directory.
|
||||
std::uint64_t const hint (signerList->getFieldU64 (sfOwnerNode));
|
||||
|
||||
TER const result = dirDelete(mEngine->view (), false, hint,
|
||||
TER const result = dirDelete(ctx_.view (), false, hint,
|
||||
getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0));
|
||||
|
||||
if (result == tesSUCCESS)
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
mTxnAccount, removeFromOwnerCount);
|
||||
|
||||
mEngine->view ().erase (signerList);
|
||||
ctx_.view ().erase (signerList);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -357,17 +307,4 @@ SetSignerList::ownerCountDelta (std::size_t entryCount)
|
||||
return 2 + entryCount;
|
||||
}
|
||||
|
||||
TER
|
||||
transact_SetSignerList (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
#if ! RIPPLE_ENABLE_MULTI_SIGN
|
||||
if (! (engine->view().flags() & tapENABLE_TESTING))
|
||||
return temDISABLED;
|
||||
#endif
|
||||
return SetSignerList (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
78
src/ripple/app/tx/impl/SetSignerList.h
Normal file
78
src/ripple/app/tx/impl/SetSignerList.h
Normal file
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2014 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_SETSIGNERLIST_H_INCLUDED
|
||||
#define RIPPLE_TX_SETSIGNERLIST_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/SignerEntries.h>
|
||||
#include <ripple/protocol/STObject.h>
|
||||
#include <ripple/protocol/STArray.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/STAccount.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/**
|
||||
See the README.md for an overview of the SetSignerList transaction that
|
||||
this class implements.
|
||||
*/
|
||||
class SetSignerList : public Transactor
|
||||
{
|
||||
private:
|
||||
// Values determined during preCheck for use later.
|
||||
enum Operation {unknown, set, destroy};
|
||||
Operation do_ {unknown};
|
||||
std::uint32_t quorum_ {0};
|
||||
std::vector<SignerEntries::SignerEntry> signers_;
|
||||
|
||||
public:
|
||||
template <class... Args>
|
||||
SetSignerList (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply () override;
|
||||
TER preCheck () override;
|
||||
|
||||
private:
|
||||
// `signers` is sorted on return
|
||||
TER validateQuorumAndSignerEntries (
|
||||
std::uint32_t quorum,
|
||||
std::vector<SignerEntries::SignerEntry>& signers) const;
|
||||
|
||||
TER replaceSignerList (uint256 const& index);
|
||||
TER destroySignerList (uint256 const& index);
|
||||
|
||||
void writeSignersToLedger (SLE::pointer ledgerEntry);
|
||||
|
||||
static std::size_t ownerCountDelta (std::size_t entryCount);
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -19,36 +19,21 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/SetTrust.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetTrust
|
||||
: public Transactor
|
||||
TER
|
||||
SetTrust::preCheck ()
|
||||
{
|
||||
public:
|
||||
SetTrust (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetTrust"))
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfTrustSetMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
@@ -60,7 +45,7 @@ public:
|
||||
|
||||
if (saLimitAmount.native ())
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: specifies native limit " <<
|
||||
saLimitAmount.getFullText ();
|
||||
return temBAD_LIMIT;
|
||||
@@ -68,14 +53,14 @@ public:
|
||||
|
||||
if (badCurrency() == saLimitAmount.getCurrency ())
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: specifies XRP as IOU";
|
||||
return temBAD_CURRENCY;
|
||||
}
|
||||
|
||||
if (saLimitAmount < zero)
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: Negative credit limit.";
|
||||
return temBAD_LIMIT;
|
||||
}
|
||||
@@ -85,16 +70,17 @@ public:
|
||||
|
||||
if (!issuer || issuer == noAccount())
|
||||
{
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
if (j_.trace) j_.trace <<
|
||||
"Malformed transaction: no destination account.";
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
|
||||
return Transactor::preCheck ();
|
||||
}
|
||||
}
|
||||
|
||||
TER doApply () override
|
||||
{
|
||||
TER
|
||||
SetTrust::doApply ()
|
||||
{
|
||||
TER terResult = tesSUCCESS;
|
||||
|
||||
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
|
||||
@@ -123,7 +109,7 @@ public:
|
||||
|
||||
STAmount const reserveCreate ((uOwnerCount < 2)
|
||||
? 0
|
||||
: mEngine->view().fees().accountReserve(uOwnerCount + 1));
|
||||
: view().fees().accountReserve(uOwnerCount + 1));
|
||||
|
||||
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
|
||||
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
|
||||
@@ -141,7 +127,7 @@ public:
|
||||
|
||||
if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth))
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Retry: Auth not required.";
|
||||
return tefNO_AUTH_REQUIRED;
|
||||
}
|
||||
@@ -152,31 +138,31 @@ public:
|
||||
// trust line to oneself to be deleted. If no such trust
|
||||
// lines exist now, why not remove this code and simply
|
||||
// return an error?
|
||||
SLE::pointer sleDelete = mEngine->view().peek (
|
||||
SLE::pointer sleDelete = view().peek (
|
||||
keylet::line(mTxnAccountID, uDstAccountID, currency));
|
||||
|
||||
if (sleDelete)
|
||||
{
|
||||
m_journal.warning <<
|
||||
j_.warning <<
|
||||
"Clearing redundant line.";
|
||||
|
||||
return trustDelete (mEngine->view(),
|
||||
return trustDelete (view(),
|
||||
sleDelete, mTxnAccountID, uDstAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Malformed transaction: Can not extend credit to self.";
|
||||
return temDST_IS_SRC;
|
||||
}
|
||||
}
|
||||
|
||||
SLE::pointer sleDst =
|
||||
mEngine->view().peek (keylet::account(uDstAccountID));
|
||||
view().peek (keylet::account(uDstAccountID));
|
||||
|
||||
if (!sleDst)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
return tecNO_DST;
|
||||
}
|
||||
@@ -184,7 +170,7 @@ public:
|
||||
STAmount saLimitAllow = saLimitAmount;
|
||||
saLimitAllow.setIssuer (mTxnAccountID);
|
||||
|
||||
SLE::pointer sleRippleState = mEngine->view().peek (
|
||||
SLE::pointer sleRippleState = view().peek (
|
||||
keylet::line(mTxnAccountID, uDstAccountID, currency));
|
||||
|
||||
if (sleRippleState)
|
||||
@@ -337,7 +323,7 @@ public:
|
||||
if (bLowReserveSet && !bLowReserved)
|
||||
{
|
||||
// Set reserve for low account.
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
sleLowAccount, 1);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
@@ -348,7 +334,7 @@ public:
|
||||
if (bLowReserveClear && bLowReserved)
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
sleLowAccount, -1);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
}
|
||||
@@ -356,7 +342,7 @@ public:
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
{
|
||||
// Set reserve for high account.
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
sleHighAccount, 1);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
@@ -367,7 +353,7 @@ public:
|
||||
if (bHighReserveClear && bHighReserved)
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
adjustOwnerCount(view(),
|
||||
sleHighAccount, -1);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
}
|
||||
@@ -379,13 +365,13 @@ public:
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult = trustDelete (mEngine->view(),
|
||||
terResult = trustDelete (view(),
|
||||
sleRippleState, uLowAccountID, uHighAccountID);
|
||||
}
|
||||
// Reserve is not scaled by load.
|
||||
else if (bReserveIncrease && mPriorBalance < reserveCreate)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Insufficent reserve to add trust line.";
|
||||
|
||||
// Another transaction could provide XRP to the account and then
|
||||
@@ -394,9 +380,9 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
mEngine->view().update (sleRippleState);
|
||||
view().update (sleRippleState);
|
||||
|
||||
m_journal.trace << "Modify ripple line";
|
||||
j_.trace << "Modify ripple line";
|
||||
}
|
||||
}
|
||||
// Line does not exist.
|
||||
@@ -404,13 +390,13 @@ public:
|
||||
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
|
||||
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Redundant: Setting non-existent ripple line to defaults.";
|
||||
return tecNO_LINE_REDUNDANT;
|
||||
}
|
||||
else if (mPriorBalance < reserveCreate) // Reserve is not scaled by load.
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"Delay transaction: Line does not exist. Insufficent reserve to create line.";
|
||||
|
||||
// Another transaction could create the account and then this transaction would succeed.
|
||||
@@ -424,12 +410,12 @@ public:
|
||||
uint256 index (getRippleStateIndex (
|
||||
mTxnAccountID, uDstAccountID, currency));
|
||||
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"doTrustSet: Creating ripple line: " <<
|
||||
to_string (index);
|
||||
|
||||
// Create a new ripple line.
|
||||
terResult = trustCreate (mEngine->view(),
|
||||
terResult = trustCreate (view(),
|
||||
bHigh,
|
||||
mTxnAccountID,
|
||||
uDstAccountID,
|
||||
@@ -445,16 +431,6 @@ public:
|
||||
}
|
||||
|
||||
return terResult;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_SetTrust (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return SetTrust (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
49
src/ripple/app/tx/impl/SetTrust.h
Normal file
49
src/ripple/app/tx/impl/SetTrust.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_SETTRUST_H_INCLUDED
|
||||
#define RIPPLE_TX_SETTRUST_H_INCLUDED
|
||||
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetTrust
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
template <class... Args>
|
||||
SetTrust (Args&&... args)
|
||||
: Transactor(std::forward<
|
||||
Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
TER preCheck () override;
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -515,23 +515,15 @@ BasicTaker::do_cross (
|
||||
|
||||
//==============================================================================
|
||||
|
||||
std::uint32_t
|
||||
Taker::calculateRate (
|
||||
View const& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& account)
|
||||
{
|
||||
return isXRP (issuer) || (account == issuer)
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate (view, issuer);
|
||||
}
|
||||
|
||||
Taker::Taker (CrossType cross_type, View& view, AccountID const& account,
|
||||
Amounts const& offer, std::uint32_t flags, beast::Journal journal)
|
||||
Taker::Taker (CrossType cross_type, View& view,
|
||||
AccountID const& account, Amounts const& offer,
|
||||
std::uint32_t flags, Config const& config,
|
||||
beast::Journal journal)
|
||||
: BasicTaker (cross_type, account, offer, Quality(offer), flags,
|
||||
calculateRate(view, offer.in.getIssuer(), account),
|
||||
calculateRate(view, offer.out.getIssuer(), account), journal)
|
||||
, view_ (view)
|
||||
, config_ (config)
|
||||
, xrp_flow_ (0)
|
||||
, direct_crossings_ (0)
|
||||
, bridge_crossings_ (0)
|
||||
@@ -587,7 +579,7 @@ STAmount
|
||||
Taker::get_funds (AccountID const& account, STAmount const& amount) const
|
||||
{
|
||||
return accountFunds(view_, account, amount, fhZERO_IF_FROZEN,
|
||||
getConfig());
|
||||
config_);
|
||||
}
|
||||
|
||||
TER Taker::transferXRP (
|
||||
@@ -779,4 +771,16 @@ Taker::cross (Offer const& leg1, Offer const& leg2)
|
||||
return fill (ret.first, leg1, ret.second, leg2);
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
Taker::calculateRate (
|
||||
View const& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& account)
|
||||
{
|
||||
return isXRP (issuer) || (account == issuer)
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate (view, issuer);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_APP_BOOK_TAKER_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/impl/Offer.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/protocol/Quality.h>
|
||||
#include <ripple/protocol/TER.h>
|
||||
@@ -239,48 +240,14 @@ public:
|
||||
class Taker
|
||||
: public BasicTaker
|
||||
{
|
||||
private:
|
||||
static
|
||||
std::uint32_t
|
||||
calculateRate (View const& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& account);
|
||||
|
||||
// The underlying ledger entry we are dealing with
|
||||
View& view_;
|
||||
|
||||
// The amount of XRP that flowed if we were autobridging
|
||||
STAmount xrp_flow_;
|
||||
|
||||
// The number direct crossings that we performed
|
||||
std::uint32_t direct_crossings_;
|
||||
|
||||
// The number autobridged crossings that we performed
|
||||
std::uint32_t bridge_crossings_;
|
||||
|
||||
TER
|
||||
fill (BasicTaker::Flow const& flow, Offer const& offer);
|
||||
|
||||
TER
|
||||
fill (
|
||||
BasicTaker::Flow const& flow1, Offer const& leg1,
|
||||
BasicTaker::Flow const& flow2, Offer const& leg2);
|
||||
|
||||
TER
|
||||
transferXRP (AccountID const& from, AccountID const& to, STAmount const& amount);
|
||||
|
||||
TER
|
||||
redeemIOU (AccountID const& account, STAmount const& amount, Issue const& issue);
|
||||
|
||||
TER
|
||||
issueIOU (AccountID const& account, STAmount const& amount, Issue const& issue);
|
||||
|
||||
public:
|
||||
Taker () = delete;
|
||||
Taker (Taker const&) = delete;
|
||||
|
||||
Taker (CrossType cross_type, View& view, AccountID const& account,
|
||||
Amounts const& offer, std::uint32_t flags, beast::Journal journal);
|
||||
Taker (CrossType cross_type, View& view,
|
||||
AccountID const& account, Amounts const& offer,
|
||||
std::uint32_t flags, Config const& config,
|
||||
beast::Journal journal);
|
||||
~Taker () = default;
|
||||
|
||||
void
|
||||
@@ -318,6 +285,45 @@ public:
|
||||
TER
|
||||
cross (Offer const& leg1, Offer const& leg2);
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
static
|
||||
std::uint32_t
|
||||
calculateRate (View const& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& account);
|
||||
|
||||
TER
|
||||
fill (BasicTaker::Flow const& flow, Offer const& offer);
|
||||
|
||||
TER
|
||||
fill (
|
||||
BasicTaker::Flow const& flow1, Offer const& leg1,
|
||||
BasicTaker::Flow const& flow2, Offer const& leg2);
|
||||
|
||||
TER
|
||||
transferXRP (AccountID const& from, AccountID const& to, STAmount const& amount);
|
||||
|
||||
TER
|
||||
redeemIOU (AccountID const& account, STAmount const& amount, Issue const& issue);
|
||||
|
||||
TER
|
||||
issueIOU (AccountID const& account, STAmount const& amount, Issue const& issue);
|
||||
|
||||
private:
|
||||
// The underlying ledger entry we are dealing with
|
||||
View& view_;
|
||||
|
||||
Config const& config_;
|
||||
|
||||
// The amount of XRP that flowed if we were autobridging
|
||||
STAmount xrp_flow_;
|
||||
|
||||
// The number direct crossings that we performed
|
||||
std::uint32_t direct_crossings_;
|
||||
|
||||
// The number autobridged crossings that we performed
|
||||
std::uint32_t bridge_crossings_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//
|
||||
// XXX Make sure all fields are recognized in transactions.
|
||||
//
|
||||
|
||||
std::pair<TER, bool>
|
||||
TransactionEngine::applyTransaction (
|
||||
STTx const& txn,
|
||||
ViewFlags flags)
|
||||
{
|
||||
TER terResult = tefINTERNAL;
|
||||
bool didApply = false;
|
||||
|
||||
try
|
||||
{
|
||||
assert (mLedger);
|
||||
|
||||
WriteLog (lsTRACE, TransactionEngine) << "applyTransaction>";
|
||||
|
||||
uint256 const& txID = txn.getTransactionID ();
|
||||
|
||||
if (!txID)
|
||||
{
|
||||
WriteLog (lsWARNING, TransactionEngine) <<
|
||||
"applyTransaction: invalid transaction id";
|
||||
return std::make_pair(temINVALID_FLAG, false);
|
||||
}
|
||||
|
||||
mNodes.emplace(mLedger.get(), flags, txID);
|
||||
|
||||
#ifdef BEAST_DEBUG
|
||||
if (1)
|
||||
{
|
||||
Serializer ser;
|
||||
txn.add (ser);
|
||||
SerialIter sit(ser.slice());
|
||||
STTx s2 (sit);
|
||||
|
||||
if (!s2.isEquivalent (txn))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Transaction serdes mismatch";
|
||||
WriteLog (lsINFO, TransactionEngine) << txn.getJson (0);
|
||||
WriteLog (lsFATAL, TransactionEngine) << s2.getJson (0);
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
terResult = Transactor::transact (txn, flags, this);
|
||||
|
||||
if (terResult == temUNKNOWN)
|
||||
{
|
||||
WriteLog (lsWARNING, TransactionEngine) <<
|
||||
"applyTransaction: Invalid transaction: unknown transaction type";
|
||||
return std::make_pair(temUNKNOWN, false);
|
||||
}
|
||||
|
||||
if (ShouldLog (lsDEBUG, TransactionEngine))
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
transResultInfo (terResult, strToken, strHuman);
|
||||
|
||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
||||
"applyTransaction: terResult=" << strToken <<
|
||||
" : " << terResult <<
|
||||
" : " << strHuman;
|
||||
}
|
||||
|
||||
didApply = isTesSuccess (terResult);
|
||||
|
||||
if (isTecClaim (terResult) && !(flags & tapRETRY))
|
||||
{
|
||||
// only claim the transaction fee
|
||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
||||
"Reprocessing tx " << txID << " to only claim fee";
|
||||
mNodes.emplace(mLedger.get(), flags, txID);
|
||||
|
||||
SLE::pointer txnAcct = view().peek(
|
||||
keylet::account(txn.getAccountID(sfAccount)));
|
||||
|
||||
if (!txnAcct)
|
||||
terResult = terNO_ACCOUNT;
|
||||
else
|
||||
{
|
||||
std::uint32_t t_seq = txn.getSequence ();
|
||||
std::uint32_t a_seq = txnAcct->getFieldU32 (sfSequence);
|
||||
|
||||
if (a_seq < t_seq)
|
||||
terResult = terPRE_SEQ;
|
||||
else if (a_seq > t_seq)
|
||||
terResult = tefPAST_SEQ;
|
||||
else
|
||||
{
|
||||
STAmount fee = txn.getTransactionFee ();
|
||||
STAmount balance = txnAcct->getFieldAmount (sfBalance);
|
||||
|
||||
// We retry/reject the transaction if the account
|
||||
// balance is zero or we're applying against an open
|
||||
// ledger and the balance is less than the fee
|
||||
if ((balance == zero) ||
|
||||
((flags & tapOPEN_LEDGER) && (balance < fee)))
|
||||
{
|
||||
// Account has no funds or ledger is open
|
||||
terResult = terINSUF_FEE_B;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fee > balance)
|
||||
fee = balance;
|
||||
txnAcct->setFieldAmount (sfBalance, balance - fee);
|
||||
txnAcct->setFieldU32 (sfSequence, t_seq + 1);
|
||||
view().update (txnAcct);
|
||||
didApply = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!didApply)
|
||||
{
|
||||
WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction " << txID;
|
||||
}
|
||||
|
||||
if (didApply && !checkInvariants (terResult, txn, flags))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Transaction violates invariants";
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
txn.getJson (0);
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
transToken (terResult) << ": " << transHuman (terResult);
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
mNodes->getJson (0);
|
||||
didApply = false;
|
||||
terResult = tefINTERNAL;
|
||||
}
|
||||
|
||||
if (didApply)
|
||||
{
|
||||
// Transaction succeeded fully or (retries are not allowed and the
|
||||
// transaction could claim a fee)
|
||||
Serializer m;
|
||||
mNodes->calcRawMeta (m, terResult, mTxnSeq++);
|
||||
|
||||
mNodes->apply(*mLedger);
|
||||
|
||||
Serializer s;
|
||||
txn.add (s);
|
||||
|
||||
if (flags & tapOPEN_LEDGER)
|
||||
{
|
||||
if (! mLedger->txInsert(txID,
|
||||
std::make_shared<
|
||||
Serializer const>(std::move(s)),
|
||||
nullptr))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Duplicate transaction applied";
|
||||
assert (false);
|
||||
throw std::runtime_error ("Duplicate transaction applied");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! mLedger->txInsert(txID,
|
||||
std::make_shared<Serializer const>(std::move(s)),
|
||||
std::make_shared<Serializer const>(std::move(m))))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Duplicate transaction applied to closed ledger";
|
||||
assert (false);
|
||||
throw std::runtime_error ("Duplicate transaction applied to closed ledger");
|
||||
}
|
||||
|
||||
// Charge whatever fee they specified. We break the encapsulation of
|
||||
// STAmount here and use "special knowledge" - namely that a native
|
||||
// amount is stored fully in the mantissa:
|
||||
auto const fee = txn.getTransactionFee ();
|
||||
|
||||
// The transactor guarantees these will never trigger
|
||||
if (!fee.native () || fee.negative ())
|
||||
throw std::runtime_error ("amount is negative!");
|
||||
|
||||
if (fee != zero)
|
||||
mLedger->destroyCoins (fee.mantissa ());
|
||||
}
|
||||
}
|
||||
|
||||
mNodes = boost::none;
|
||||
|
||||
if (!(flags & tapOPEN_LEDGER) && isTemMalformed (terResult))
|
||||
{
|
||||
// XXX Malformed or failed transaction in closed ledger must bow out.
|
||||
}
|
||||
}
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Caught exception: " << e.what();
|
||||
return { tefEXCEPTION, false };
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Caught unknown exception";
|
||||
return { tefEXCEPTION, false };
|
||||
}
|
||||
|
||||
return { terResult, didApply };
|
||||
}
|
||||
|
||||
bool
|
||||
TransactionEngine::checkInvariants (
|
||||
TER result,
|
||||
STTx const& txn,
|
||||
ViewFlags flags)
|
||||
{
|
||||
// VFALCO I deleted a bunch of code that was wrapped in #if 0.
|
||||
// If you need it, check the commit log.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
@@ -21,94 +21,36 @@
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/tx/impl/Transactor.h>
|
||||
#include <ripple/app/tx/impl/SignerEntries.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TER transact_Payment (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_SetAccount (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_SetRegularKey (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_SetTrust (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_CreateOffer (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_CancelOffer (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_Change (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_CreateTicket (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_CancelTicket (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
TER transact_SetSignerList (STTx const& txn, ViewFlags params, TransactionEngine* engine);
|
||||
|
||||
TER
|
||||
Transactor::transact (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
switch (txn.getTxnType ())
|
||||
{
|
||||
case ttPAYMENT:
|
||||
return transact_Payment (txn, params, engine);
|
||||
|
||||
case ttACCOUNT_SET:
|
||||
return transact_SetAccount (txn, params, engine);
|
||||
|
||||
case ttREGULAR_KEY_SET:
|
||||
return transact_SetRegularKey (txn, params, engine);
|
||||
|
||||
case ttTRUST_SET:
|
||||
return transact_SetTrust (txn, params, engine);
|
||||
|
||||
case ttOFFER_CREATE:
|
||||
return transact_CreateOffer (txn, params, engine);
|
||||
|
||||
case ttOFFER_CANCEL:
|
||||
return transact_CancelOffer (txn, params, engine);
|
||||
|
||||
case ttAMENDMENT:
|
||||
case ttFEE:
|
||||
return transact_Change (txn, params, engine);
|
||||
|
||||
case ttTICKET_CREATE:
|
||||
return transact_CreateTicket (txn, params, engine);
|
||||
|
||||
case ttTICKET_CANCEL:
|
||||
return transact_CancelTicket (txn, params, engine);
|
||||
|
||||
case ttSIGNER_LIST_SET:
|
||||
return transact_SetSignerList (txn, params, engine);
|
||||
|
||||
default:
|
||||
return temUNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
Transactor::Transactor (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine,
|
||||
beast::Journal journal)
|
||||
: mTxn (txn)
|
||||
, mEngine (engine)
|
||||
, mParams (mEngine->view().flags())
|
||||
Transactor::Transactor(
|
||||
ApplyContext& ctx)
|
||||
: mTxn (ctx.tx)
|
||||
, ctx_ (ctx)
|
||||
, j_ (ctx.journal)
|
||||
, mHasAuthKey (false)
|
||||
, mSigMaster (false)
|
||||
, m_journal (journal)
|
||||
{
|
||||
assert(mEngine->view().flags() == params);
|
||||
}
|
||||
|
||||
void Transactor::calculateFee ()
|
||||
{
|
||||
mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad(
|
||||
calculateBaseFee(), mEngine->view().fees().base,
|
||||
mEngine->view().fees().units, mParams & tapADMIN));
|
||||
calculateBaseFee(), view().fees().base,
|
||||
view().fees().units, view().flags() & tapADMIN));
|
||||
}
|
||||
|
||||
std::uint64_t Transactor::calculateBaseFee ()
|
||||
{
|
||||
// Returns the fee in fee units
|
||||
return getConfig ().TRANSACTION_FEE_BASE;
|
||||
return ctx_.config.TRANSACTION_FEE_BASE;
|
||||
}
|
||||
|
||||
TER Transactor::payFee ()
|
||||
@@ -119,9 +61,9 @@ TER Transactor::payFee ()
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
// Only check fee is sufficient when the ledger is open.
|
||||
if ((mParams & tapOPEN_LEDGER) && saPaid < mFeeDue)
|
||||
if (view().open() && saPaid < mFeeDue)
|
||||
{
|
||||
m_journal.trace << "Insufficient fee paid: " <<
|
||||
j_.trace << "Insufficient fee paid: " <<
|
||||
saPaid.getText () << "/" << mFeeDue.getText ();
|
||||
|
||||
return telINSUF_FEE_P;
|
||||
@@ -135,11 +77,11 @@ TER Transactor::payFee ()
|
||||
|
||||
if (mSourceBalance < saPaid)
|
||||
{
|
||||
m_journal.trace << "Insufficient balance:" <<
|
||||
j_.trace << "Insufficient balance:" <<
|
||||
" balance=" << mSourceBalance.getText () <<
|
||||
" paid=" << saPaid.getText ();
|
||||
|
||||
if ((mSourceBalance > zero) && (!(mParams & tapOPEN_LEDGER)))
|
||||
if ((mSourceBalance > zero) && ! view().open())
|
||||
{
|
||||
// Closed ledger, non-zero balance, less than fee
|
||||
mSourceBalance.clear ();
|
||||
@@ -156,6 +98,8 @@ TER Transactor::payFee ()
|
||||
mSourceBalance -= saPaid;
|
||||
mTxnAccount->setFieldAmount (sfBalance, mSourceBalance);
|
||||
|
||||
// VFALCO Should we call view().destroyCoins() here as well?
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -168,16 +112,16 @@ TER Transactor::checkSeq ()
|
||||
{
|
||||
if (a_seq < t_seq)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: has future sequence number " <<
|
||||
"a_seq=" << a_seq << " t_seq=" << t_seq;
|
||||
return terPRE_SEQ;
|
||||
}
|
||||
|
||||
if (mEngine->view().txExists(mTxn.getTransactionID ()))
|
||||
if (view().txExists(mTxn.getTransactionID ()))
|
||||
return tefALREADY;
|
||||
|
||||
m_journal.trace << "applyTransaction: has past sequence number " <<
|
||||
j_.trace << "applyTransaction: has past sequence number " <<
|
||||
"a_seq=" << a_seq << " t_seq=" << t_seq;
|
||||
return tefPAST_SEQ;
|
||||
}
|
||||
@@ -187,7 +131,7 @@ TER Transactor::checkSeq ()
|
||||
return tefWRONG_PRIOR;
|
||||
|
||||
if (mTxn.isFieldPresent (sfLastLedgerSequence) &&
|
||||
(mEngine->getLedger()->getLedgerSeq() > mTxn.getFieldU32 (sfLastLedgerSequence)))
|
||||
(view().seq() > mTxn.getFieldU32 (sfLastLedgerSequence)))
|
||||
return tefMAX_LEDGER;
|
||||
|
||||
mTxnAccount->setFieldU32 (sfSequence, t_seq + 1);
|
||||
@@ -214,7 +158,7 @@ TER Transactor::preCheckAccount ()
|
||||
|
||||
if (!mTxnAccountID)
|
||||
{
|
||||
m_journal.warning << "applyTransaction: bad transaction source id";
|
||||
j_.warning << "applyTransaction: bad transaction source id";
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
return tesSUCCESS;
|
||||
@@ -235,17 +179,17 @@ TER Transactor::preCheckSigningKey ()
|
||||
if (!mTxn.isKnownGood ())
|
||||
{
|
||||
if (mTxn.isKnownBad () ||
|
||||
(!(mParams & tapNO_CHECK_SIGN) && !mTxn.checkSign(
|
||||
(!(view().flags() & tapNO_CHECK_SIGN) && !mTxn.checkSign(
|
||||
(
|
||||
#if RIPPLE_ENABLE_MULTI_SIGN
|
||||
true
|
||||
#else
|
||||
mEngine->view().flags() & tapENABLE_TESTING
|
||||
view().flags() & tapENABLE_TESTING
|
||||
#endif
|
||||
))))
|
||||
{
|
||||
mTxn.setBad ();
|
||||
m_journal.debug << "apply: Invalid transaction (bad signature)";
|
||||
j_.debug << "apply: Invalid transaction (bad signature)";
|
||||
return temINVALID;
|
||||
}
|
||||
|
||||
@@ -269,7 +213,7 @@ TER Transactor::apply ()
|
||||
return terResult;
|
||||
|
||||
// Find source account
|
||||
mTxnAccount = mEngine->view().peek (keylet::account(mTxnAccountID));
|
||||
mTxnAccount = view().peek (keylet::account(mTxnAccountID));
|
||||
|
||||
calculateFee ();
|
||||
|
||||
@@ -279,7 +223,7 @@ TER Transactor::apply ()
|
||||
{
|
||||
if (mustHaveValidAccount ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: delay: source account does not exist " <<
|
||||
toBase58(mTxn.getAccountID(sfAccount));
|
||||
return terNO_ACCOUNT;
|
||||
@@ -305,7 +249,7 @@ TER Transactor::apply ()
|
||||
if (terResult != tesSUCCESS) return (terResult);
|
||||
|
||||
if (mTxnAccount)
|
||||
mEngine->view().update (mTxnAccount);
|
||||
view().update (mTxnAccount);
|
||||
|
||||
return doApply ();
|
||||
}
|
||||
@@ -314,7 +258,7 @@ TER Transactor::checkSign ()
|
||||
{
|
||||
#if RIPPLE_ENABLE_MULTI_SIGN
|
||||
#else
|
||||
if(mEngine->view().flags() & tapENABLE_TESTING)
|
||||
if(view().flags() & tapENABLE_TESTING)
|
||||
#endif
|
||||
{
|
||||
// If the mSigningPubKey is empty, then we must be multi-signing.
|
||||
@@ -347,13 +291,13 @@ TER Transactor::checkSingleSign ()
|
||||
}
|
||||
else if (mHasAuthKey)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: Delay: Not authorized to use account.";
|
||||
return tefBAD_AUTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: Invalid: Not authorized to use account.";
|
||||
return tefBAD_AUTH_MASTER;
|
||||
}
|
||||
@@ -372,15 +316,16 @@ struct GetSignerListResult
|
||||
};
|
||||
|
||||
// We need the SignerList for every SigningFor while multi-signing.
|
||||
static
|
||||
GetSignerListResult
|
||||
getSignerList (
|
||||
AccountID signingForAcctID, TransactionEngine* engine, beast::Journal journal)
|
||||
getSignerList (AccountID signingForAcctID,
|
||||
BasicView const& view, beast::Journal journal)
|
||||
{
|
||||
GetSignerListResult ret;
|
||||
|
||||
auto const k = keylet::signers(signingForAcctID);
|
||||
SLE::pointer accountSignersList =
|
||||
engine->view().peek (k);
|
||||
auto const accountSignersList =
|
||||
view.read (k);
|
||||
|
||||
// If the signer list doesn't exist the account is not multi-signing.
|
||||
if (!accountSignersList)
|
||||
@@ -414,7 +359,7 @@ CheckSigningAccountsResult
|
||||
checkSigningAccounts (
|
||||
std::vector<SignerEntries::SignerEntry> signerEntries,
|
||||
STArray const& signingAccounts,
|
||||
TransactionEngine* engine,
|
||||
ApplyContext& ctx,
|
||||
beast::Journal journal)
|
||||
{
|
||||
CheckSigningAccountsResult ret;
|
||||
@@ -489,8 +434,8 @@ checkSigningAccounts (
|
||||
|
||||
// In any of these cases we need to know whether the account is in
|
||||
// the ledger. Determine that now.
|
||||
SLE::pointer signersAccountRoot =
|
||||
engine->view().peek (keylet::account(signingAcctID));
|
||||
auto signersAccountRoot =
|
||||
ctx.view().read (keylet::account(signingAcctID));
|
||||
|
||||
if (signingAcctIDFromPubKey == signingAcctID)
|
||||
{
|
||||
@@ -553,7 +498,7 @@ TER Transactor::checkMultiSign ()
|
||||
// Get mTxnAccountID's SignerList and Quorum.
|
||||
using namespace TransactorDetail;
|
||||
GetSignerListResult const outer =
|
||||
getSignerList (mTxnAccountID, mEngine, m_journal);
|
||||
getSignerList (mTxnAccountID, view(), j_);
|
||||
|
||||
if (outer.ter != tesSUCCESS)
|
||||
return outer.ter;
|
||||
@@ -587,7 +532,7 @@ TER Transactor::checkMultiSign ()
|
||||
// from these signers directly effect the quorum.
|
||||
CheckSigningAccountsResult const outerSigningAccountsResult =
|
||||
checkSigningAccounts (
|
||||
outer.signerEntries, signingAccounts, mEngine, m_journal);
|
||||
outer.signerEntries, signingAccounts, ctx_, j_);
|
||||
|
||||
if (outerSigningAccountsResult.ter != tesSUCCESS)
|
||||
return outerSigningAccountsResult.ter;
|
||||
@@ -602,7 +547,7 @@ TER Transactor::checkMultiSign ()
|
||||
{
|
||||
if (++signerEntriesItr == outer.signerEntries.end ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: Invalid SigningFor.Account.";
|
||||
return tefBAD_SIGNATURE;
|
||||
}
|
||||
@@ -610,21 +555,21 @@ TER Transactor::checkMultiSign ()
|
||||
if (signerEntriesItr->account != signingForID)
|
||||
{
|
||||
// The signingForID is not in the SignerEntries.
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: Invalid SigningFor.Account.";
|
||||
return tefBAD_SIGNATURE;
|
||||
}
|
||||
if (signerEntriesItr->weight <= 0)
|
||||
{
|
||||
// The SigningFor entry needs a weight greater than zero.
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: SigningFor.Account needs weight > 0.";
|
||||
return tefBAD_SIGNATURE;
|
||||
}
|
||||
|
||||
// See if the signingForID has a SignerList.
|
||||
GetSignerListResult const inner =
|
||||
getSignerList (signingForID, mEngine, m_journal);
|
||||
getSignerList (signingForID, view(), j_);
|
||||
|
||||
if (inner.ter != tesSUCCESS)
|
||||
return inner.ter;
|
||||
@@ -632,7 +577,7 @@ TER Transactor::checkMultiSign ()
|
||||
// Results from these signers indirectly effect the quorum.
|
||||
CheckSigningAccountsResult const innerSigningAccountsResult =
|
||||
checkSigningAccounts (
|
||||
inner.signerEntries, signingAccounts, mEngine, m_journal);
|
||||
inner.signerEntries, signingAccounts, ctx_, j_);
|
||||
|
||||
if (innerSigningAccountsResult.ter != tesSUCCESS)
|
||||
return innerSigningAccountsResult.ter;
|
||||
@@ -652,7 +597,7 @@ TER Transactor::checkMultiSign ()
|
||||
// -- January 2015
|
||||
if (innerSigningAccountsResult.weightSum < inner.quorum)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: Level-2 SigningFor did not make quorum.";
|
||||
return tefBAD_QUORUM;
|
||||
}
|
||||
@@ -664,7 +609,7 @@ TER Transactor::checkMultiSign ()
|
||||
// Cannot perform transaction if quorum is not met.
|
||||
if (weightSum < outer.quorum)
|
||||
{
|
||||
m_journal.trace <<
|
||||
j_.trace <<
|
||||
"applyTransaction: MultiSignature failed to meet quorum.";
|
||||
return tefBAD_QUORUM;
|
||||
}
|
||||
@@ -673,4 +618,173 @@ TER Transactor::checkMultiSign ()
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static
|
||||
void
|
||||
log (std::pair<
|
||||
TER, bool> const& result,
|
||||
beast::Journal j)
|
||||
{
|
||||
if(j.trace) j.trace <<
|
||||
"apply: { " << transToken(result.first) <<
|
||||
", " << (result.second ? "true" : "false") << " }";
|
||||
}
|
||||
|
||||
std::pair<TER, bool>
|
||||
Transactor::operator()()
|
||||
{
|
||||
JLOG(j_.trace) <<
|
||||
"applyTransaction>";
|
||||
|
||||
uint256 const& txID = mTxn.getTransactionID ();
|
||||
|
||||
if (!txID)
|
||||
{
|
||||
JLOG(j_.warning) <<
|
||||
"applyTransaction: transaction id may not be zero";
|
||||
auto const result =
|
||||
std::make_pair(temINVALID_FLAG, false);
|
||||
log(result, j_);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef BEAST_DEBUG
|
||||
{
|
||||
Serializer ser;
|
||||
mTxn.add (ser);
|
||||
SerialIter sit(ser.slice());
|
||||
STTx s2 (sit);
|
||||
|
||||
if (! s2.isEquivalent(mTxn))
|
||||
{
|
||||
JLOG(j_.fatal) <<
|
||||
"Transaction serdes mismatch";
|
||||
JLOG(j_.info) << to_string(mTxn.getJson (0));
|
||||
JLOG(j_.fatal) << s2.getJson (0);
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TER terResult = apply();
|
||||
|
||||
if (terResult == temUNKNOWN)
|
||||
{
|
||||
JLOG(j_.warning) <<
|
||||
"applyTransaction: Invalid transaction: unknown transaction type";
|
||||
auto const result =
|
||||
std::make_pair(temUNKNOWN, false);
|
||||
log(result, j_);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (j_.debug)
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
transResultInfo (terResult, strToken, strHuman);
|
||||
|
||||
j_.debug <<
|
||||
"applyTransaction: terResult=" << strToken <<
|
||||
" : " << terResult <<
|
||||
" : " << strHuman;
|
||||
}
|
||||
|
||||
bool didApply = isTesSuccess (terResult);
|
||||
|
||||
if (isTecClaim (terResult) && !(view().flags() & tapRETRY))
|
||||
{
|
||||
// only claim the transaction fee
|
||||
JLOG(j_.debug) <<
|
||||
"Reprocessing tx " << txID << " to only claim fee";
|
||||
|
||||
ctx_.discard();
|
||||
|
||||
auto const txnAcct = view().peek(
|
||||
keylet::account(mTxn.getAccountID(sfAccount)));
|
||||
|
||||
if (txnAcct)
|
||||
{
|
||||
std::uint32_t t_seq = mTxn.getSequence ();
|
||||
std::uint32_t a_seq = txnAcct->getFieldU32 (sfSequence);
|
||||
|
||||
if (a_seq < t_seq)
|
||||
terResult = terPRE_SEQ;
|
||||
else if (a_seq > t_seq)
|
||||
terResult = tefPAST_SEQ;
|
||||
else
|
||||
{
|
||||
STAmount fee = mTxn.getTransactionFee ();
|
||||
STAmount balance = txnAcct->getFieldAmount (sfBalance);
|
||||
|
||||
// We retry/reject the transaction if the account
|
||||
// balance is zero or we're applying against an open
|
||||
// ledger and the balance is less than the fee
|
||||
if ((balance == zero) ||
|
||||
(view().open() && (balance < fee)))
|
||||
{
|
||||
// Account has no funds or ledger is open
|
||||
terResult = terINSUF_FEE_B;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fee > balance)
|
||||
fee = balance;
|
||||
txnAcct->setFieldAmount (sfBalance, balance - fee);
|
||||
txnAcct->setFieldU32 (sfSequence, t_seq + 1);
|
||||
view().update (txnAcct);
|
||||
didApply = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
terResult = terNO_ACCOUNT;
|
||||
}
|
||||
}
|
||||
else if (!didApply)
|
||||
{
|
||||
JLOG(j_.debug) << "Not applying transaction " << txID;
|
||||
}
|
||||
|
||||
if (didApply)
|
||||
{
|
||||
// Transaction succeeded fully or (retries are
|
||||
// not allowed and the transaction could claim a fee)
|
||||
|
||||
if(view().closed())
|
||||
{
|
||||
// VFALCO Fix this nonsense with Amount
|
||||
// Charge whatever fee they specified. We break the
|
||||
// encapsulation of STAmount here and use "special
|
||||
// knowledge" - namely that a native amount is
|
||||
// stored fully in the mantissa:
|
||||
auto const fee = mTxn.getTransactionFee ();
|
||||
|
||||
// The transactor guarantees these will never trigger
|
||||
if (!fee.native () || fee.negative ())
|
||||
{
|
||||
// VFALCO Log to journal here
|
||||
// JLOG(journal.fatal) << "invalid fee";
|
||||
throw std::logic_error(
|
||||
"amount is negative!");
|
||||
}
|
||||
|
||||
if (fee != zero)
|
||||
view().destroyCoins (fee.mantissa ());
|
||||
}
|
||||
|
||||
ctx_.apply(terResult);
|
||||
// VFALCO NOTE since we called apply(), it is not
|
||||
// okay to look at view() past this point.
|
||||
}
|
||||
|
||||
auto const result =
|
||||
std::make_pair(terResult, didApply);
|
||||
log(result, j_);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,27 +20,17 @@
|
||||
#ifndef RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
|
||||
#define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
|
||||
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Transactor
|
||||
{
|
||||
public:
|
||||
static
|
||||
TER
|
||||
transact (
|
||||
STTx const& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine);
|
||||
|
||||
TER
|
||||
apply ();
|
||||
|
||||
protected:
|
||||
STTx const& mTxn;
|
||||
TransactionEngine* mEngine;
|
||||
ViewFlags const mParams;
|
||||
ApplyContext& ctx_;
|
||||
beast::Journal j_;
|
||||
|
||||
AccountID mTxnAccountID;
|
||||
STAmount mFeeDue;
|
||||
@@ -51,36 +41,53 @@ protected:
|
||||
bool mSigMaster;
|
||||
RippleAddress mSigningPubKey;
|
||||
|
||||
beast::Journal m_journal;
|
||||
public:
|
||||
/** Process the transaction. */
|
||||
std::pair<TER, bool>
|
||||
operator()();
|
||||
|
||||
virtual TER preCheck ();
|
||||
View&
|
||||
view()
|
||||
{
|
||||
return ctx_.view();
|
||||
}
|
||||
|
||||
View const&
|
||||
view() const
|
||||
{
|
||||
return ctx_.view();
|
||||
}
|
||||
|
||||
protected:
|
||||
TER
|
||||
apply();
|
||||
|
||||
explicit
|
||||
Transactor (ApplyContext& ctx);
|
||||
|
||||
// Non-virtual components of preCheck()
|
||||
TER preCheckAccount ();
|
||||
TER preCheckSigningKey ();
|
||||
|
||||
virtual TER checkSeq ();
|
||||
virtual TER payFee ();
|
||||
|
||||
void calculateFee ();
|
||||
|
||||
// VFALCO This is the equivalent of dynamic_cast
|
||||
// to discover the type of the derived class,
|
||||
// and therefore bad.
|
||||
virtual
|
||||
bool
|
||||
mustHaveValidAccount()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the fee, not scaled for load (Should be in fee units. FIXME)
|
||||
virtual std::uint64_t calculateBaseFee ();
|
||||
|
||||
virtual TER preCheck ();
|
||||
virtual TER checkSeq ();
|
||||
virtual TER payFee ();
|
||||
virtual TER checkSign ();
|
||||
virtual TER doApply () = 0;
|
||||
|
||||
Transactor (
|
||||
const STTx& txn,
|
||||
ViewFlags params,
|
||||
TransactionEngine* engine,
|
||||
beast::Journal journal = beast::Journal ());
|
||||
|
||||
virtual bool mustHaveValidAccount ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
TER checkSingleSign ();
|
||||
TER checkMultiSign ();
|
||||
|
||||
86
src/ripple/app/tx/impl/apply.cpp
Normal file
86
src/ripple/app/tx/impl/apply.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||
|
||||
#include <ripple/app/tx/impl/CancelOffer.h>
|
||||
#include <ripple/app/tx/impl/CancelTicket.h>
|
||||
#include <ripple/app/tx/impl/Change.h>
|
||||
#include <ripple/app/tx/impl/CreateOffer.h>
|
||||
#include <ripple/app/tx/impl/CreateTicket.h>
|
||||
#include <ripple/app/tx/impl/Payment.h>
|
||||
#include <ripple/app/tx/impl/SetAccount.h>
|
||||
#include <ripple/app/tx/impl/SetRegularKey.h>
|
||||
#include <ripple/app/tx/impl/SetSignerList.h>
|
||||
#include <ripple/app/tx/impl/SetTrust.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <class Processor,
|
||||
class... Args>
|
||||
static
|
||||
std::pair<TER, bool>
|
||||
do_apply (Args&&... args)
|
||||
{
|
||||
ApplyContext ctx (
|
||||
std::forward<Args>(args)...);
|
||||
Processor p(ctx);
|
||||
return p();
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
static
|
||||
std::pair<TER, bool>
|
||||
invoke (TxType type,
|
||||
Args&&... args)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ttACCOUNT_SET: return do_apply< SetAccount >(std::forward<Args>(args)...);
|
||||
case ttOFFER_CANCEL: return do_apply< CancelOffer >(std::forward<Args>(args)...);
|
||||
case ttOFFER_CREATE: return do_apply< CreateOffer >(std::forward<Args>(args)...);
|
||||
case ttPAYMENT: return do_apply< Payment >(std::forward<Args>(args)...);
|
||||
case ttREGULAR_KEY_SET: return do_apply< SetRegularKey >(std::forward<Args>(args)...);
|
||||
case ttSIGNER_LIST_SET: return do_apply< SetSignerList >(std::forward<Args>(args)...);
|
||||
case ttTICKET_CANCEL: return do_apply< CancelTicket >(std::forward<Args>(args)...);
|
||||
case ttTICKET_CREATE: return do_apply< CreateTicket >(std::forward<Args>(args)...);
|
||||
case ttTRUST_SET: return do_apply< SetTrust >(std::forward<Args>(args)...);
|
||||
|
||||
// VFALCO These are both the same?
|
||||
case ttAMENDMENT:
|
||||
case ttFEE: return do_apply< Change >(std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return { temUNKNOWN, false };
|
||||
}
|
||||
|
||||
std::pair<TER, bool>
|
||||
apply (BasicView& view,
|
||||
STTx const& tx, ViewFlags flags,
|
||||
Config const& config,
|
||||
beast::Journal journal)
|
||||
{
|
||||
return invoke (tx.getTxnType(),
|
||||
view, tx, flags, config, journal);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void testCanceledOffer ()
|
||||
{
|
||||
using namespace jtx;
|
||||
Env env = *this;
|
||||
Env env (*this);
|
||||
auto const gw = Account ("gateway");
|
||||
auto const USD = gw["USD"];
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/ledger/LedgerConsensus.h>
|
||||
#include <ripple/app/ledger/LedgerTiming.h>
|
||||
#include <ripple/app/ledger/tests/common_ledger.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/basics/seconds_clock.h>
|
||||
#include <ripple/protocol/TxFormats.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
@@ -90,12 +91,13 @@ TestLedger::TestLedger (
|
||||
createGenesisLedger(startAmountDrops, masterAcct);
|
||||
}
|
||||
|
||||
std::pair<TER, bool> TestLedger::applyTransaction (STTx const& tx, bool check)
|
||||
std::pair<TER, bool>
|
||||
TestLedger::applyTransaction (STTx const& tx, bool check)
|
||||
{
|
||||
// Apply the transaction to the open ledger.
|
||||
TransactionEngine engine(openLedger_);
|
||||
auto r = engine.applyTransaction (
|
||||
tx, tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN));
|
||||
auto const r = apply(
|
||||
*openLedger_, tx, check ? tapNONE : tapNO_CHECK_SIGN,
|
||||
getConfig(), beast::Journal{});
|
||||
|
||||
// Close the open ledger to see if the transaction was real committed.
|
||||
//
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ripple/protocol/TER.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -65,11 +66,40 @@ struct Fees
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A view into a ledger's state items.
|
||||
/** Information about the notional ledger backing the view. */
|
||||
struct ViewInfo
|
||||
{
|
||||
// Fields for all ledgers
|
||||
bool open = true;
|
||||
LedgerIndex seq = 0;
|
||||
std::uint32_t parentCloseTime = 0;
|
||||
|
||||
The interface provides raw access for state item
|
||||
modification operations. There is no checkpointing
|
||||
// Fields for closed ledgers
|
||||
// Closed means "tx set already determined"
|
||||
//uint256 hash;
|
||||
//uint256 txHash;
|
||||
//uint256 stateHash;
|
||||
//uint256 parentHash;
|
||||
//std::uint64_t coins = 0;
|
||||
//bool validated = false;
|
||||
//int closeTimeRes = 0;
|
||||
|
||||
// For closed ledgers, the time the ledger
|
||||
// closed. For open ledgers, the time the ledger
|
||||
// will close if there's no transactions.
|
||||
//
|
||||
std::uint32_t closeTime = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A view into a ledger.
|
||||
|
||||
This interface provides read access to state
|
||||
and transaction items. There is no checkpointing
|
||||
or calculation of metadata.
|
||||
|
||||
A raw interace is provided for mutable ledgers.
|
||||
*/
|
||||
class BasicView
|
||||
{
|
||||
@@ -80,24 +110,44 @@ public:
|
||||
|
||||
virtual ~BasicView() = default;
|
||||
|
||||
/** Returns information about the ledger. */
|
||||
virtual
|
||||
ViewInfo const&
|
||||
info() const = 0;
|
||||
|
||||
/** Returns true if this reflects an open ledger. */
|
||||
bool
|
||||
open() const
|
||||
{
|
||||
return info().open;
|
||||
}
|
||||
|
||||
/** Returns true if this reflects a closed ledger. */
|
||||
bool
|
||||
closed() const
|
||||
{
|
||||
return ! info().open;
|
||||
}
|
||||
|
||||
/** Returns the close time of the previous ledger. */
|
||||
std::uint32_t
|
||||
parentCloseTime() const
|
||||
{
|
||||
return info().parentCloseTime;
|
||||
}
|
||||
|
||||
/** Returns the sequence number of the base ledger. */
|
||||
LedgerIndex
|
||||
seq() const
|
||||
{
|
||||
return info().seq;
|
||||
}
|
||||
|
||||
/** Returns the fees for the base ledger. */
|
||||
virtual
|
||||
Fees const&
|
||||
fees() const = 0;
|
||||
|
||||
/** Returns the sequence number of the base ledger. */
|
||||
virtual
|
||||
LedgerIndex
|
||||
seq() const = 0;
|
||||
|
||||
/** Return the last known close time.
|
||||
|
||||
The epoch is based on the Ripple network clock.
|
||||
*/
|
||||
virtual
|
||||
std::uint32_t
|
||||
time() const = 0;
|
||||
|
||||
/** Determine if a state item exists.
|
||||
|
||||
@note This can be more efficient than calling read.
|
||||
@@ -204,6 +254,18 @@ public:
|
||||
void
|
||||
destroyCoins (std::uint64_t feeDrops) = 0;
|
||||
|
||||
/** Returns the number of newly inserted transactions.
|
||||
|
||||
This will always be zero for closed ledgers, there
|
||||
is no efficient way to count the number of tx in
|
||||
the map. For views representing open ledgers this
|
||||
starts out as one and gets incremented for each
|
||||
transaction that is applied.
|
||||
*/
|
||||
virtual
|
||||
std::size_t
|
||||
txCount() const = 0;
|
||||
|
||||
/** Returns `true` if a tx exists in the tx map. */
|
||||
virtual
|
||||
bool
|
||||
@@ -214,10 +276,11 @@ public:
|
||||
@param metaData Optional metadata (may be nullptr)
|
||||
*/
|
||||
virtual
|
||||
bool
|
||||
void
|
||||
txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData) = 0;
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
Serializer const> const& metaData) = 0;
|
||||
|
||||
// DEBUG ROUTINE
|
||||
// Return a list of transaction keys in the tx map.
|
||||
@@ -255,11 +318,6 @@ enum ViewFlags
|
||||
//
|
||||
tapENABLE_TESTING = 0x02,
|
||||
|
||||
// Transaction is running against an open ledger
|
||||
// true = failures are not forwarded, check transaction fee
|
||||
// false = debit ledger for consumed funds
|
||||
tapOPEN_LEDGER = 0x10,
|
||||
|
||||
// This is not the transaction's last pass
|
||||
// Transaction can be retried, soft failures allowed
|
||||
tapRETRY = 0x20,
|
||||
@@ -268,6 +326,27 @@ enum ViewFlags
|
||||
tapADMIN = 0x400,
|
||||
};
|
||||
|
||||
inline
|
||||
ViewFlags operator|(
|
||||
ViewFlags const& lhs,
|
||||
ViewFlags const& rhs)
|
||||
{
|
||||
return static_cast<ViewFlags>(
|
||||
static_cast<int>(lhs) |
|
||||
static_cast<int>(rhs));
|
||||
}
|
||||
|
||||
inline
|
||||
ViewFlags
|
||||
operator&(
|
||||
ViewFlags const& lhs,
|
||||
ViewFlags const& rhs)
|
||||
{
|
||||
return static_cast<ViewFlags>(
|
||||
static_cast<int>(lhs) &
|
||||
static_cast<int>(rhs));
|
||||
}
|
||||
|
||||
/** A contextual view into a ledger's state items.
|
||||
|
||||
This refinement of BasicView provides an interface where
|
||||
@@ -422,24 +501,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ViewInfo const&
|
||||
info() const
|
||||
{
|
||||
return view_.info();
|
||||
}
|
||||
|
||||
Fees const&
|
||||
fees() const override
|
||||
{
|
||||
return view_.fees();
|
||||
}
|
||||
|
||||
LedgerIndex
|
||||
seq() const override
|
||||
{
|
||||
return view_.seq();
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
time() const override
|
||||
{
|
||||
return view_.time();
|
||||
}
|
||||
|
||||
bool
|
||||
exists (Keylet const& k) const override
|
||||
{
|
||||
@@ -488,20 +561,25 @@ public:
|
||||
return view_.destroyCoins(feeDrops);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
txCount() const override
|
||||
{
|
||||
return view_.txCount();
|
||||
}
|
||||
|
||||
bool
|
||||
txExists (uint256 const& key) const override
|
||||
{
|
||||
return view_.txExists(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
Serializer const> const& metaData) override
|
||||
{
|
||||
return view_.txInsert(
|
||||
key, txn, metaData);
|
||||
view_.txInsert(key, txn, metaData);
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
@@ -528,24 +606,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ViewInfo const&
|
||||
info() const
|
||||
{
|
||||
return view_.info();
|
||||
}
|
||||
|
||||
Fees const&
|
||||
fees() const override
|
||||
{
|
||||
return view_.fees();
|
||||
}
|
||||
|
||||
LedgerIndex
|
||||
seq() const override
|
||||
{
|
||||
return view_.seq();
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
time() const override
|
||||
{
|
||||
return view_.time();
|
||||
}
|
||||
|
||||
bool
|
||||
exists (Keylet const& k) const override
|
||||
{
|
||||
@@ -594,20 +666,25 @@ public:
|
||||
return view_.destroyCoins(feeDrops);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
txCount() const override
|
||||
{
|
||||
return view_.txCount();
|
||||
}
|
||||
|
||||
bool
|
||||
txExists (uint256 const& key) const override
|
||||
{
|
||||
return view_.txExists(key);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
txInsert (uint256 const& key,
|
||||
std::shared_ptr<Serializer const
|
||||
> const& txn, std::shared_ptr<
|
||||
Serializer const> const& metaData) override
|
||||
{
|
||||
return view_.txInsert(
|
||||
key, txn, metaData);
|
||||
view_.txInsert(key, txn, metaData);
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
|
||||
@@ -1240,7 +1240,7 @@ accountSend (View& view,
|
||||
{
|
||||
// VFALCO Its laborious to have to mutate the
|
||||
// TER based on params everywhere
|
||||
terResult = (view.flags() & tapOPEN_LEDGER)
|
||||
terResult = view.open()
|
||||
? telFAILED_PROCESSING
|
||||
: tecFAILED_PROCESSING;
|
||||
}
|
||||
@@ -1497,7 +1497,7 @@ transferXRP (View& view,
|
||||
// VFALCO Its unfortunate we have to keep
|
||||
// mutating these TER everywhere
|
||||
// FIXME: this logic should be moved to callers maybe?
|
||||
return (view.flags() & tapOPEN_LEDGER)
|
||||
return view.open()
|
||||
? telFAILED_PROCESSING
|
||||
: tecFAILED_PROCESSING;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
namespace ripple {
|
||||
|
||||
// See https://ripple.com/wiki/Transaction_errors
|
||||
|
||||
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity.
|
||||
//
|
||||
enum TER // aka TransactionEngineResult
|
||||
// "Transaction Engine Result"
|
||||
// or Transaction ERror.
|
||||
//
|
||||
enum TER
|
||||
{
|
||||
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
|
||||
|
||||
|
||||
@@ -304,7 +304,8 @@ ripplePathFind (RippleLineCache::pointer const& cache,
|
||||
saMaxAmount.negate();
|
||||
|
||||
boost::optional<PaymentView> sandbox;
|
||||
sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER);
|
||||
sandbox.emplace(*lpLedger, tapNONE);
|
||||
assert(sandbox->open());
|
||||
|
||||
auto rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
@@ -329,7 +330,8 @@ ripplePathFind (RippleLineCache::pointer const& cache,
|
||||
<< "Trying with an extra path element";
|
||||
|
||||
spsComputed.push_back(fullLiquidityPath);
|
||||
sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER);
|
||||
sandbox.emplace(*lpLedger, tapNONE);
|
||||
assert(sandbox->open());
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
*sandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
|
||||
@@ -65,7 +65,7 @@ Json::Value doTransactionEntry (RPC::Context& context)
|
||||
else
|
||||
{
|
||||
Transaction::pointer tpTrans;
|
||||
TransactionMetaSet::pointer tmTrans;
|
||||
TxMeta::pointer tmTrans;
|
||||
|
||||
if (!getTransaction (*lpLedger, uTransID, tpTrans, tmTrans,
|
||||
getApp().getMasterTransaction()))
|
||||
|
||||
@@ -83,7 +83,7 @@ Json::Value doTx (RPC::Context& context)
|
||||
}
|
||||
else
|
||||
{
|
||||
TransactionMetaSet::pointer txMeta;
|
||||
TxMeta::pointer txMeta;
|
||||
|
||||
if (getTransactionMeta (*lgr, txn->getID (), txMeta))
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ addPaymentDeliveredAmount (
|
||||
Json::Value& meta,
|
||||
RPC::Context& context,
|
||||
Transaction::pointer transaction,
|
||||
TransactionMetaSet::pointer transactionMeta)
|
||||
TxMeta::pointer transactionMeta)
|
||||
{
|
||||
// We only want to add a "delivered_amount" field if the transaction
|
||||
// succeeded - otherwise nothing could have been delivered.
|
||||
|
||||
@@ -28,7 +28,7 @@ addPaymentDeliveredAmount (
|
||||
Json::Value&,
|
||||
RPC::Context&,
|
||||
Transaction::pointer,
|
||||
TransactionMetaSet::pointer);
|
||||
TxMeta::pointer);
|
||||
|
||||
} // RPC
|
||||
} // ripple
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ripple/test/jtx/tags.h>
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
@@ -117,6 +118,10 @@ class Env
|
||||
public:
|
||||
beast::unit_test::suite& test;
|
||||
|
||||
/** Configuration used. */
|
||||
// VFALCO NOTE Some code still calls getConfig()
|
||||
Config const config;
|
||||
|
||||
/** The master account. */
|
||||
Account const master;
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <ripple/test/jtx/seq.h>
|
||||
#include <ripple/test/jtx/sig.h>
|
||||
#include <ripple/test/jtx/utility.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/app/paths/FindPaths.h>
|
||||
#include <ripple/app/tx/TransactionEngine.h>
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
@@ -198,11 +198,12 @@ Env::submit (JTx const& jt)
|
||||
if (stx)
|
||||
{
|
||||
ViewFlags flags = tapNONE;
|
||||
flags = flags | tapOPEN_LEDGER;
|
||||
flags = flags | tapENABLE_TESTING;
|
||||
TransactionEngine txe (ledger);
|
||||
// VFALCO Could wrap the log in a Journal here
|
||||
std::tie(ter, didApply) =
|
||||
txe.applyTransaction(*stx, flags);
|
||||
ripple::apply(
|
||||
*ledger, *stx, flags, config,
|
||||
beast::Journal{});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ripple/app/ledger/impl/LedgerMaster.cpp>
|
||||
#include <ripple/app/ledger/impl/LedgerTiming.cpp>
|
||||
#include <ripple/app/ledger/impl/MetaView.cpp>
|
||||
#include <ripple/app/ledger/impl/TxMeta.cpp>
|
||||
|
||||
#include <ripple/app/ledger/tests/common_ledger.cpp>
|
||||
#include <ripple/app/ledger/tests/DeferredCredits.test.cpp>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
|
||||
#include <ripple/app/tx/impl/apply.cpp>
|
||||
#include <ripple/app/tx/impl/BookTip.cpp>
|
||||
#include <ripple/app/tx/impl/CancelOffer.cpp>
|
||||
#include <ripple/app/tx/impl/CancelTicket.cpp>
|
||||
@@ -37,8 +38,7 @@
|
||||
#include <ripple/app/tx/impl/Taker.cpp>
|
||||
#include <ripple/app/tx/impl/TransactionMaster.cpp>
|
||||
#include <ripple/app/tx/impl/Transaction.cpp>
|
||||
#include <ripple/app/tx/impl/TransactionEngine.cpp>
|
||||
#include <ripple/app/tx/impl/TransactionMeta.cpp>
|
||||
#include <ripple/app/tx/impl/ApplyContext.cpp>
|
||||
#include <ripple/app/tx/impl/TransactionAcquire.cpp>
|
||||
#include <ripple/app/tx/impl/Transactor.cpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user