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:
Vinnie Falco
2015-06-26 17:14:06 -07:00
parent b11b9939f4
commit f96ac3db67
71 changed files with 4229 additions and 3615 deletions

View File

@@ -1409,6 +1409,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </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 Include="..\..\src\ripple\app\ledger\InboundLedger.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedgers.h"> <ClInclude Include="..\..\src\ripple\app\ledger\InboundLedgers.h">
@@ -1475,6 +1479,8 @@
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h"> <ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\TxMeta.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\main\Application.cpp"> <ClCompile Include="..\..\src\ripple\app\main\Application.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|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)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|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)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelOffer.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\CancelTicket.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CancelTicket.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\CancelTicket.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\Change.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\Change.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\Change.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateOffer.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CreateOffer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateOffer.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\CreateTicket.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CreateTicket.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\CreateTicket.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\InboundTransactions.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\InboundTransactions.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|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)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\Payment.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetAccount.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetAccount.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetAccount.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetRegularKey.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetRegularKey.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetRegularKey.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetSignerList.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetSignerList.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetSignerList.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\SetTrust.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetTrust.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ripple\app\tx\impl\SetTrust.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\SignerEntries.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SignerEntries.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|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)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMaster.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\Transactor.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -1849,12 +1879,8 @@
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h"> <ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionEngine.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h"> <ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMeta.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\base_uint.h"> <ClInclude Include="..\..\src\ripple\basics\base_uint.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\basics\BasicConfig.h"> <ClInclude Include="..\..\src\ripple\basics\BasicConfig.h">
@@ -1869,6 +1895,8 @@
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h"> <ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\basics\contract.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\CountedObject.h"> <ClInclude Include="..\..\src\ripple\basics\CountedObject.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\basics\DecayingSample.h"> <ClInclude Include="..\..\src\ripple\basics\DecayingSample.h">

View File

@@ -2145,6 +2145,9 @@
<ClCompile Include="..\..\src\ripple\app\ledger\impl\MetaView.cpp"> <ClCompile Include="..\..\src\ripple\app\ledger\impl\MetaView.cpp">
<Filter>ripple\app\ledger\impl</Filter> <Filter>ripple\app\ledger\impl</Filter>
</ClCompile> </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"> <ClInclude Include="..\..\src\ripple\app\ledger\InboundLedger.h">
<Filter>ripple\app\ledger</Filter> <Filter>ripple\app\ledger</Filter>
</ClInclude> </ClInclude>
@@ -2217,6 +2220,9 @@
<ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h"> <ClInclude Include="..\..\src\ripple\app\ledger\TransactionStateSF.h">
<Filter>ripple\app\ledger</Filter> <Filter>ripple\app\ledger</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\TxMeta.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\main\Application.cpp"> <ClCompile Include="..\..\src\ripple\app\main\Application.cpp">
<Filter>ripple\app\main</Filter> <Filter>ripple\app\main</Filter>
</ClCompile> </ClCompile>
@@ -2454,6 +2460,18 @@
<ClCompile Include="..\..\src\ripple\app\tests\Regression_test.cpp"> <ClCompile Include="..\..\src\ripple\app\tests\Regression_test.cpp">
<Filter>ripple\app\tests</Filter> <Filter>ripple\app\tests</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </ClCompile>
@@ -2463,18 +2481,33 @@
<ClCompile Include="..\..\src\ripple\app\tx\impl\CancelOffer.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CancelOffer.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CancelTicket.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\Change.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CreateOffer.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\CreateTicket.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\InboundTransactions.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </ClCompile>
@@ -2493,18 +2526,33 @@
<ClCompile Include="..\..\src\ripple\app\tx\impl\Payment.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\Payment.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetAccount.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetRegularKey.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetSignerList.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SetTrust.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\SignerEntries.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </ClCompile>
@@ -2523,15 +2571,9 @@
<ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionAcquire.cpp"> <ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionAcquire.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\TransactionMaster.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple\app\tx\impl\Transactor.cpp">
<Filter>ripple\app\tx\impl</Filter> <Filter>ripple\app\tx\impl</Filter>
</ClCompile> </ClCompile>
@@ -2568,15 +2610,9 @@
<ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h"> <ClInclude Include="..\..\src\ripple\app\tx\TransactionAcquire.h">
<Filter>ripple\app\tx</Filter> <Filter>ripple\app\tx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionEngine.h">
<Filter>ripple\app\tx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h"> <ClInclude Include="..\..\src\ripple\app\tx\TransactionMaster.h">
<Filter>ripple\app\tx</Filter> <Filter>ripple\app\tx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\app\tx\TransactionMeta.h">
<Filter>ripple\app\tx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\base_uint.h"> <ClInclude Include="..\..\src\ripple\basics\base_uint.h">
<Filter>ripple\basics</Filter> <Filter>ripple\basics</Filter>
</ClInclude> </ClInclude>
@@ -2598,6 +2634,9 @@
<ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h"> <ClInclude Include="..\..\src\ripple\basics\CheckLibraryVersions.h">
<Filter>ripple\basics</Filter> <Filter>ripple\basics</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\basics\contract.h">
<Filter>ripple\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\CountedObject.h"> <ClInclude Include="..\..\src\ripple\basics\CountedObject.h">
<Filter>ripple\basics</Filter> <Filter>ripple\basics</Filter>
</ClInclude> </ClInclude>

View File

@@ -36,7 +36,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit)
mTxn = std::make_shared<STTx> (std::ref (txnIt)); mTxn = std::make_shared<STTx> (std::ref (txnIt));
mRawMeta = sit.getVL (); mRawMeta = sit.getVL ();
mMeta = std::make_shared<TransactionMetaSet> (mTxn->getTransactionID (), mMeta = std::make_shared<TxMeta> (mTxn->getTransactionID (),
ledger->getLedgerSeq (), mRawMeta); ledger->getLedgerSeq (), mRawMeta);
mAffected = mMeta->getAffectedAccounts (); mAffected = mMeta->getAffectedAccounts ();
mResult = mMeta->getResultTER (); mResult = mMeta->getResultTER ();
@@ -44,7 +44,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit)
} }
AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger,
STTx::ref txn, TransactionMetaSet::ref met) STTx::ref txn, TxMeta::ref met)
: mLedger (ledger) : mLedger (ledger)
, mTxn (txn) , mTxn (txn)
, mMeta (met) , mMeta (met)

View File

@@ -53,14 +53,14 @@ public:
public: public:
AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit); AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit);
AcceptedLedgerTx (Ledger::ref ledger, STTx::ref, AcceptedLedgerTx (Ledger::ref ledger, STTx::ref,
TransactionMetaSet::ref); TxMeta::ref);
AcceptedLedgerTx (Ledger::ref ledger, STTx::ref, TER result); AcceptedLedgerTx (Ledger::ref ledger, STTx::ref, TER result);
STTx::ref getTxn () const STTx::ref getTxn () const
{ {
return mTxn; return mTxn;
} }
TransactionMetaSet::ref getMeta () const TxMeta::ref getMeta () const
{ {
return mMeta; return mMeta;
} }
@@ -105,7 +105,7 @@ public:
private: private:
Ledger::pointer mLedger; Ledger::pointer mLedger;
STTx::pointer mTxn; STTx::pointer mTxn;
TransactionMetaSet::pointer mMeta; TxMeta::pointer mMeta;
TER mResult; TER mResult;
boost::container::flat_set<AccountID> mAffected; boost::container::flat_set<AccountID> mAffected;
Blob mRawMeta; Blob mRawMeta;

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/ledger/Ledger.h> #include <ripple/app/ledger/Ledger.h>
#include <ripple/basics/contract.h>
#include <ripple/app/ledger/AcceptedLedger.h> #include <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/InboundLedgers.h> #include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerMaster.h> #include <ripple/app/ledger/LedgerMaster.h>
@@ -81,9 +82,6 @@ makeGenesisAccount (AccountID const& id,
Ledger::Ledger (RippleAddress const& masterPublicKey, Ledger::Ledger (RippleAddress const& masterPublicKey,
std::uint64_t balanceInDrops) std::uint64_t balanceInDrops)
: mTotCoins (balanceInDrops) : mTotCoins (balanceInDrops)
, seq_ (1) // First Ledger
, mCloseTime (0)
, mParentCloseTime (0)
, mCloseResolution (ledgerDefaultTimeResolution) , mCloseResolution (ledgerDefaultTimeResolution)
, mCloseFlags (0) , mCloseFlags (0)
, mImmutable (false) , mImmutable (false)
@@ -94,13 +92,15 @@ Ledger::Ledger (RippleAddress const& masterPublicKey,
// VFALCO Needs audit // VFALCO Needs audit
, fees_(getFees(*this, getConfig())) , fees_(getFees(*this, getConfig()))
{ {
// first ledger
info_.seq = 1;
auto sle = makeGenesisAccount( auto sle = makeGenesisAccount(
calcAccountID(masterPublicKey), calcAccountID(masterPublicKey),
balanceInDrops); balanceInDrops);
WriteLog (lsTRACE, Ledger) WriteLog (lsTRACE, Ledger)
<< "root account: " << sle->getJson(0); << "root account: " << sle->getJson(0);
unchecked_insert(std::move(sle)); unchecked_insert(std::move(sle));
stateMap_->flushDirty (hotACCOUNT_NODE, seq_); stateMap_->flushDirty (hotACCOUNT_NODE, info_.seq);
} }
Ledger::Ledger (uint256 const& parentHash, Ledger::Ledger (uint256 const& parentHash,
@@ -117,9 +117,6 @@ Ledger::Ledger (uint256 const& parentHash,
, mTransHash (transHash) , mTransHash (transHash)
, mAccountHash (accountHash) , mAccountHash (accountHash)
, mTotCoins (totCoins) , mTotCoins (totCoins)
, seq_ (ledgerSeq)
, mCloseTime (closeTime)
, mParentCloseTime (parentCloseTime)
, mCloseResolution (closeResolution) , mCloseResolution (closeResolution)
, mCloseFlags (closeFlags) , mCloseFlags (closeFlags)
, mImmutable (true) , mImmutable (true)
@@ -131,6 +128,10 @@ Ledger::Ledger (uint256 const& parentHash,
// VFALCO Needs audit // VFALCO Needs audit
, fees_(getFees(*this, getConfig())) , fees_(getFees(*this, getConfig()))
{ {
info_.seq = ledgerSeq;
info_.parentCloseTime = parentCloseTime;
info_.closeTime = closeTime;
updateHash (); updateHash ();
loaded = true; loaded = true;
@@ -157,12 +158,8 @@ Ledger::Ledger (Ledger const& ledger,
bool isMutable) bool isMutable)
: mParentHash (ledger.mParentHash) : mParentHash (ledger.mParentHash)
, mTotCoins (ledger.mTotCoins) , mTotCoins (ledger.mTotCoins)
, seq_ (ledger.seq_)
, mCloseTime (ledger.mCloseTime)
, mParentCloseTime (ledger.mParentCloseTime)
, mCloseResolution (ledger.mCloseResolution) , mCloseResolution (ledger.mCloseResolution)
, mCloseFlags (ledger.mCloseFlags) , mCloseFlags (ledger.mCloseFlags)
, mClosed (ledger.mClosed)
, mValidated (ledger.mValidated) , mValidated (ledger.mValidated)
, mAccepted (ledger.mAccepted) , mAccepted (ledger.mAccepted)
, mImmutable (!isMutable) , mImmutable (!isMutable)
@@ -170,16 +167,15 @@ Ledger::Ledger (Ledger const& ledger,
, stateMap_ (ledger.stateMap_->snapShot (isMutable)) , stateMap_ (ledger.stateMap_->snapShot (isMutable))
// VFALCO Needs audit // VFALCO Needs audit
, fees_(getFees(*this, getConfig())) , fees_(getFees(*this, getConfig()))
, info_ (ledger.info_)
{ {
updateHash (); updateHash ();
} }
// Create a new ledger that follows this one // Create a new open ledger that follows this one
Ledger::Ledger (bool /* dummy */, Ledger::Ledger (bool /* dummy */,
Ledger& prevLedger) Ledger& prevLedger)
: mTotCoins (prevLedger.mTotCoins) : mTotCoins (prevLedger.mTotCoins)
, seq_ (prevLedger.seq_ + 1)
, mParentCloseTime (prevLedger.mCloseTime)
, mCloseResolution (prevLedger.mCloseResolution) , mCloseResolution (prevLedger.mCloseResolution)
, mCloseFlags (0) , mCloseFlags (0)
, mImmutable (false) , mImmutable (false)
@@ -189,6 +185,10 @@ Ledger::Ledger (bool /* dummy */,
// VFALCO Needs audit // VFALCO Needs audit
, fees_(getFees(*this, getConfig())) , fees_(getFees(*this, getConfig()))
{ {
info_.open = true;
info_.seq = prevLedger.info_.seq + 1;
info_.parentCloseTime =
prevLedger.info_.closeTime;
prevLedger.updateHash (); prevLedger.updateHash ();
mParentHash = prevLedger.getHash (); mParentHash = prevLedger.getHash ();
@@ -196,16 +196,17 @@ Ledger::Ledger (bool /* dummy */,
assert (mParentHash.isNonZero ()); assert (mParentHash.isNonZero ());
mCloseResolution = getNextLedgerTimeResolution (prevLedger.mCloseResolution, 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); getApp().getOPs ().getCloseTimeNC (), mCloseResolution);
} }
else 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) Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime)
: mTotCoins (0) : mTotCoins (0)
, seq_ (ledgerSeq)
, mCloseTime (closeTime)
, mParentCloseTime (0)
, mCloseResolution (ledgerDefaultTimeResolution) , mCloseResolution (ledgerDefaultTimeResolution)
, mCloseFlags (0) , mCloseFlags (0)
, mImmutable (false) , mImmutable (false)
@@ -235,6 +233,9 @@ Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime)
// VFALCO Needs audit // VFALCO Needs audit
, fees_(getFees(*this, getConfig())) , 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 // VFALCO This has to match addRaw
mHash = sha512Half( mHash = sha512Half(
HashPrefix::ledgerMaster, HashPrefix::ledgerMaster,
std::uint32_t(seq_), std::uint32_t(info_.seq),
std::uint64_t(mTotCoins), std::uint64_t(mTotCoins),
mParentHash, mParentHash,
mTransHash, mTransHash,
mAccountHash, mAccountHash,
std::uint32_t(mParentCloseTime), std::uint32_t(info_.parentCloseTime),
std::uint32_t(mCloseTime), std::uint32_t(info_.closeTime),
std::uint8_t(mCloseResolution), std::uint8_t(mCloseResolution),
std::uint8_t(mCloseFlags)); std::uint8_t(mCloseFlags));
mValidHash = true; mValidHash = true;
@@ -292,13 +293,13 @@ void Ledger::setRaw (SerialIter& sit, bool hasPrefix)
if (hasPrefix) if (hasPrefix)
sit.get32 (); sit.get32 ();
seq_ = sit.get32 (); info_.seq = sit.get32 ();
mTotCoins = sit.get64 (); mTotCoins = sit.get64 ();
mParentHash = sit.get256 (); mParentHash = sit.get256 ();
mTransHash = sit.get256 (); mTransHash = sit.get256 ();
mAccountHash = sit.get256 (); mAccountHash = sit.get256 ();
mParentCloseTime = sit.get32 (); info_.parentCloseTime = sit.get32 ();
mCloseTime = sit.get32 (); info_.closeTime = sit.get32 ();
mCloseResolution = sit.get8 (); mCloseResolution = sit.get8 ();
mCloseFlags = sit.get8 (); mCloseFlags = sit.get8 ();
updateHash (); updateHash ();
@@ -310,13 +311,13 @@ void Ledger::setRaw (SerialIter& sit, bool hasPrefix)
void Ledger::addRaw (Serializer& s) const void Ledger::addRaw (Serializer& s) const
{ {
s.add32 (seq_); s.add32 (info_.seq);
s.add64 (mTotCoins); s.add64 (mTotCoins);
s.add256 (mParentHash); s.add256 (mParentHash);
s.add256 (mTransHash); s.add256 (mTransHash);
s.add256 (mAccountHash); s.add256 (mAccountHash);
s.add32 (mParentCloseTime); s.add32 (info_.parentCloseTime);
s.add32 (mCloseTime); s.add32 (info_.closeTime);
s.add8 (mCloseResolution); s.add8 (mCloseResolution);
s.add8 (mCloseFlags); s.add8 (mCloseFlags);
} }
@@ -326,8 +327,9 @@ void Ledger::setAccepted (
{ {
// Used when we witnessed the consensus. Rounds the close time, updates the // Used when we witnessed the consensus. Rounds the close time, updates the
// hash, and sets the ledger accepted and immutable. // hash, and sets the ledger accepted and immutable.
assert (mClosed && !mAccepted); assert (closed() && !mAccepted);
mCloseTime = correctCloseTime ? roundCloseTime (closeTime, closeResolution) info_.closeTime = correctCloseTime
? roundCloseTime (closeTime, closeResolution)
: closeTime; : closeTime;
mCloseResolution = closeResolution; mCloseResolution = closeResolution;
mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime; mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
@@ -338,9 +340,10 @@ void Ledger::setAccepted (
void Ledger::setAccepted () void Ledger::setAccepted ()
{ {
// used when we acquired the ledger // 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) if ((mCloseFlags & sLCF_NoConsensusTime) == 0)
mCloseTime = roundCloseTime (mCloseTime, mCloseResolution); info_.closeTime = roundCloseTime(
info_.closeTime, mCloseResolution);
mAccepted = true; mAccepted = true;
setImmutable (); setImmutable ();
@@ -396,7 +399,7 @@ getTransaction (Ledger const& ledger,
bool bool
getTransaction (Ledger const& ledger, getTransaction (Ledger const& ledger,
uint256 const& txID, Transaction::pointer& txn, uint256 const& txID, Transaction::pointer& txn,
TransactionMetaSet::pointer& meta, TxMeta::pointer& meta,
TransactionMaster& cache) TransactionMaster& cache)
{ {
SHAMapTreeNode::TNType type; SHAMapTreeNode::TNType type;
@@ -428,7 +431,7 @@ getTransaction (Ledger const& ledger,
else else
it.getVL (); // skip transaction it.getVL (); // skip transaction
meta = std::make_shared<TransactionMetaSet> ( meta = std::make_shared<TxMeta> (
txID, ledger.seq(), it.getVL ()); txID, ledger.seq(), it.getVL ());
} }
else else
@@ -442,7 +445,7 @@ getTransaction (Ledger const& ledger,
} }
bool getTransactionMeta (Ledger const& ledger, bool getTransactionMeta (Ledger const& ledger,
uint256 const& txID, TransactionMetaSet::pointer& meta) uint256 const& txID, TxMeta::pointer& meta)
{ {
SHAMapTreeNode::TNType type; SHAMapTreeNode::TNType type;
auto const item = auto const item =
@@ -456,7 +459,7 @@ bool getTransactionMeta (Ledger const& ledger,
SerialIter it (item->slice()); SerialIter it (item->slice());
it.getVL (); // skip transaction 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; return true;
} }
@@ -506,7 +509,7 @@ bool Ledger::saveValidatedLedger (bool current)
WriteLog (lsFATAL, Ledger) << "sAL: " << getAccountHash () WriteLog (lsFATAL, Ledger) << "sAL: " << getAccountHash ()
<< " != " << stateMap_->getHash (); << " != " << stateMap_->getHash ();
WriteLog (lsFATAL, Ledger) << "saveAcceptedLedger: seq=" WriteLog (lsFATAL, Ledger) << "saveAcceptedLedger: seq="
<< seq_ << ", current=" << current; << info_.seq << ", current=" << current;
assert (false); assert (false);
} }
@@ -529,7 +532,7 @@ bool Ledger::saveValidatedLedger (bool current)
catch (...) catch (...)
{ {
WriteLog (lsWARNING, Ledger) << "An accepted ledger was missing nodes"; 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 // Clients can now trust the database for information about this
// ledger sequence. // ledger sequence.
getApp().pendingSaves().erase(getLedgerSeq()); getApp().pendingSaves().erase(getLedgerSeq());
@@ -538,7 +541,7 @@ bool Ledger::saveValidatedLedger (bool current)
{ {
auto db = getApp().getLedgerDB ().checkoutDb(); 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 else
WriteLog (lsWARNING, Ledger) WriteLog (lsWARNING, Ledger)
<< "Transaction in ledger " << seq_ << "Transaction in ledger " << info_.seq
<< " affects no accounts"; << " affects no accounts";
*db << *db <<
@@ -621,9 +624,9 @@ bool Ledger::saveValidatedLedger (bool current)
// TODO(tom): ARG! // TODO(tom): ARG!
*db << boost::str (addLedger % *db << boost::str (addLedger %
to_string (getHash ()) % seq_ % to_string (mParentHash) % to_string (getHash ()) % info_.seq % to_string (mParentHash) %
beast::lexicalCastThrow <std::string> (mTotCoins) % mCloseTime % beast::lexicalCastThrow <std::string> (mTotCoins) % info_.closeTime %
mParentCloseTime % mCloseResolution % mCloseFlags % info_.parentCloseTime % mCloseResolution % mCloseFlags %
to_string (mAccountHash) % to_string (mTransHash)); to_string (mAccountHash) % to_string (mTransHash));
} }
@@ -875,13 +878,13 @@ bool Ledger::isAcquiringAS (void) const
boost::posix_time::ptime Ledger::getCloseTime () const boost::posix_time::ptime Ledger::getCloseTime () const
{ {
return ptFromSeconds (mCloseTime); return ptFromSeconds (info_.closeTime);
} }
void Ledger::setCloseTime (boost::posix_time::ptime ptm) void Ledger::setCloseTime (boost::posix_time::ptime ptm)
{ {
assert (!mImmutable); assert (!mImmutable);
mCloseTime = iToSeconds (ptm); info_.closeTime = iToSeconds (ptm);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -969,55 +972,50 @@ Ledger::unchecked_replace(
auto const ours = std::move(sle); auto const ours = std::move(sle);
} }
std::size_t
Ledger::txCount() const
{
// Always zero for closed ledgers.
return 0;
}
bool bool
Ledger::txExists (uint256 const& key) const Ledger::txExists (uint256 const& key) const
{ {
return txMap().hasItem (key); return txMap().hasItem (key);
} }
bool void
Ledger::txInsert (uint256 const& key, Ledger::txInsert (uint256 const& key,
std::shared_ptr<Serializer const> const& txn, std::shared_ptr<Serializer const
std::shared_ptr<Serializer const> const& metaData) > const& txn, std::shared_ptr<
Serializer const> const& metaData)
{ {
if (metaData) if (metaData)
{ {
// low-level - just add to table // 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 (txn->peekData ());
s.addVL (metaData->peekData ()); s.addVL (metaData->peekData ());
auto item = std::make_shared< auto item = std::make_shared<
SHAMapItem const> (key, std::move(s)); SHAMapItem const> (key, std::move(s));
if (! txMap().addGiveItem
// VFALCO Should just terminate the app (std::move(item), true, true))
// with a fatal error here. LogicError("duplicate_tx: " + to_string(key));
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);
} }
else else
{ {
// low-level - just add to table // low-level - just add to table
auto item = std::make_shared< auto item = std::make_shared<
SHAMapItem const> (key, txn->peekData ()); SHAMapItem const>(key, txn->peekData());
if (! txMap().addGiveItem(
if (! txMap().addGiveItem (std::move(item), true, false)) std::move(item), true, false))
{ LogicError("duplicate_tx: " + to_string(key));
WriteLog (lsWARNING, Ledger)
<< "Attempt to add transaction to ledger that already had it";
return false;
}
} }
// VFALCO TODO We could touch only the txMap // VFALCO TODO We could touch only the txMap
touch(); touch();
return true;
} }
std::vector<uint256> std::vector<uint256>
@@ -1074,7 +1072,7 @@ void Ledger::visitStateItems (std::function<void (SLE::ref)> function) const
if (mHash.isNonZero ()) if (mHash.isNonZero ())
{ {
getApp().getInboundLedgers().acquire( getApp().getInboundLedgers().acquire(
mHash, seq_, InboundLedger::fcGENERIC); mHash, info_.seq, InboundLedger::fcGENERIC);
} }
throw; throw;
} }
@@ -1164,10 +1162,10 @@ bool Ledger::assertSane ()
// VFALCO TODO Document this skip list concept // VFALCO TODO Document this skip list concept
void Ledger::updateSkipList () void Ledger::updateSkipList ()
{ {
if (seq_ == 0) // genesis ledger has no previous ledger if (info_.seq == 0) // genesis ledger has no previous ledger
return; return;
std::uint32_t prevIndex = seq_ - 1; std::uint32_t prevIndex = info_.seq - 1;
// update record of every 256th ledger // update record of every 256th ledger
if ((prevIndex & 0xff) == 0) if ((prevIndex & 0xff) == 0)
@@ -1287,6 +1285,7 @@ qualityDirDescriber (
sle->setFieldU64 (sfExchangeRate, uRate); sle->setFieldU64 (sfExchangeRate, uRate);
if (isNew) if (isNew)
{ {
// VFALCO NO! This shouldn't be done here!
getApp().getOrderBookDB().addOrderBook( getApp().getOrderBookDB().addOrderBook(
{{uTakerPaysCurrency, uTakerPaysIssuer}, {{uTakerPaysCurrency, uTakerPaysIssuer},
{uTakerGetsCurrency, uTakerGetsIssuer}}); {uTakerGetsCurrency, uTakerGetsIssuer}});

View File

@@ -20,16 +20,16 @@
#ifndef RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED #ifndef RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
#define RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED #define RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
#include <ripple/shamap/SHAMap.h> #include <ripple/app/ledger/TxMeta.h>
#include <ripple/app/tx/Transaction.h>
#include <ripple/app/tx/TransactionMeta.h>
#include <ripple/ledger/SLECache.h> #include <ripple/ledger/SLECache.h>
#include <ripple/ledger/View.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/Indexes.h>
#include <ripple/protocol/STLedgerEntry.h> #include <ripple/protocol/STLedgerEntry.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/Serializer.h> #include <ripple/protocol/Serializer.h>
#include <ripple/protocol/Book.h> #include <ripple/protocol/Book.h>
#include <ripple/shamap/SHAMap.h>
#include <beast/utility/Journal.h> #include <beast/utility/Journal.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <mutex> #include <mutex>
@@ -118,24 +118,18 @@ public:
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
ViewInfo const&
info() const
{
return info_;
}
Fees const& Fees const&
fees() const override fees() const override
{ {
return fees_; return fees_;
} }
LedgerIndex
seq() const override
{
return seq_;
}
std::uint32_t
time() const override
{
return mParentCloseTime;
}
bool bool
exists (Keylet const& k) const override; exists (Keylet const& k) const override;
@@ -161,10 +155,13 @@ public:
mTotCoins -= feeDrops; mTotCoins -= feeDrops;
} }
std::size_t
txCount() const override;
bool bool
txExists (uint256 const& key) const override; txExists (uint256 const& key) const override;
bool void
txInsert (uint256 const& key, txInsert (uint256 const& key,
std::shared_ptr<Serializer const std::shared_ptr<Serializer const
> const& txn, std::shared_ptr< > const& txn, std::shared_ptr<
@@ -187,9 +184,9 @@ public:
mValidHash = false; mValidHash = false;
} }
void setClosed () void setClosed()
{ {
mClosed = true; info_.open = false;
} }
void setValidated() void setValidated()
@@ -204,10 +201,10 @@ public:
void setImmutable (); void setImmutable ();
// VFALCO Rename to closed // DEPRECATED use closed()
bool isClosed () const bool isClosed () const
{ {
return mClosed; return closed();
} }
bool isAccepted () const bool isAccepted () const
@@ -225,10 +222,13 @@ public:
return mImmutable; return mImmutable;
} }
// Indicates that all ledger entries
// are available locally. For example,
// all in the NodeStore and memory.
void setFull () void setFull ()
{ {
txMap_->setLedgerSeq (seq_); txMap_->setLedgerSeq (info_.seq);
stateMap_->setLedgerSeq (seq_); stateMap_->setLedgerSeq (info_.seq);
} }
// ledger signature operations // ledger signature operations
@@ -266,20 +266,22 @@ public:
mTotCoins = totCoins; mTotCoins = totCoins;
} }
// DEPRECATED
std::uint32_t getCloseTimeNC () const std::uint32_t getCloseTimeNC () const
{ {
return mCloseTime; return info_.closeTime;
} }
// DEPRECATED Use parentCloseTime()
std::uint32_t getParentCloseTimeNC () const std::uint32_t getParentCloseTimeNC () const
{ {
return mParentCloseTime; return info_.parentCloseTime;
} }
// DEPRECATED // DEPRECATED Use seq()
std::uint32_t getLedgerSeq () const std::uint32_t getLedgerSeq () const
{ {
return seq_; return info_.seq;
} }
int getCloseResolution () const int getCloseResolution () const
@@ -293,10 +295,10 @@ public:
} }
// close time functions // close time functions
void setCloseTime (std::uint32_t ct) void setCloseTime (std::uint32_t when)
{ {
assert (!mImmutable); assert (!mImmutable);
mCloseTime = ct; info_.closeTime = when;
} }
void setCloseTime (boost::posix_time::ptime); void setCloseTime (boost::posix_time::ptime);
@@ -383,6 +385,7 @@ public:
return mBaseFee; return mBaseFee;
} }
// DEPRECATED use fees()
std::uint64_t getReserve (int increments) const std::uint64_t getReserve (int increments) const
{ {
// Returns the required reserve in drops // Returns the required reserve in drops
@@ -391,6 +394,7 @@ public:
+ mReserveBase; + mReserveBase;
} }
// DEPRECATED use fees()
std::uint64_t getReserveInc () const std::uint64_t getReserveInc () const
{ {
deprecatedUpdateCachedFees (); deprecatedUpdateCachedFees ();
@@ -444,20 +448,12 @@ private:
uint256 mTransHash; uint256 mTransHash;
uint256 mAccountHash; uint256 mAccountHash;
std::uint64_t mTotCoins; 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) // the resolution for this ledger close time (2-120 seconds)
int mCloseResolution; int mCloseResolution;
// flags indicating how this ledger close took place // flags indicating how this ledger close took place
std::uint32_t mCloseFlags; std::uint32_t mCloseFlags;
bool mClosed = false;
bool mValidated = false; bool mValidated = false;
bool mValidHash = false; bool mValidHash = false;
bool mAccepted = false; bool mAccepted = false;
@@ -470,6 +466,7 @@ private:
std::mutex mutable mutex_; std::mutex mutable mutex_;
Fees fees_; Fees fees_;
ViewInfo info_;
// Ripple cost of the reference transaction // Ripple cost of the reference transaction
std::uint64_t mutable mBaseFee = 0; std::uint64_t mutable mBaseFee = 0;
@@ -561,13 +558,13 @@ getTransaction (Ledger const& ledger,
bool bool
getTransaction (Ledger const& ledger, getTransaction (Ledger const& ledger,
uint256 const& transID, Transaction::pointer & txn, uint256 const& transID, Transaction::pointer & txn,
TransactionMetaSet::pointer & txMeta, TxMeta::pointer & txMeta,
TransactionMaster& cache); TransactionMaster& cache);
bool bool
getTransactionMeta (Ledger const&, getTransactionMeta (Ledger const&,
uint256 const& transID, uint256 const& transID,
TransactionMetaSet::pointer & txMeta); TxMeta::pointer & txMeta);
// VFALCO NOTE This is called from only one place // VFALCO NOTE This is called from only one place
bool bool

View File

@@ -80,10 +80,9 @@ public:
*/ */
void applyTransactions ( void applyTransactions (
SHAMap const* set, SHAMap const* set,
Ledger::ref applyLedger, BasicView& applyView,
Ledger::ref checkLedger, Ledger::ref checkLedger,
CanonicalTXSet& retriableTransactions, CanonicalTXSet& retriableTransactions,
bool openLgr,
bool enableTesting = false); bool enableTesting = false);
} // ripple } // ripple

View File

@@ -133,7 +133,7 @@ static
void void
log_one(Ledger::pointer ledger, uint256 const& tx, char const* msg) log_one(Ledger::pointer ledger, uint256 const& tx, char const* msg)
{ {
TransactionMetaSet::pointer metaData; TxMeta::pointer metaData;
getTransactionMeta(*ledger, tx, metaData); getTransactionMeta(*ledger, tx, metaData);
if (metaData != nullptr) if (metaData != nullptr)
@@ -154,9 +154,9 @@ void
log_metadata_difference(Ledger::pointer builtLedger, Ledger::pointer validLedger, log_metadata_difference(Ledger::pointer builtLedger, Ledger::pointer validLedger,
uint256 const& tx) uint256 const& tx)
{ {
TransactionMetaSet::pointer validMetaData; TxMeta::pointer validMetaData;
getTransactionMeta(*validLedger, tx, validMetaData); getTransactionMeta(*validLedger, tx, validMetaData);
TransactionMetaSet::pointer builtMetaData; TxMeta::pointer builtMetaData;
getTransactionMeta(*builtLedger, tx, builtMetaData); getTransactionMeta(*builtLedger, tx, builtMetaData);
assert(validMetaData != nullptr || builtMetaData != nullptr); assert(validMetaData != nullptr || builtMetaData != nullptr);

View File

@@ -166,7 +166,7 @@ void fillJson (Object& json, LedgerFill const& fill)
SerialIter tsit (make_Slice(vl)); SerialIter tsit (make_Slice(vl));
STTx txn (tsit); STTx txn (tsit);
TransactionMetaSet meta ( TxMeta meta (
item->getTag (), ledger.getLedgerSeq(), sit.getVL ()); item->getTag (), ledger.getLedgerSeq(), sit.getVL ());
auto&& txJson = appendObject (txns); auto&& txJson = appendObject (txns);

View File

@@ -20,13 +20,14 @@
#ifndef RIPPLE_LEDGER_METAVIEW_H_INCLUDED #ifndef RIPPLE_LEDGER_METAVIEW_H_INCLUDED
#define RIPPLE_LEDGER_METAVIEW_H_INCLUDED #define RIPPLE_LEDGER_METAVIEW_H_INCLUDED
#include <ripple/app/tx/TransactionMeta.h>
#include <ripple/ledger/View.h> #include <ripple/ledger/View.h>
#include <ripple/app/ledger/TxMeta.h>
#include <ripple/basics/CountedObject.h> #include <ripple/basics/CountedObject.h>
#include <ripple/basics/UnorderedContainers.h> #include <ripple/basics/UnorderedContainers.h>
#include <ripple/protocol/Keylet.h> #include <ripple/protocol/Keylet.h>
#include <ripple/protocol/Serializer.h> #include <ripple/protocol/Serializer.h>
#include <ripple/protocol/STLedgerEntry.h> #include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/STTx.h>
#include <beast/utility/noexcept.h> #include <beast/utility/noexcept.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <list> #include <list>
@@ -35,6 +36,25 @@
namespace ripple { 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. /** 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. 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 // Note that this class needs to be
// somewhat light-weight copy constructible. // somewhat light-weight copy constructible.
BasicView const* parent_; BasicView const& base_;
ViewFlags flags_ = tapNONE; ViewFlags flags_ = tapNONE;
LedgerIndex seq_; ViewInfo info_;
std::uint32_t time_; // should be Clock::time_point
tx_list txs_; tx_list txs_;
item_list items_; item_list items_;
TransactionMetaSet meta_;
std::uint32_t destroyedCoins_ = 0; std::uint32_t destroyedCoins_ = 0;
boost::optional<STAmount> deliverAmount_;
public: public:
MetaView() = delete; MetaView() = delete;
MetaView(MetaView const&) = delete;
MetaView& operator= (MetaView const&) = delete; MetaView& operator= (MetaView const&) = delete;
/** Create a shallow copy of a MetaView. /** 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. are shared with the other view.
The copy has the same Info values.
It is only safe to use the BasicView modification It is only safe to use the BasicView modification
functions. Using View modification functions will functions. Using View modification functions will
break invariants. 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, // VFALCO Refactor to disallow at compile time,
// breaking invariants on a shallow copy. // 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: 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 It is only safe to use the BasicView modification
functions. Using View modification functions will functions. Using View modification functions will
break invariants. break invariants.
@note This is for converting a closed ledger @param parent A view representing the previous
into an open ledger. ledger that this open ledger follows.
@note A pointer is used to prevent confusion
with copy construction.
*/ */
// VFALCO Refactor to disallow at compile time, MetaView (open_ledger_t,
// breaking invariants on a shallow copy. BasicView const& parent);
//
MetaView (BasicView const* parent, /** Create a nested MetaView.
LedgerIndex seq, std::uint32_t time,
Effects:
The ViewInfo is copied from the base.
*/
MetaView (BasicView const& base,
ViewFlags flags); 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 // BasicView
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
ViewInfo const&
info() const
{
return info_;
}
Fees const& Fees const&
fees() const override fees() const override
{ {
return parent_->fees(); return base_.fees();
}
LedgerIndex
seq() const override
{
return seq_;
}
std::uint32_t
time() const override
{
return time_;
} }
bool bool
@@ -213,10 +199,13 @@ public:
void void
destroyCoins (std::uint64_t feeDrops) override; destroyCoins (std::uint64_t feeDrops) override;
std::size_t
txCount() const override;
bool bool
txExists (uint256 const& key) const override; txExists (uint256 const& key) const override;
bool void
txInsert (uint256 const& key, txInsert (uint256 const& key,
std::shared_ptr<Serializer const std::shared_ptr<Serializer const
> const& txn, std::shared_ptr< > 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 `to` must contain contents identical to the
view passed upon construction, else undefined parent view passed upon construction, else
behavior will result. undefined behavior will result.
After a call to apply(), the only valid operation that After a call to apply(), the only valid operation
may be performed on this is a call to the destructor. on the object is a call to the destructor.
*/ */
void 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 // For diagnostics
Json::Value getJson (int) const; Json::Value getJson (int) const;
void calcRawMeta (Serializer&, TER result, std::uint32_t index);
void setDeliveredAmount (STAmount const& amt) void setDeliveredAmount (STAmount const& amt)
{ {
meta_.setDeliveredAmount (amt); deliverAmount_ = amt;
} }
private: private:
static
bool
threadTx (TxMeta& meta,
std::shared_ptr<SLE> const& to,
Mods& mods);
std::shared_ptr<SLE> std::shared_ptr<SLE>
getForMod (uint256 const& key, getForMod (uint256 const& key,
Mods& mods); Mods& mods, beast::Journal j);
bool bool
threadTx (AccountID const& to, threadTx (TxMeta& meta,
Mods& mods); AccountID const& to, Mods& mods,
beast::Journal j);
bool bool
threadTx (std::shared_ptr<SLE> const& to, threadOwners (TxMeta& meta, std::shared_ptr<
Mods& mods); SLE const> const& sle, Mods& mods,
beast::Journal j);
bool
threadOwners (std::shared_ptr<
SLE const> const& sle, Mods& mods);
}; };
} // ripple } // ripple

View File

@@ -28,26 +28,27 @@
namespace ripple { namespace ripple {
class TransactionMetaSet // VFALCO Move to ripple/app/ledger/detail, rename to TxMeta
class TxMeta
{ {
public: public:
using pointer = std::shared_ptr<TransactionMetaSet>; using pointer = std::shared_ptr<TxMeta>;
using ref = const pointer&; using ref = const pointer&;
private: private:
struct CtorHelper{}; struct CtorHelper{};
template<class T> 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); CtorHelper);
public: public:
TransactionMetaSet () TxMeta ()
: mLedger (0) : mLedger (0)
, mIndex (static_cast<std::uint32_t> (-1)) , mIndex (static_cast<std::uint32_t> (-1))
, mResult (255) , 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) : mTransactionID (txID)
, mLedger (ledger) , mLedger (ledger)
, mIndex (static_cast<std::uint32_t> (-1)) , mIndex (static_cast<std::uint32_t> (-1))
@@ -55,15 +56,15 @@ public:
{ {
} }
TransactionMetaSet (uint256 const& txID, std::uint32_t ledger, Blob const&); TxMeta (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, std::string const&);
void init (uint256 const& transactionID, std::uint32_t ledger); void init (uint256 const& transactionID, std::uint32_t ledger);
void clear () void clear ()
{ {
mNodes.clear (); mNodes.clear ();
} }
void swap (TransactionMetaSet&) noexcept; void swap (TxMeta&) noexcept;
uint256 const& getTxID () uint256 const& getTxID ()
{ {

View File

@@ -22,6 +22,7 @@
#include <ripple/app/ledger/LedgerMaster.h> #include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerTiming.h> #include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/app/ledger/LedgerToJson.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/DisputedTx.h>
#include <ripple/app/ledger/impl/LedgerConsensusImp.h> #include <ripple/app/ledger/impl/LedgerConsensusImp.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
@@ -31,7 +32,7 @@
#include <ripple/app/misc/NetworkOPs.h> #include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Validations.h> #include <ripple/app/misc/Validations.h>
#include <ripple/app/tx/TransactionAcquire.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/CountedObject.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/core/Config.h> #include <ripple/core/Config.h>
@@ -979,15 +980,27 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
// Build the new last closed ledger // Build the new last closed ledger
auto newLCL = std::make_shared<Ledger> (false, *mPreviousLedger); 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, // Set up to write SHAMap changes to our database,
// perform updates, extract changes // perform updates, extract changes
WriteLog (lsDEBUG, LedgerConsensus) WriteLog (lsDEBUG, LedgerConsensus)
<< "Applying consensus set transactions to the" << "Applying consensus set transactions to the"
<< " last closed ledger"; << " 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->updateSkipList ();
newLCL->setClosed ();
int asf = newLCL->stateMap().flushDirty ( int asf = newLCL->stateMap().flushDirty (
hotACCOUNT_NODE, newLCL->getLedgerSeq()); hotACCOUNT_NODE, newLCL->getLedgerSeq());
@@ -1057,8 +1070,20 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
// Build new open ledger // Build new open ledger
auto newOL = std::make_shared<Ledger> (true, *newLCL); auto newOL = std::make_shared<Ledger> (true, *newLCL);
MetaView accum(*newOL, tapNONE);
assert(accum.open());
// Apply disputed transactions that didn't get in // 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; bool anyDisputes = false;
for (auto& it : mDisputes) for (auto& it : mDisputes)
{ {
@@ -1075,6 +1100,7 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
auto txn = std::make_shared<STTx>(sit); auto txn = std::make_shared<STTx>(sit);
retriableTransactions.push_back (txn); retriableTransactions.push_back (txn);
anyDisputes = true; anyDisputes = true;
} }
catch (...) catch (...)
@@ -1087,7 +1113,8 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
if (anyDisputes) 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) WriteLog (lsDEBUG, LedgerConsensus)
<< "Applying transactions from current open ledger"; << "Applying transactions from current open ledger";
applyTransactions (&oldOL->txMap(), applyTransactions (&oldOL->txMap(),
newOL, newLCL, retriableTransactions, true); accum, newLCL, retriableTransactions);
} }
// Apply local transactions // Apply local transactions
TransactionEngine engine (newOL);
for (auto it : m_localTX.getTxSet ()) for (auto it : m_localTX.getTxSet ())
{ {
try try
{ {
engine.applyTransaction (*it.second, tapOPEN_LEDGER); apply (accum, *it.second, tapNONE, getConfig(),
deprecatedLogs().journal("LedgerConsensus"));
} }
catch (...) 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 // We have a new Last Closed Ledger and new Open Ledger
ledgerMaster_.pushLedger (newLCL, newOL); ledgerMaster_.pushLedger (newLCL, newOL);
} }
@@ -1715,20 +1744,18 @@ make_LedgerConsensus (ConsensusImp& consensus, int previousProposers,
@param engine The transaction engine containing the ledger. @param engine The transaction engine containing the ledger.
@param txn The transaction to be applied to 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. @param retryAssured true if the transaction should be retried on failure.
@return One of resultSuccess, resultFail or resultRetry. @return One of resultSuccess, resultFail or resultRetry.
*/ */
static static
int applyTransaction ( int
TransactionEngine& engine, applyTransaction (BasicView& view,
std::shared_ptr<STTx const> const& txn, STTx const& txn,
bool openLedger,
bool retryAssured, bool retryAssured,
bool enableTesting) bool enableTesting)
{ {
// Returns false if the transaction has need not be retried. // Returns false if the transaction has need not be retried.
ViewFlags parms = openLedger ? tapOPEN_LEDGER : tapNONE; ViewFlags parms = tapNONE;
if (enableTesting) if (enableTesting)
parms = parms | tapENABLE_TESTING; parms = parms | tapENABLE_TESTING;
@@ -1738,21 +1765,22 @@ int applyTransaction (
parms = static_cast<ViewFlags> (parms | tapRETRY); parms = static_cast<ViewFlags> (parms | tapRETRY);
} }
if ((getApp().getHashRouter ().getFlags (txn->getTransactionID ()) if ((getApp().getHashRouter ().getFlags (txn.getTransactionID ())
& SF_SIGGOOD) == SF_SIGGOOD) & SF_SIGGOOD) == SF_SIGGOOD)
{ {
parms = static_cast<ViewFlags> parms = static_cast<ViewFlags>
(parms | tapNO_CHECK_SIGN); (parms | tapNO_CHECK_SIGN);
} }
WriteLog (lsDEBUG, LedgerConsensus) << "TXN " WriteLog (lsDEBUG, LedgerConsensus) << "TXN "
<< txn->getTransactionID () << txn.getTransactionID ()
<< (openLedger ? " open" : " closed") //<< (engine.view().open() ? " open" : " closed") // because of the optional in engine
<< (retryAssured ? "/retry" : "/final"); << (retryAssured ? "/retry" : "/final");
WriteLog (lsTRACE, LedgerConsensus) << txn->getJson (0); WriteLog (lsTRACE, LedgerConsensus) << txn.getJson (0);
try try
{ {
auto result = engine.applyTransaction (*txn, parms); auto const result = apply(view, txn, parms, getConfig(),
deprecatedLogs().journal("LedgerConsensus"));
if (result.second) if (result.second)
{ {
@@ -1783,14 +1811,11 @@ int applyTransaction (
void applyTransactions ( void applyTransactions (
SHAMap const* set, SHAMap const* set,
Ledger::ref applyLedger, BasicView& applyView,
Ledger::ref checkLedger, Ledger::ref checkLedger,
CanonicalTXSet& retriableTransactions, CanonicalTXSet& retriableTransactions,
bool openLgr,
bool enableTesting) bool enableTesting)
{ {
TransactionEngine engine (applyLedger);
if (set) if (set)
{ {
for (auto const item : *set) for (auto const item : *set)
@@ -1805,9 +1830,11 @@ void applyTransactions (
try try
{ {
SerialIter sit (item->slice()); 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 // On failure, stash the failed transaction for
// later retry. // later retry.
@@ -1836,8 +1863,8 @@ void applyTransactions (
{ {
try try
{ {
switch (applyTransaction (engine, it->second, switch (applyTransaction (applyView,
openLgr, certainRetry, enableTesting)) *it->second, certainRetry, enableTesting))
{ {
case LedgerConsensusImp::resultSuccess: case LedgerConsensusImp::resultSuccess:
it = retriableTransactions.erase (it); it = retriableTransactions.erase (it);

View File

@@ -24,6 +24,7 @@
#include <ripple/app/ledger/OrderBookDB.h> #include <ripple/app/ledger/OrderBookDB.h>
#include <ripple/app/ledger/PendingSaves.h> #include <ripple/app/ledger/PendingSaves.h>
#include <ripple/app/ledger/impl/LedgerCleaner.h> #include <ripple/app/ledger/impl/LedgerCleaner.h>
#include <ripple/app/tx/apply.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/misc/IHashRouter.h> #include <ripple/app/misc/IHashRouter.h>
#include <ripple/app/misc/NetworkOPs.h> #include <ripple/app/misc/NetworkOPs.h>
@@ -31,7 +32,6 @@
#include <ripple/app/misc/SHAMapStore.h> #include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/misc/Validations.h> #include <ripple/app/misc/Validations.h>
#include <ripple/app/paths/PathRequests.h> #include <ripple/app/paths/PathRequests.h>
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/basics/RangeSet.h> #include <ripple/basics/RangeSet.h>
#include <ripple/core/LoadFeeTrack.h> #include <ripple/core/LoadFeeTrack.h>
@@ -352,20 +352,20 @@ public:
// Start with a mutable snapshot of the open ledger // Start with a mutable snapshot of the open ledger
auto const ledger = auto const ledger =
mCurrentLedger.getMutable(); mCurrentLedger.getMutable();
TransactionEngine engine (ledger);
int recovers = 0; int recovers = 0;
for (auto const& it : mHeldTransactions) for (auto const& it : mHeldTransactions)
{ {
try try
{ {
ViewFlags tepFlags = tapOPEN_LEDGER; ViewFlags tepFlags = tapNONE;
if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD)) if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD))
tepFlags = static_cast<ViewFlags> (tepFlags | tapNO_CHECK_SIGN); 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) if (ret.second)
++recovers; ++recovers;

View File

@@ -18,10 +18,11 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/basics/contract.h>
#include <ripple/protocol/Quality.h> #include <ripple/protocol/Quality.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/ledger/CachedView.h> #include <ripple/ledger/CachedView.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h> #include <ripple/basics/StringUtilities.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
@@ -42,34 +43,39 @@ namespace ripple {
#define DIR_NODE_MAX 32 #define DIR_NODE_MAX 32
#endif #endif
MetaView::MetaView (BasicView const* parent, shallow_copy_t const shallow_copy {};
LedgerIndex seq, std::uint32_t time, 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) ViewFlags flags)
: parent_ (parent) : base_ (base)
, flags_ (flags) , flags_ (flags)
, seq_ (parent->seq()) , info_ (base.info())
, 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())
{ {
} }
@@ -81,7 +87,7 @@ MetaView::exists (Keylet const& k) const
assert(k.key.isNonZero()); assert(k.key.isNonZero());
auto const iter = items_.find(k.key); auto const iter = items_.find(k.key);
if (iter == items_.end()) if (iter == items_.end())
return parent_->exists(k); return base_.exists(k);
if (iter->second.first == taaDELETE) if (iter->second.first == taaDELETE)
return false; return false;
if (! k.check(*iter->second.second)) if (! k.check(*iter->second.second))
@@ -99,11 +105,11 @@ MetaView::succ (uint256 const& key,
{ {
boost::optional<uint256> next = key; boost::optional<uint256> next = key;
item_list::const_iterator iter; item_list::const_iterator iter;
// Find parent successor that is // Find base successor that is
// not also deleted in our list // not also deleted in our list
do do
{ {
next = parent_->succ(*next, last); next = base_.succ(*next, last);
if (! next) if (! next)
break; break;
iter = items_.find(*next); iter = items_.find(*next);
@@ -141,7 +147,7 @@ MetaView::read (Keylet const& k) const
if (iter == items_.end()) if (iter == items_.end())
{ {
auto const sle = auto const sle =
parent_->read(k); base_.read(k);
if (! sle) if (! sle)
return nullptr; return nullptr;
return sle; return sle;
@@ -163,13 +169,13 @@ MetaView::unchecked_erase (uint256 const& key)
if (iter == items_.end() || if (iter == items_.end() ||
iter->first != key) iter->first != key)
{ {
assert(parent_->exists( assert(base_.exists(
keylet::unchecked(key))); keylet::unchecked(key)));
using namespace std; using namespace std;
items_.emplace_hint(iter, piecewise_construct, items_.emplace_hint(iter, piecewise_construct,
forward_as_tuple(key), forward_as_tuple( forward_as_tuple(key), forward_as_tuple(
taaDELETE, make_shared<SLE>( taaDELETE, make_shared<SLE>(
*parent_->read(keylet::unchecked(key))))); *base_.read(keylet::unchecked(key)))));
return true; return true;
} }
if (iter->second.first == taaCREATE) if (iter->second.first == taaCREATE)
@@ -192,7 +198,7 @@ MetaView::unchecked_insert(
iter->first != sle->key()) iter->first != sle->key())
{ {
// VFALCO return Keylet from SLE // VFALCO return Keylet from SLE
assert(! parent_->exists(Keylet{ assert(! base_.exists(Keylet{
sle->getType(), sle->key()})); sle->getType(), sle->key()}));
using namespace std; using namespace std;
items_.emplace_hint(iter, piecewise_construct, items_.emplace_hint(iter, piecewise_construct,
@@ -217,7 +223,7 @@ MetaView::unchecked_insert(
break; break;
}; };
// VFALCO return Keylet from SLE // VFALCO return Keylet from SLE
assert(parent_->exists( assert(base_.exists(
Keylet{sle->getType(), sle->key()})); Keylet{sle->getType(), sle->key()}));
iter->second.first = taaMODIFY; iter->second.first = taaMODIFY;
iter->second.second = std::move(sle); iter->second.second = std::move(sle);
@@ -232,7 +238,7 @@ MetaView::unchecked_replace (std::shared_ptr<SLE>&& sle)
iter->first != sle->key()) iter->first != sle->key())
{ {
// VFALCO return Keylet from SLE // VFALCO return Keylet from SLE
assert(parent_->exists(Keylet{ assert(base_.exists(Keylet{
sle->getType(), sle->key()})); sle->getType(), sle->key()}));
using namespace std; using namespace std;
items_.emplace_hint(iter, piecewise_construct, items_.emplace_hint(iter, piecewise_construct,
@@ -255,29 +261,33 @@ MetaView::destroyCoins (std::uint64_t feeDrops)
destroyedCoins_ += feeDrops; destroyedCoins_ += feeDrops;
} }
std::size_t
MetaView::txCount() const
{
return base_.txCount() + txs_.size();
}
bool bool
MetaView::txExists (uint256 const& key) const MetaView::txExists (uint256 const& key) const
{ {
if (txs_.count(key) > 0) if (txs_.count(key) > 0)
return true; return true;
return parent_->txExists(key); return base_.txExists(key);
} }
bool void
MetaView::txInsert (uint256 const& key, MetaView::txInsert (uint256 const& key,
std::shared_ptr<Serializer const> const& txn, std::shared_ptr<Serializer const
std::shared_ptr<Serializer const> const& metaData) > const& txn, std::shared_ptr<
Serializer const> const& metaData)
{ {
bool already = txs_.count(key); if (txs_.count(key) ||
if (! already) base_.txExists(key))
already = parent_->txExists(key); LogicError("duplicate_tx: " + to_string(key));
if (already)
return false;
txs_.emplace(std::piecewise_construct, txs_.emplace(std::piecewise_construct,
std::forward_as_tuple(key), std::forward_as_tuple(key),
std::forward_as_tuple( std::forward_as_tuple(
txn, metaData)); txn, metaData));
return true;
} }
std::vector<uint256> std::vector<uint256>
@@ -301,7 +311,7 @@ MetaView::peek (Keylet const& k)
iter->first != k.key) iter->first != k.key)
{ {
auto const sle = auto const sle =
parent_->read(k); base_.read(k);
if (! sle) if (! sle)
return nullptr; return nullptr;
// Make our own copy // Make our own copy
@@ -349,7 +359,7 @@ MetaView::insert (std::shared_ptr<SLE> const& sle)
iter->first != sle->key()) iter->first != sle->key())
{ {
// VFALCO return Keylet from SLE // VFALCO return Keylet from SLE
assert(! parent_->exists( assert(! base_.exists(
Keylet{sle->getType(), sle->key()})); Keylet{sle->getType(), sle->key()}));
items_.emplace_hint(iter, std::piecewise_construct, items_.emplace_hint(iter, std::piecewise_construct,
std::forward_as_tuple(sle->getIndex()), std::forward_as_tuple(sle->getIndex()),
@@ -372,7 +382,7 @@ MetaView::insert (std::shared_ptr<SLE> const& sle)
break; break;
} }
// Existed in parent, deleted here // Existed in parent, deleted here
assert(parent_->exists( assert(base_.exists(
Keylet{sle->getType(), sle->key()})); Keylet{sle->getType(), sle->key()}));
iter->second.first = taaMODIFY; iter->second.first = taaMODIFY;
iter->second.second = sle; iter->second.second = sle;
@@ -386,7 +396,7 @@ MetaView::update (std::shared_ptr<SLE> const& sle)
iter->first != sle->key()) iter->first != sle->key())
{ {
// VFALCO return Keylet from SLE // VFALCO return Keylet from SLE
assert(parent_->exists( assert(base_.exists(
Keylet{sle->getType(), sle->key()})); Keylet{sle->getType(), sle->key()}));
items_.emplace_hint(iter, std::piecewise_construct, items_.emplace_hint(iter, std::piecewise_construct,
std::forward_as_tuple(sle->key()), 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 // Write back the account states
for (auto& item : items_) for (auto& item : items_)
{ {
@@ -521,23 +533,212 @@ Json::Value MetaView::getJson (int) const
ret[jss::nodes] = nodes; 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; 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> std::shared_ptr<SLE>
MetaView::getForMod (uint256 const& key, MetaView::getForMod (uint256 const& key,
Mods& mods) Mods& mods, beast::Journal j)
{ {
auto iter = items_.find (key); auto iter = items_.find (key);
if (iter != items_.end ()) if (iter != items_.end ())
{ {
if (iter->second.first == taaDELETE) if (iter->second.first == taaDELETE)
{ {
WriteLog (lsFATAL, View) << JLOG(j.fatal) <<
"Trying to thread to deleted node"; "Trying to thread to deleted node";
return nullptr; return nullptr;
} }
@@ -554,7 +755,7 @@ MetaView::getForMod (uint256 const& key,
} }
} }
// VFALCO NOTE Should this be read() or peek()? // VFALCO NOTE Should this be read() or peek()?
auto const csle = parent_->read( auto const csle = base_.read(
keylet::unchecked(key)); keylet::unchecked(key));
if (! csle) if (! csle)
return nullptr; return nullptr;
@@ -566,50 +767,33 @@ MetaView::getForMod (uint256 const& key,
} }
bool bool
MetaView::threadTx (AccountID const& to, MetaView::threadTx (TxMeta& meta,
Mods& mods) AccountID const& to, Mods& mods,
beast::Journal j)
{ {
auto const sle = getForMod( auto const sle = getForMod(
keylet::account(to).key, mods); keylet::account(to).key, mods, j);
#ifdef META_DEBUG #ifdef META_DEBUG
WriteLog (lsTRACE, View) << JLOG(j.trace) <<
"Thread to " << toBase58(to); "Thread to " << toBase58(to);
#endif #endif
assert(sle); assert(sle);
if (! sle) if (! sle)
{ {
WriteLog (lsFATAL, View) << JLOG(j.fatal) <<
"Threading to non-existent account: " << "Threading to non-existent account: " <<
toBase58(to); toBase58(to);
return false; return false;
} }
return threadTx (sle, mods); return threadTx (meta, sle, mods);
} }
bool bool
MetaView::threadTx( MetaView::threadOwners (TxMeta& meta,
std::shared_ptr<SLE> const& to, std::shared_ptr<
Mods& mods) SLE const> const& sle, Mods& mods,
{ beast::Journal j)
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)
{ {
// thread new or modified sle to owner or owners // thread new or modified sle to owner or owners
// VFALCO Why not isFieldPresent? // VFALCO Why not isFieldPresent?
@@ -618,163 +802,24 @@ MetaView::threadOwners(std::shared_ptr<
{ {
// thread to owner's account // thread to owner's account
#ifdef META_DEBUG #ifdef META_DEBUG
WriteLog (lsTRACE, View) << "Thread to single owner"; JLOG(j.trace) << "Thread to single owner";
#endif #endif
return threadTx (sle->getAccountID(sfAccount), mods); return threadTx (meta, sle->getAccountID(
sfAccount), mods, j);
} }
else if (sle->getType() == ltRIPPLE_STATE) else if (sle->getType() == ltRIPPLE_STATE)
{ {
// thread to owner's accounts // thread to owner's accounts
#ifdef META_DEBUG #ifdef META_DEBUG
WriteLog (lsTRACE, View) << "Thread to two owners"; JLOG(j.trace) << "Thread to two owners";
#endif #endif
return return
threadTx(sle->getFieldAmount(sfLowLimit).getIssuer(), mods) && threadTx (meta, sle->getFieldAmount(
threadTx(sle->getFieldAmount(sfHighLimit).getIssuer(), mods); sfLowLimit).getIssuer(), mods, j) &&
threadTx (meta, sle->getFieldAmount(
sfHighLimit).getIssuer(), mods, j);
} }
return false; 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 } // ripple

View File

@@ -18,7 +18,7 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/TransactionMeta.h> #include <ripple/app/ledger/TxMeta.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
#include <ripple/protocol/STAccount.h> #include <ripple/protocol/STAccount.h>
@@ -29,7 +29,7 @@ namespace ripple {
// VFALCO TODO rename class to TransactionMeta // VFALCO TODO rename class to TransactionMeta
template<class T> template<class T>
TransactionMetaSet::TransactionMetaSet (uint256 const& txid, TxMeta::TxMeta (uint256 const& txid,
std::uint32_t ledger, T const& data, CtorHelper) std::uint32_t ledger, T const& data, CtorHelper)
: mTransactionID (txid) : mTransactionID (txid)
, mLedger (ledger) , mLedger (ledger)
@@ -46,21 +46,21 @@ TransactionMetaSet::TransactionMetaSet (uint256 const& txid,
setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount)); setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
} }
TransactionMetaSet::TransactionMetaSet (uint256 const& txid, TxMeta::TxMeta (uint256 const& txid,
std::uint32_t ledger, std::uint32_t ledger,
Blob const& vec) 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::uint32_t ledger,
std::string const& data) 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) for (auto const& n : mNodes)
{ {
@@ -71,7 +71,7 @@ bool TransactionMetaSet::isNodeAffected (uint256 const& node) const
return false; return false;
} }
void TransactionMetaSet::setAffectedNode (uint256 const& node, SField const& type, void TxMeta::setAffectedNode (uint256 const& node, SField const& type,
std::uint16_t nodeType) std::uint16_t nodeType)
{ {
// make sure the node exists and force its type // 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> boost::container::flat_set<AccountID>
TransactionMetaSet::getAffectedAccounts() const TxMeta::getAffectedAccounts() const
{ {
boost::container::flat_set<AccountID> list; boost::container::flat_set<AccountID> list;
list.reserve (10); list.reserve (10);
@@ -137,7 +137,7 @@ TransactionMetaSet::getAffectedAccounts() const
} }
else 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; return list;
} }
STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField const& type) STObject& TxMeta::getAffectedNode (SLE::ref node, SField const& type)
{ {
assert (&type); assert (&type);
uint256 index = node->getIndex (); uint256 index = node->getIndex ();
@@ -167,7 +167,7 @@ STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField const& type
return obj; return obj;
} }
STObject& TransactionMetaSet::getAffectedNode (uint256 const& node) STObject& TxMeta::getAffectedNode (uint256 const& node)
{ {
for (auto& n : mNodes) for (auto& n : mNodes)
{ {
@@ -178,7 +178,7 @@ STObject& TransactionMetaSet::getAffectedNode (uint256 const& node)
throw std::runtime_error ("Affected node not found"); 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) 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"); 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; mTransactionID = id;
mLedger = ledger; mLedger = ledger;
@@ -197,13 +197,13 @@ void TransactionMetaSet::init (uint256 const& id, std::uint32_t ledger)
mDelivered = boost::optional <STAmount> (); mDelivered = boost::optional <STAmount> ();
} }
void TransactionMetaSet::swap (TransactionMetaSet& s) noexcept void TxMeta::swap (TxMeta& s) noexcept
{ {
assert ((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger)); assert ((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger));
mNodes.swap (s.mNodes); 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) 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); return o1.getFieldH256 (sfLedgerIndex) < o2.getFieldH256 (sfLedgerIndex);
} }
STObject TransactionMetaSet::getAsObject () const STObject TxMeta::getAsObject () const
{ {
STObject metaData (sfTransactionMetaData); STObject metaData (sfTransactionMetaData);
assert (mResult != 255); assert (mResult != 255);
@@ -235,7 +235,7 @@ STObject TransactionMetaSet::getAsObject () const
return metaData; 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); mResult = static_cast<int> (result);
mIndex = index; mIndex = index;

View File

@@ -152,7 +152,7 @@ class MetaView_test
using namespace jtx; using namespace jtx;
Env env(*this); Env env(*this);
wipe(*env.ledger); wipe(*env.ledger);
MetaView v(env.ledger.get(), tapNONE); MetaView v(*env.ledger, tapNONE);
succ(v, 0, boost::none); succ(v, 0, boost::none);
v.insert(sle(1)); v.insert(sle(1));
expect(v.exists(k(1))); expect(v.exists(k(1)));
@@ -189,7 +189,7 @@ class MetaView_test
v0.unchecked_insert(sle(4)); v0.unchecked_insert(sle(4));
v0.unchecked_insert(sle(7)); v0.unchecked_insert(sle(7));
{ {
MetaView v1(&v0, tapNONE); MetaView v1(v0, tapNONE);
v1.insert(sle(3)); v1.insert(sle(3));
v1.insert(sle(5)); v1.insert(sle(5));
v1.insert(sle(6)); v1.insert(sle(6));
@@ -252,7 +252,7 @@ class MetaView_test
v0.unchecked_insert(sle(4, 4)); v0.unchecked_insert(sle(4, 4));
{ {
MetaView v1(&v0, tapNONE); MetaView v1(v0, tapNONE);
v1.erase(v1.peek(k(2))); v1.erase(v1.peek(k(2)));
v1.insert(sle(3, 3)); v1.insert(sle(3, 3));
auto s = v1.peek(k(4)); 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(3))) == 3);
expect(seq(v1.read(k(4))) == 5); expect(seq(v1.read(k(4))) == 5);
{ {
MetaView v2(&v1); MetaView v2(v1, tapNONE);
auto s = v2.peek(k(3)); auto s = v2.peek(k(3));
seq(s, 6); seq(s, 6);
v2.update(s); v2.update(s);
@@ -280,7 +280,7 @@ class MetaView_test
expect(seq(v1.read(k(4))) == 5); expect(seq(v1.read(k(4))) == 5);
{ {
MetaView v2(&v1); MetaView v2(v1, tapNONE);
auto s = v2.peek(k(3)); auto s = v2.peek(k(3));
seq(s, 6); seq(s, 6);
v2.update(s); v2.update(s);
@@ -311,36 +311,41 @@ class MetaView_test
{ {
Env env(*this); Env env(*this);
wipe(*env.ledger); wipe(*env.ledger);
MetaView v0(env.ledger.get(), tapNONE); MetaView v0(*env.ledger, tapNONE);
expect(v0.seq() != 98); expect(v0.seq() != 98);
expect(v0.seq() == env.ledger->seq()); expect(v0.seq() == env.ledger->seq());
expect(v0.time() != 99); expect(v0.parentCloseTime() != 99);
expect(v0.time() == env.ledger->time()); expect(v0.parentCloseTime() ==
env.ledger->parentCloseTime());
expect(v0.flags() == tapNONE); expect(v0.flags() == tapNONE);
{ {
// Shallow copy MetaView v1(shallow_copy, v0);
MetaView v1(v0);
expect (v1.seq() == v0.seq()); expect (v1.seq() == v0.seq());
expect (v1.time() == v1.time()); expect (v1.parentCloseTime() ==
v1.parentCloseTime());
expect (v1.flags() == tapNONE); expect (v1.flags() == tapNONE);
MetaView v2(&v1, tapNO_CHECK_SIGN); MetaView v2(v1, tapNO_CHECK_SIGN);
expect(v2.time() == v1.time()); expect(v2.parentCloseTime() ==
v1.parentCloseTime());
expect(v2.seq() == v1.seq()); expect(v2.seq() == v1.seq());
expect(v2.flags() == tapNO_CHECK_SIGN); expect(v2.flags() == tapNO_CHECK_SIGN);
MetaView v3(&v2); MetaView v3(v2, tapNONE);
expect(v3.seq() == v2.seq()); expect(v3.seq() == v2.seq());
expect(v3.time() == v2.time()); expect(v3.parentCloseTime() ==
expect(v3.flags() == v2.flags()); 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.seq() == v0.seq());
expect(v1.time() == v0.time()); expect(v1.parentCloseTime() ==
v0.parentCloseTime());
expect(v1.flags() == tapNO_CHECK_SIGN); expect(v1.flags() == tapNO_CHECK_SIGN);
PaymentView v2(&v1); PaymentView v2(&v1);
expect(v2.seq() == v1.seq()); expect(v2.seq() == v1.seq());
expect(v2.time() == v1.time()); expect(v2.parentCloseTime() ==
v1.parentCloseTime());
expect(v2.flags() == v1.flags()); expect(v2.flags() == v1.flags());
} }
} }
@@ -359,9 +364,9 @@ class MetaView_test
wipe(*env.ledger); wipe(*env.ledger);
BasicView& v0 = *env.ledger; BasicView& v0 = *env.ledger;
v0.unchecked_insert(sle(1)); 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.erase(v2.peek(k(1)));
v2.apply(v1); v2.apply(v1);
} }

View File

@@ -20,6 +20,7 @@
#include <ripple/app/ledger/tests/common_ledger.h> #include <ripple/app/ledger/tests/common_ledger.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/paths/FindPaths.h> #include <ripple/app/paths/FindPaths.h>
#include <ripple/app/tx/apply.h>
#include <ripple/protocol/RippleAddress.h> #include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
#include <ripple/protocol/types.h> #include <ripple/protocol/types.h>
@@ -127,9 +128,9 @@ parseTransaction(TestAccount& account, Json::Value const& tx_json, bool sign)
void void
applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check) applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check)
{ {
TransactionEngine engine(ledger); auto const r = apply (*ledger, tx,
auto r = engine.applyTransaction(tx, check ? tapNONE : tapNO_CHECK_SIGN, getConfig(),
tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN)); beast::Journal{});
if (r.first != tesSUCCESS) if (r.first != tesSUCCESS)
throw std::runtime_error("r != tesSUCCESS"); throw std::runtime_error("r != tesSUCCESS");
if (!r.second) 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. // that other Ledger constructor can take a const Ledger.
Ledger oldLCL(*LCL, false); Ledger oldLCL(*LCL, false);
Ledger::pointer newLCL = std::make_shared<Ledger>(false, oldLCL); Ledger::pointer newLCL = std::make_shared<Ledger>(false, oldLCL);
MetaView accum(*newLCL, tapNONE);
// Set up to write SHAMap changes to our database, // Set up to write SHAMap changes to our database,
// perform updates, extract changes // perform updates, extract changes
applyTransactions(&set, newLCL, newLCL, retriableTransactions, false); applyTransactions(&set, accum, newLCL, retriableTransactions);
accum.apply(*newLCL, {});
newLCL->updateSkipList(); newLCL->updateSkipList();
newLCL->setClosed(); newLCL->setClosed();
newLCL->stateMap().flushDirty( newLCL->stateMap().flushDirty(

View File

@@ -67,9 +67,9 @@
#include <ripple/websocket/MakeServer.h> #include <ripple/websocket/MakeServer.h>
#include <ripple/crypto/RandomNumbers.h> #include <ripple/crypto/RandomNumbers.h>
#include <beast/asio/io_latency_probe.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/text/LexicalCast.h>
#include <beast/module/core/thread/DeadlineTimer.h> #include <beast/module/core/thread/DeadlineTimer.h>
#include <boost/asio/signal_set.hpp>
#include <fstream> #include <fstream>
namespace ripple { namespace ripple {
@@ -1337,11 +1337,9 @@ bool ApplicationImp::loadOldLedger (
txn->getJson(0); txn->getJson(0);
Serializer s; Serializer s;
txn->getSTransaction()->add(s); txn->getSTransaction()->add(s);
if (! cur->txInsert(item->getTag(), cur->txInsert(item->getTag(),
std::make_shared<Serializer const>(std::move(s)), std::make_shared<Serializer const>(
nullptr)) std::move(s)), nullptr);
if (m_journal.warning) m_journal.warning <<
"Unable to add transaction " << item->getTag();
getApp().getHashRouter().setFlag (item->getTag(), SF_SIGGOOD); getApp().getHashRouter().setFlag (item->getTag(), SF_SIGGOOD);
} }
@@ -1485,7 +1483,7 @@ static void addTxnSeqField ()
} }
else else
{ {
TransactionMetaSet m (transID, 0, txnMeta); TxMeta m (transID, 0, txnMeta);
txIDs.push_back (std::make_pair (transID, m.getIndex ())); txIDs.push_back (std::make_pair (transID, m.getIndex ()));
} }

View File

@@ -35,7 +35,7 @@ namespace ripple {
// VFALCO TODO rename to SortedTxSet // VFALCO TODO rename to SortedTxSet
class CanonicalTXSet class CanonicalTXSet
{ {
public: private:
class Key class Key
{ {
public: public:
@@ -71,6 +71,7 @@ public:
std::uint32_t mSeq; std::uint32_t mSeq;
}; };
public:
using iterator = std::map <Key, std::shared_ptr<STTx const>>::iterator; using iterator = std::map <Key, std::shared_ptr<STTx const>>::iterator;
using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::const_iterator; using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::const_iterator;

View File

@@ -24,6 +24,7 @@
#include <ripple/app/ledger/Consensus.h> #include <ripple/app/ledger/Consensus.h>
#include <ripple/app/ledger/LedgerConsensus.h> #include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/AcceptedLedger.h> #include <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/ledger/CachedView.h> #include <ripple/ledger/CachedView.h>
#include <ripple/app/ledger/InboundLedger.h> #include <ripple/app/ledger/InboundLedger.h>
#include <ripple/app/ledger/InboundLedgers.h> #include <ripple/app/ledger/InboundLedgers.h>
@@ -38,7 +39,7 @@
#include <ripple/app/misc/Validations.h> #include <ripple/app/misc/Validations.h>
#include <ripple/app/misc/impl/AccountTxPaging.h> #include <ripple/app/misc/impl/AccountTxPaging.h>
#include <ripple/app/misc/UniqueNodeList.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/app/tx/TransactionMaster.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/basics/Time.h> #include <ripple/basics/Time.h>
@@ -251,19 +252,6 @@ public:
*/ */
void apply (std::unique_lock<std::mutex>& batchLock); 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. // Owner functions.
// //
@@ -987,14 +975,35 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
batchLock.unlock(); batchLock.unlock();
{
Ledger::pointer ledger; Ledger::pointer ledger;
TransactionEngine engine; bool applied = false;
boost::optional<MetaView> accum;
{
auto lock = beast::make_lock(getApp().getMasterMutex()); 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(); ledger->setImmutable();
m_ledgerMaster.getCurrentLedgerHolder().set (ledger); m_ledgerMaster.getCurrentLedgerHolder().set (ledger);
} }
@@ -1101,28 +1110,6 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
mDispatchState = DispatchState::none; 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 // Owner functions
// //
@@ -1793,7 +1780,7 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs (
ledger->pendSaveValidated(false, false); 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)); txn->getID (), txn->getLedger (), txnMeta));
} }
} }

View File

@@ -233,7 +233,7 @@ public:
virtual std::size_t getLocalTxCount () = 0; virtual std::size_t getLocalTxCount () = 0;
// client information retrieval functions // 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>; using AccountTxs = std::vector<AccountTx>;
virtual AccountTxs getAccountTxs ( virtual AccountTxs getAccountTxs (

View File

@@ -46,7 +46,7 @@ convertBlobsToTxResult (
tr->setStatus (Transaction::sqlTransactionStatus(status)); tr->setStatus (Transaction::sqlTransactionStatus(status));
tr->setLedger (ledger_index); tr->setLedger (ledger_index);
auto metaset = std::make_shared<TransactionMetaSet> ( auto metaset = std::make_shared<TxMeta> (
tr->getID (), tr->getLedger (), rawMeta); tr->getID (), tr->getLedger (), rawMeta);
to.emplace_back(std::move(tr), metaset); to.emplace_back(std::move(tr), metaset);

View File

@@ -525,8 +525,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
if (valid) if (valid)
{ {
boost::optional<PaymentView> sandbox; boost::optional<PaymentView> sandbox;
sandbox.emplace(cache->getLedger().get(), sandbox.emplace(*cache->getLedger(),
tapOPEN_LEDGER); tapNONE);
auto& sourceAccount = !isXRP (currIssuer.account) auto& sourceAccount = !isXRP (currIssuer.account)
? currIssuer.account ? currIssuer.account
@@ -552,8 +552,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
m_journal.debug m_journal.debug
<< iIdentifier << " Trying with an extra path element"; << iIdentifier << " Trying with an extra path element";
spsPaths.push_back (fullLiquidityPath); spsPaths.push_back (fullLiquidityPath);
sandbox.emplace(cache->getLedger().get(), sandbox.emplace(*cache->getLedger(),
tapOPEN_LEDGER); tapNONE);
rc = path::RippleCalc::rippleCalculate ( rc = path::RippleCalc::rippleCalculate (
*sandbox, *sandbox,
saMaxAmount, saMaxAmount,

View File

@@ -378,7 +378,7 @@ TER Pathfinder::getPathLiquidity (
path::RippleCalc::Input rcInput; path::RippleCalc::Input rcInput;
rcInput.defaultPathsAllowed = false; rcInput.defaultPathsAllowed = false;
PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER); PaymentView sandbox (*mLedger, tapNONE);
try try
{ {
@@ -443,7 +443,7 @@ void Pathfinder::computePathRanks (int maxPaths)
// Must subtract liquidity in default path from remaining amount. // Must subtract liquidity in default path from remaining amount.
try try
{ {
PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER); PaymentView sandbox (*mLedger, tapNONE);
path::RippleCalc::Input rcInput; path::RippleCalc::Input rcInput;
rcInput.partialPaymentAllowed = true; rcInput.partialPaymentAllowed = true;

View File

@@ -212,7 +212,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
if (node().sleOffer->isFieldPresent (sfExpiration) && if (node().sleOffer->isFieldPresent (sfExpiration) &&
(node().sleOffer->getFieldU32 (sfExpiration) <= (node().sleOffer->getFieldU32 (sfExpiration) <=
view().time())) view().parentCloseTime()))
{ {
// Offer is expired. // Offer is expired.
WriteLog (lsTRACE, RippleCalc) WriteLog (lsTRACE, RippleCalc)

View File

@@ -73,14 +73,14 @@ public:
/** @{ */ /** @{ */
explicit explicit
PaymentView (PaymentView const* parent) PaymentView (PaymentView const* parent)
: ViewWrapper (parent) : ViewWrapper (*parent, parent->flags())
, pv_ (parent) , pv_ (parent)
{ {
} }
explicit explicit
PaymentView (PaymentView* parent) PaymentView (PaymentView* parent)
: ViewWrapper (parent) : ViewWrapper (*parent, parent->flags())
, pv_ (parent) , pv_ (parent)
{ {
} }

56
src/ripple/app/tx/apply.h Normal file
View 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

View 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

View File

@@ -17,11 +17,13 @@
*/ */
//============================================================================== //==============================================================================
#ifndef RIPPLE_APP_TX_TRANSACTIONENGINE_H_INCLUDED #ifndef RIPPLE_TX_APPLYCONTEXT_H_INCLUDED
#define RIPPLE_APP_TX_TRANSACTIONENGINE_H_INCLUDED #define RIPPLE_TX_APPLYCONTEXT_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/MetaView.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 <boost/optional.hpp>
#include <utility> #include <utility>
@@ -29,71 +31,54 @@ namespace ripple {
// tx_enable_test // tx_enable_test
// One instance per ledger. /** State information when applying a tx. */
// Only one transaction applied at a time. class ApplyContext
class TransactionEngine
{ {
boost::optional<MetaView> mNodes;
void txnWrite();
protected:
Ledger::pointer mLedger;
int mTxnSeq = 0;
public: public:
TransactionEngine() = default;
explicit explicit
TransactionEngine (Ledger::ref ledger) ApplyContext (BasicView& base,
: mLedger (ledger) STTx const& tx, ViewFlags flags,
{ Config const& config,
assert (mLedger); beast::Journal = {});
}
STTx const& tx;
Config const& config;
beast::Journal const journal;
View& View&
view () view()
{ {
return *mNodes; return *view_;
} }
Ledger::ref View const&
getLedger() view() const
{ {
return mLedger; return *view_;
}
void
setLedger (Ledger::ref ledger)
{
assert (ledger);
mLedger = ledger;
} }
/** Sets the DeliveredAmount field in the metadata */ /** Sets the DeliveredAmount field in the metadata */
void void
deliverAmount (STAmount const& delivered) deliverAmount (STAmount const& delivered)
{ {
mNodes->setDeliveredAmount(delivered); view_->setDeliveredAmount(delivered);
} }
std::pair<TER, bool> /** Discard changes and start fresh. */
applyTransaction (STTx const&, ViewFlags); void
discard();
bool /** Apply the transaction result to the base. */
checkInvariants (TER result, STTx const& txn, ViewFlags params); 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 } // ripple
#endif #endif

View File

@@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
/* /*
This file is part of rippled: https://github.com/ripple/rippled This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc. Copyright (c) 2012, 2013 Ripple Labs Inc.
@@ -18,37 +18,21 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Transactor.h> #include <ripple/app/tx/impl/CancelOffer.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
namespace ripple { namespace ripple {
class CancelOffer TER
: public Transactor 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 ()); std::uint32_t const uTxFlags (mTxn.getFlags ());
if (uTxFlags & tfUniversalMask) if (uTxFlags & tfUniversalMask)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Invalid flags set."; "Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -57,48 +41,39 @@ public:
if (!uOfferSequence) if (!uOfferSequence)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"No sequence specified."; "No sequence specified.";
return temBAD_SEQUENCE; return temBAD_SEQUENCE;
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
TER doApply () override TER
{ CancelOffer::doApply ()
{
std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence); std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
if (mTxnAccount->getFieldU32 (sfSequence) - 1 <= uOfferSequence) if (mTxnAccount->getFieldU32 (sfSequence) - 1 <= uOfferSequence)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Sequence " << uOfferSequence << " is invalid."; "Sequence " << uOfferSequence << " is invalid.";
return temBAD_SEQUENCE; return temBAD_SEQUENCE;
} }
uint256 const offerIndex (getOfferIndex (mTxnAccountID, uOfferSequence)); uint256 const offerIndex (getOfferIndex (mTxnAccountID, uOfferSequence));
auto sleOffer = mEngine->view().peek ( auto sleOffer = view().peek (
keylet::offer(offerIndex)); keylet::offer(offerIndex));
if (sleOffer) if (sleOffer)
{ {
m_journal.debug << "Trying to cancel offer #" << uOfferSequence; j_.debug << "Trying to cancel offer #" << uOfferSequence;
return offerDelete (mEngine->view(), sleOffer); return offerDelete (view(), sleOffer);
} }
m_journal.debug << "Offer #" << uOfferSequence << " can't be found."; j_.debug << "Offer #" << uOfferSequence << " can't be found.";
return tesSUCCESS; return tesSUCCESS;
}
};
TER
transact_CancelOffer (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{
return CancelOffer (txn, params, engine).apply ();
} }
} }

View 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

View File

@@ -18,38 +18,32 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Transactor.h> #include <ripple/app/tx/impl/CancelTicket.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
namespace ripple { namespace ripple {
class CancelTicket TER
: public Transactor CancelTicket::preCheck()
{ {
public: #if ! RIPPLE_ENABLE_TICKETS
CancelTicket ( if (! (view().flags() & tapENABLE_TESTING))
STTx const& txn, return temDISABLED;
ViewFlags params, #endif
TransactionEngine* engine) return Transactor::preCheck ();
: Transactor ( }
txn,
params,
engine,
deprecatedLogs().journal("CancelTicket"))
{
} TER
CancelTicket::doApply ()
TER doApply () override {
{
assert (mTxnAccount); assert (mTxnAccount);
uint256 const ticketId = mTxn.getFieldH256 (sfTicketID); uint256 const ticketId = mTxn.getFieldH256 (sfTicketID);
// VFALCO This is highly suspicious, we're requiring that the // VFALCO This is highly suspicious, we're requiring that the
// transaction provide the return value of getTicketIndex? // 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) if (!sleTicket)
return tecNO_ENTRY; return tecNO_ENTRY;
@@ -69,7 +63,7 @@ public:
{ {
std::uint32_t const expiration = sleTicket->getFieldU32 (sfExpiration); std::uint32_t const expiration = sleTicket->getFieldU32 (sfExpiration);
if (mEngine->view().time() >= expiration) if (view().parentCloseTime() >= expiration)
authorized = true; authorized = true;
} }
@@ -78,29 +72,14 @@ public:
std::uint64_t const hint (sleTicket->getFieldU64 (sfOwnerNode)); 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)); getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0));
adjustOwnerCount(mEngine->view(), mEngine->view().peek( adjustOwnerCount(view(), view().peek(
keylet::account(ticket_owner)), -1); keylet::account(ticket_owner)), -1);
mEngine->view ().erase (sleTicket); ctx_.view ().erase (sleTicket);
return result; 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();
} }
} }

View 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

View File

@@ -18,33 +18,18 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Change.h>
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/misc/AmendmentTable.h> #include <ripple/app/misc/AmendmentTable.h>
#include <ripple/app/misc/NetworkOPs.h> #include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/tx/impl/Transactor.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
namespace ripple { namespace ripple {
class Change TER
: public Transactor 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) if (mTxn.getTxnType () == ttAMENDMENT)
return applyAmendment (); return applyAmendment ();
@@ -52,80 +37,84 @@ public:
return applyFee (); return applyFee ();
return temUNKNOWN; return temUNKNOWN;
} }
TER checkSign () override TER
{ Change::checkSign()
{
if (mTxn.getAccountID (sfAccount).isNonZero ()) if (mTxn.getAccountID (sfAccount).isNonZero ())
{ {
m_journal.warning << "Bad source account"; j_.warning << "Bad source account";
return temBAD_SRC_ACCOUNT; return temBAD_SRC_ACCOUNT;
} }
if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ()) if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ())
{ {
m_journal.warning << "Bad signature"; j_.warning << "Bad signature";
return temBAD_SIGNATURE; return temBAD_SIGNATURE;
} }
return tesSUCCESS; return tesSUCCESS;
} }
TER checkSeq () override TER
{ Change::checkSeq()
{
if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID)) if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID))
{ {
m_journal.warning << "Bad sequence"; j_.warning << "Bad sequence";
return temBAD_SEQUENCE; return temBAD_SEQUENCE;
} }
return tesSUCCESS; return tesSUCCESS;
} }
TER payFee () override TER
{ Change::payFee()
{
if (mTxn.getTransactionFee () != STAmount ()) if (mTxn.getTransactionFee () != STAmount ())
{ {
m_journal.warning << "Non-zero fee"; j_.warning << "Non-zero fee";
return temBAD_FEE; return temBAD_FEE;
} }
return tesSUCCESS; return tesSUCCESS;
} }
TER preCheck () override TER
{ Change::preCheck()
{
mTxnAccountID = mTxn.getAccountID(sfAccount); mTxnAccountID = mTxn.getAccountID(sfAccount);
if (mTxnAccountID.isNonZero ()) if (mTxnAccountID.isNonZero ())
{ {
m_journal.warning << "Bad source id"; j_.warning << "Bad source id";
return temBAD_SRC_ACCOUNT; 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 temINVALID;
} }
return tesSUCCESS; return tesSUCCESS;
} }
private: TER
TER applyAmendment () Change::applyAmendment()
{ {
uint256 amendment (mTxn.getFieldH256 (sfAmendment)); uint256 amendment (mTxn.getFieldH256 (sfAmendment));
auto const k = keylet::amendments(); auto const k = keylet::amendments();
SLE::pointer amendmentObject = SLE::pointer amendmentObject =
mEngine->view().peek (k); view().peek (k);
if (!amendmentObject) if (!amendmentObject)
{ {
amendmentObject = std::make_shared<SLE>(k); amendmentObject = std::make_shared<SLE>(k);
mEngine->view().insert(amendmentObject); view().insert(amendmentObject);
} }
STVector256 amendments = STVector256 amendments =
@@ -137,7 +126,7 @@ private:
amendments.push_back (amendment); amendments.push_back (amendment);
amendmentObject->setFieldV256 (sfAmendments, amendments); amendmentObject->setFieldV256 (sfAmendments, amendments);
mEngine->view().update (amendmentObject); view().update (amendmentObject);
getApp().getAmendmentTable ().enable (amendment); getApp().getAmendmentTable ().enable (amendment);
@@ -145,22 +134,23 @@ private:
getApp().getOPs ().setAmendmentBlocked (); getApp().getOPs ().setAmendmentBlocked ();
return tesSUCCESS; return tesSUCCESS;
} }
TER applyFee () TER
{ Change::applyFee()
{
auto const k = keylet::fees(); auto const k = keylet::fees();
SLE::pointer feeObject = mEngine->view().peek (k); SLE::pointer feeObject = view().peek (k);
if (!feeObject) if (!feeObject)
{ {
feeObject = std::make_shared<SLE>(k); feeObject = std::make_shared<SLE>(k);
mEngine->view().insert(feeObject); view().insert(feeObject);
} }
// VFALCO-FIXME this generates errors // VFALCO-FIXME this generates errors
// m_journal.trace << // j_.trace <<
// "Previous fee object: " << feeObject->getJson (0); // "Previous fee object: " << feeObject->getJson (0);
feeObject->setFieldU64 ( feeObject->setFieldU64 (
@@ -172,30 +162,13 @@ private:
feeObject->setFieldU32 ( feeObject->setFieldU32 (
sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement)); sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
mEngine->view().update (feeObject); view().update (feeObject);
// VFALCO-FIXME this generates errors // VFALCO-FIXME this generates errors
// m_journal.trace << // j_.trace <<
// "New fee object: " << feeObject->getJson (0); // "New fee object: " << feeObject->getJson (0);
m_journal.warning << "Fees have been changed"; j_.warning << "Fees have been changed";
return tesSUCCESS; 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 ();
} }
} }

View 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

View File

@@ -18,9 +18,10 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/CreateOffer.h>
#include <ripple/app/tx/impl/OfferStream.h> #include <ripple/app/tx/impl/OfferStream.h>
#include <ripple/app/tx/impl/Taker.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/protocol/Quality.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
@@ -31,42 +32,34 @@
namespace ripple { namespace ripple {
class CreateOffer TER
: public Transactor 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 // Only valid for custom currencies
assert (!isXRP (issue.currency)); assert (!isXRP (issue.currency));
auto const issuerAccount = mEngine->view().read( auto const issuerAccount = ctx_.view().read(
keylet::account(issue.account)); keylet::account(issue.account));
if (!issuerAccount) if (!issuerAccount)
{ {
if (m_journal.warning) m_journal.warning << if (j_.warning) j_.warning <<
"delay: can't receive IOUs from non-existent issuer: " << "delay: can't receive IOUs from non-existent issuer: " <<
to_string (issue.account); to_string (issue.account);
return (mParams & tapRETRY) return (view().flags() & tapRETRY)
? terNO_ACCOUNT ? terNO_ACCOUNT
: tecNO_ISSUER; : tecNO_ISSUER;
} }
if (issuerAccount->getFieldU32 (sfFlags) & lsfRequireAuth) if (issuerAccount->getFieldU32 (sfFlags) & lsfRequireAuth)
{ {
auto const trustLine = mEngine->view().read( auto const trustLine = ctx_.view().read(
keylet::line(mTxnAccountID, issue.account, issue.currency)); keylet::line(mTxnAccountID, issue.account, issue.currency));
if (!trustLine) if (!trustLine)
{ {
return (mParams & tapRETRY) return (view().flags() & tapRETRY)
? terNO_LINE ? terNO_LINE
: tecNO_LINE; : tecNO_LINE;
} }
@@ -81,35 +74,33 @@ private:
if (!is_authorized) if (!is_authorized)
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"delay: can't receive IOUs from issuer without auth."; "delay: can't receive IOUs from issuer without auth.";
return (mParams & tapRETRY) return (view().flags() & tapRETRY)
? terNO_AUTH ? terNO_AUTH
: tecNO_AUTH; : tecNO_AUTH;
} }
} }
return tesSUCCESS; return tesSUCCESS;
} }
static bool
bool CreateOffer::dry_offer (View& view, Offer const& offer)
dry_offer (View& view, Offer const& offer) {
{
if (offer.fully_consumed ()) if (offer.fully_consumed ())
return true; return true;
auto const amount = accountFunds(view, offer.owner(), 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); return (amount <= zero);
} }
static std::pair<bool, Quality>
std::pair<bool, Quality> CreateOffer::select_path (
select_path (
bool have_direct, OfferStream const& direct, bool have_direct, OfferStream const& direct,
bool have_bridge, OfferStream const& leg1, OfferStream const& leg2) bool have_bridge, OfferStream const& leg1, OfferStream const& leg2)
{ {
// If we don't have any viable path, why are we here?! // If we don't have any viable path, why are we here?!
assert (have_direct || have_bridge); assert (have_direct || have_bridge);
@@ -133,15 +124,15 @@ private:
// Either there was no direct offer, or it didn't have a better quality // Either there was no direct offer, or it didn't have a better quality
// than the bridge. // than the bridge.
return std::make_pair (false, bridged_quality); return std::make_pair (false, bridged_quality);
} }
std::pair<TER, Amounts> std::pair<TER, Amounts>
bridged_cross ( CreateOffer::bridged_cross (
Taker& taker, Taker& taker,
View& view, View& view,
View& view_cancel, View& view_cancel,
Clock::time_point const when) Clock::time_point const when)
{ {
auto const& taker_amount = taker.original_offer (); auto const& taker_amount = taker.original_offer ();
assert (!isXRP (taker_amount.in) && !isXRP (taker_amount.out)); assert (!isXRP (taker_amount.in) && !isXRP (taker_amount.out));
@@ -150,13 +141,13 @@ private:
throw std::logic_error ("Bridging with XRP and an endpoint."); throw std::logic_error ("Bridging with XRP and an endpoint.");
OfferStream offers_direct (view, view_cancel, 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, 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, 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; TER cross_result = tesSUCCESS;
@@ -191,23 +182,23 @@ private:
if (use_direct) if (use_direct)
{ {
if (m_journal.debug) if (j_.debug)
{ {
m_journal.debug << count << " Direct:"; j_.debug << count << " Direct:";
m_journal.debug << " offer: " << offers_direct.tip (); j_.debug << " offer: " << offers_direct.tip ();
m_journal.debug << " in: " << offers_direct.tip ().amount().in; j_.debug << " in: " << offers_direct.tip ().amount().in;
m_journal.debug << " out: " << offers_direct.tip ().amount ().out; j_.debug << " out: " << offers_direct.tip ().amount ().out;
m_journal.debug << " owner: " << offers_direct.tip ().owner (); j_.debug << " owner: " << offers_direct.tip ().owner ();
m_journal.debug << " funds: " << accountFunds(view, j_.debug << " funds: " << accountFunds(view,
offers_direct.tip ().owner (), offers_direct.tip ().owner (),
offers_direct.tip ().amount ().out, offers_direct.tip ().amount ().out,
fhIGNORE_FREEZE, fhIGNORE_FREEZE,
getConfig()); ctx_.config);
} }
cross_result = taker.cross(offers_direct.tip ()); 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 ())) if (dry_offer (view, offers_direct.tip ()))
{ {
@@ -217,36 +208,36 @@ private:
} }
else else
{ {
if (m_journal.debug) if (j_.debug)
{ {
auto const owner1_funds_before = accountFunds(view, auto const owner1_funds_before = accountFunds(view,
offers_leg1.tip ().owner (), offers_leg1.tip ().owner (),
offers_leg1.tip ().amount ().out, offers_leg1.tip ().amount ().out,
fhIGNORE_FREEZE, fhIGNORE_FREEZE,
getConfig()); ctx_.config);
auto const owner2_funds_before = accountFunds(view, auto const owner2_funds_before = accountFunds(view,
offers_leg2.tip ().owner (), offers_leg2.tip ().owner (),
offers_leg2.tip ().amount ().out, offers_leg2.tip ().amount ().out,
fhIGNORE_FREEZE, fhIGNORE_FREEZE,
getConfig()); ctx_.config);
m_journal.debug << count << " Bridge:"; j_.debug << count << " Bridge:";
m_journal.debug << " offer1: " << offers_leg1.tip (); j_.debug << " offer1: " << offers_leg1.tip ();
m_journal.debug << " in: " << offers_leg1.tip ().amount().in; j_.debug << " in: " << offers_leg1.tip ().amount().in;
m_journal.debug << " out: " << offers_leg1.tip ().amount ().out; j_.debug << " out: " << offers_leg1.tip ().amount ().out;
m_journal.debug << " owner: " << offers_leg1.tip ().owner (); j_.debug << " owner: " << offers_leg1.tip ().owner ();
m_journal.debug << " funds: " << owner1_funds_before; j_.debug << " funds: " << owner1_funds_before;
m_journal.debug << " offer2: " << offers_leg2.tip (); j_.debug << " offer2: " << offers_leg2.tip ();
m_journal.debug << " in: " << offers_leg2.tip ().amount ().in; j_.debug << " in: " << offers_leg2.tip ().amount ().in;
m_journal.debug << " out: " << offers_leg2.tip ().amount ().out; j_.debug << " out: " << offers_leg2.tip ().amount ().out;
m_journal.debug << " owner: " << offers_leg2.tip ().owner (); j_.debug << " owner: " << offers_leg2.tip ().owner ();
m_journal.debug << " funds: " << owner2_funds_before; j_.debug << " funds: " << owner2_funds_before;
} }
cross_result = taker.cross(offers_leg1.tip (), offers_leg2.tip ()); 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 ())) if (dry_offer (view, offers_leg1.tip ()))
{ {
@@ -268,7 +259,7 @@ private:
if (taker.done()) 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; break;
} }
@@ -281,19 +272,19 @@ private:
} }
return std::make_pair(cross_result, taker.remaining_offer ()); return std::make_pair(cross_result, taker.remaining_offer ());
} }
std::pair<TER, Amounts> std::pair<TER, Amounts>
direct_cross ( CreateOffer::direct_cross (
Taker& taker, Taker& taker,
View& view, View& view,
View& view_cancel, View& view_cancel,
Clock::time_point const when) Clock::time_point const when)
{ {
OfferStream offers ( OfferStream offers (
view, view_cancel, view, view_cancel,
Book (taker.issue_in (), taker.issue_out ()), Book (taker.issue_in (), taker.issue_out ()),
when, m_journal); when, ctx_.config, j_);
TER cross_result (tesSUCCESS); TER cross_result (tesSUCCESS);
int count = 0; int count = 0;
@@ -313,20 +304,20 @@ private:
count++; count++;
if (m_journal.debug) if (j_.debug)
{ {
m_journal.debug << count << " Direct:"; j_.debug << count << " Direct:";
m_journal.debug << " offer: " << offer; j_.debug << " offer: " << offer;
m_journal.debug << " in: " << offer.amount ().in; j_.debug << " in: " << offer.amount ().in;
m_journal.debug << " out: " << offer.amount ().out; j_.debug << " out: " << offer.amount ().out;
m_journal.debug << " owner: " << offer.owner (); j_.debug << " owner: " << offer.owner ();
m_journal.debug << " funds: " << accountFunds(view, j_.debug << " funds: " << accountFunds(view,
offer.owner (), offer.amount ().out, fhIGNORE_FREEZE, getConfig()); offer.owner (), offer.amount ().out, fhIGNORE_FREEZE, ctx_.config);
} }
cross_result = taker.cross (offer); 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)) if (dry_offer (view, offer))
{ {
@@ -342,7 +333,7 @@ private:
if (taker.done()) 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; break;
} }
@@ -355,15 +346,14 @@ private:
} }
return std::make_pair(cross_result, taker.remaining_offer ()); return std::make_pair(cross_result, taker.remaining_offer ());
} }
// Step through the stream for as long as possible, skipping any offers // Step through the stream for as long as possible, skipping any offers
// that are from the taker or which cross the taker's threshold. // that are from the taker or which cross the taker's threshold.
// Return false if the is no offer in the book, true otherwise. // Return false if the is no offer in the book, true otherwise.
static bool
bool CreateOffer::step_account (OfferStream& stream, Taker const& taker)
step_account (OfferStream& stream, Taker const& taker) {
{
while (stream.step ()) while (stream.step ())
{ {
auto const& offer = stream.tip (); auto const& offer = stream.tip ();
@@ -379,25 +369,25 @@ private:
// We ran out of offers. Can't advance. // We ran out of offers. Can't advance.
return false; return false;
} }
// Fill offer as much as possible by consuming offers already on the books, // Fill offer as much as possible by consuming offers already on the books,
// and adjusting account balances accordingly. // and adjusting account balances accordingly.
// //
// Charges fees on top to taker. // Charges fees on top to taker.
std::pair<TER, Amounts> std::pair<TER, Amounts>
cross ( CreateOffer::cross (
View& view, View& view,
View& cancel_view, View& cancel_view,
Amounts const& taker_amount) Amounts const& taker_amount)
{ {
Clock::time_point const when = 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, Taker taker (cross_type_, view, mTxnAccountID, taker_amount,
mTxn.getFlags(), beast::Journal (takerSink)); mTxn.getFlags(), ctx_.config, beast::Journal (takerSink));
try try
{ {
@@ -408,58 +398,50 @@ private:
} }
catch (std::exception const& e) 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 ()); return std::make_pair (tecINTERNAL, taker.remaining_offer ());
} }
catch (...) catch (...)
{ {
m_journal.error << "Exception during offer crossing."; j_.error << "Exception during offer crossing.";
return std::make_pair (tecINTERNAL, taker.remaining_offer ()); return std::make_pair (tecINTERNAL, taker.remaining_offer ());
} }
} }
static std::string
std::string CreateOffer::format_amount (STAmount const& amount)
format_amount (STAmount const& amount) {
{
std::string txt = amount.getText (); std::string txt = amount.getText ();
txt += "/"; txt += "/";
txt += to_string (amount.issue().currency); txt += to_string (amount.issue().currency);
return txt; return txt;
} }
public: STAmount
CreateOffer ( CreateOffer::getAccountReserve (SLE::pointer account)
CrossType cross_type, {
STTx const& txn, return STAmount (ctx_.view().fees().accountReserve(
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(
account->getFieldU32 (sfOwnerCount) + 1)); 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 (); std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfOfferCreateMask) if (uTxFlags & tfOfferCreateMask)
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"Malformed transaction: Invalid flags set."; "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -469,7 +451,7 @@ public:
if (bImmediateOrCancel && bFillOrKill) if (bImmediateOrCancel && bFillOrKill)
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"Malformed transaction: both IoC and FoK set."; "Malformed transaction: both IoC and FoK set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -478,7 +460,7 @@ public:
if (bHaveExpiration && (mTxn.getFieldU32 (sfExpiration) == 0)) if (bHaveExpiration && (mTxn.getFieldU32 (sfExpiration) == 0))
{ {
if (m_journal.debug) m_journal.warning << if (j_.debug) j_.warning <<
"Malformed offer: bad expiration"; "Malformed offer: bad expiration";
return temBAD_EXPIRATION; return temBAD_EXPIRATION;
} }
@@ -487,7 +469,7 @@ public:
if (bHaveCancel && (mTxn.getFieldU32 (sfOfferSequence) == 0)) if (bHaveCancel && (mTxn.getFieldU32 (sfOfferSequence) == 0))
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"Malformed offer: bad cancel sequence"; "Malformed offer: bad cancel sequence";
return temBAD_SEQUENCE; return temBAD_SEQUENCE;
} }
@@ -500,13 +482,13 @@ public:
if (saTakerPays.native () && saTakerGets.native ()) if (saTakerPays.native () && saTakerGets.native ())
{ {
if (m_journal.debug) m_journal.warning << if (j_.debug) j_.warning <<
"Malformed offer: XRP for XRP"; "Malformed offer: XRP for XRP";
return temBAD_OFFER; return temBAD_OFFER;
} }
if (saTakerPays <= zero || saTakerGets <= zero) if (saTakerPays <= zero || saTakerGets <= zero)
{ {
if (m_journal.debug) m_journal.warning << if (j_.debug) j_.warning <<
"Malformed offer: bad amount"; "Malformed offer: bad amount";
return temBAD_OFFER; return temBAD_OFFER;
} }
@@ -519,14 +501,14 @@ public:
if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID) if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID)
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"Malformed offer: redundant offer"; "Malformed offer: redundant offer";
return temREDUNDANT; return temREDUNDANT;
} }
// We don't allow a non-native currency to use the currency code XRP. // We don't allow a non-native currency to use the currency code XRP.
if (badCurrency() == uPaysCurrency || badCurrency() == uGetsCurrency) if (badCurrency() == uPaysCurrency || badCurrency() == uGetsCurrency)
{ {
if (m_journal.debug) m_journal.warning << if (j_.debug) j_.warning <<
"Malformed offer: Bad currency."; "Malformed offer: Bad currency.";
return temBAD_CURRENCY; return temBAD_CURRENCY;
} }
@@ -534,17 +516,17 @@ public:
if (saTakerPays.native () != !uPaysIssuerID || if (saTakerPays.native () != !uPaysIssuerID ||
saTakerGets.native () != !uGetsIssuerID) saTakerGets.native () != !uGetsIssuerID)
{ {
if (m_journal.warning) m_journal.warning << if (j_.warning) j_.warning <<
"Malformed offer: bad issuer"; "Malformed offer: bad issuer";
return temBAD_ISSUER; return temBAD_ISSUER;
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
std::pair<TER, bool> std::pair<TER, bool>
applyGuts (View& view, View& view_cancel) CreateOffer::applyGuts (View& view, View& view_cancel)
{ {
std::uint32_t const uTxFlags = mTxn.getFlags (); std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const bPassive (uTxFlags & tfPassive); bool const bPassive (uTxFlags & tfPassive);
@@ -591,15 +573,15 @@ public:
if (isGlobalFrozen (view, uPaysIssuerID) || isGlobalFrozen (view, uGetsIssuerID)) if (isGlobalFrozen (view, uPaysIssuerID) || isGlobalFrozen (view, uGetsIssuerID))
{ {
if (m_journal.warning) m_journal.warning << if (j_.warning) j_.warning <<
"Offer involves frozen asset"; "Offer involves frozen asset";
result = tecFROZEN; result = tecFROZEN;
} }
else if (accountFunds(view, mTxnAccountID, saTakerGets, 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."; "delay: Offers must be at least partially funded.";
result = tecUNFUNDED_OFFER; result = tecUNFUNDED_OFFER;
@@ -608,7 +590,7 @@ public:
// before the transaction sequence number. // before the transaction sequence number.
else if (bHaveCancel && (uAccountSequenceNext - 1 <= uCancelSequence)) else if (bHaveCancel && (uAccountSequenceNext - 1 <= uCancelSequence))
{ {
if (m_journal.debug) m_journal.debug << if (j_.debug) j_.debug <<
"uAccountSequenceNext=" << uAccountSequenceNext << "uAccountSequenceNext=" << uAccountSequenceNext <<
" uOfferSequence=" << uCancelSequence; " uOfferSequence=" << uCancelSequence;
@@ -617,7 +599,7 @@ public:
if (result != tesSUCCESS) if (result != tesSUCCESS)
{ {
m_journal.debug << "final result: " << transToken (result); j_.debug << "final result: " << transToken (result);
return { result, true }; return { result, true };
} }
@@ -632,7 +614,7 @@ public:
// to fail to delete it. // to fail to delete it.
if (sleCancel) if (sleCancel)
{ {
m_journal.debug << "Create cancels order " << uCancelSequence; j_.debug << "Create cancels order " << uCancelSequence;
result = offerDelete (view, sleCancel); result = offerDelete (view, sleCancel);
} }
} }
@@ -641,7 +623,7 @@ public:
// because we definitively know the time that it closed but we do not // because we definitively know the time that it closed but we do not
// know the closing time of the ledger that is under construction. // know the closing time of the ledger that is under construction.
if (bHaveExpiration && if (bHaveExpiration &&
(mEngine->view().time() >= uExpiration)) (ctx_.view().parentCloseTime() >= uExpiration))
{ {
return { tesSUCCESS, true }; return { tesSUCCESS, true };
} }
@@ -650,7 +632,8 @@ public:
if (result == tesSUCCESS && !saTakerPays.native ()) if (result == tesSUCCESS && !saTakerPays.native ())
result = checkAcceptAsset (Issue (uPaysCurrency, uPaysIssuerID)); result = checkAcceptAsset (Issue (uPaysCurrency, uPaysIssuerID));
bool const bOpenLedger (mParams & tapOPEN_LEDGER); bool const bOpenLedger =
ctx_.view().open();
bool crossed = false; bool crossed = false;
if (result == tesSUCCESS) if (result == tesSUCCESS)
@@ -663,27 +646,27 @@ public:
// empty (fully crossed), or something in-between. // empty (fully crossed), or something in-between.
Amounts place_offer; Amounts place_offer;
m_journal.debug << "Attempting cross: " << j_.debug << "Attempting cross: " <<
to_string (taker_amount.in.issue ()) << " -> " << to_string (taker_amount.in.issue ()) << " -> " <<
to_string (taker_amount.out.issue ()); to_string (taker_amount.out.issue ());
if (m_journal.trace) if (j_.trace)
{ {
m_journal.debug << " mode: " << j_.debug << " mode: " <<
(bPassive ? "passive " : "") << (bPassive ? "passive " : "") <<
(bSell ? "sell" : "buy"); (bSell ? "sell" : "buy");
m_journal.trace <<" in: " << format_amount (taker_amount.in); j_.trace <<" in: " << format_amount (taker_amount.in);
m_journal.trace << " out: " << format_amount (taker_amount.out); j_.trace << " out: " << format_amount (taker_amount.out);
} }
std::tie(result, place_offer) = cross (view, view_cancel, taker_amount); std::tie(result, place_offer) = cross (view, view_cancel, taker_amount);
assert (result != tefINTERNAL); assert (result != tefINTERNAL);
if (m_journal.trace) if (j_.trace)
{ {
m_journal.trace << "Cross result: " << transToken (result); j_.trace << "Cross result: " << transToken (result);
m_journal.trace << " in: " << format_amount (place_offer.in); j_.trace << " in: " << format_amount (place_offer.in);
m_journal.trace << " out: " << format_amount (place_offer.out); j_.trace << " out: " << format_amount (place_offer.out);
} }
if (result == tecFAILED_PROCESSING && bOpenLedger) if (result == tecFAILED_PROCESSING && bOpenLedger)
@@ -691,7 +674,7 @@ public:
if (result != tesSUCCESS) if (result != tesSUCCESS)
{ {
m_journal.debug << "final result: " << transToken (result); j_.debug << "final result: " << transToken (result);
return { result, true }; return { result, true };
} }
@@ -705,7 +688,7 @@ public:
// never be negative. If it is, something went very very wrong. // never be negative. If it is, something went very very wrong.
if (place_offer.in < zero || place_offer.out < zero) 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) << " in: " << format_amount (place_offer.in) <<
" out: " << format_amount (place_offer.out); " out: " << format_amount (place_offer.out);
return { tefINTERNAL, true }; return { tefINTERNAL, true };
@@ -713,7 +696,7 @@ public:
if (place_offer.in == zero || place_offer.out == zero) if (place_offer.in == zero || place_offer.out == zero)
{ {
m_journal.debug << "Offer fully crossed!"; j_.debug << "Offer fully crossed!";
return { result, true }; return { result, true };
} }
@@ -728,22 +711,22 @@ public:
if (result != tesSUCCESS) if (result != tesSUCCESS)
{ {
m_journal.debug << "final result: " << transToken (result); j_.debug << "final result: " << transToken (result);
return { result, true }; return { result, true };
} }
if (m_journal.trace) if (j_.trace)
{ {
m_journal.trace << "Place" << (crossed ? " remaining " : " ") << "offer:"; j_.trace << "Place" << (crossed ? " remaining " : " ") << "offer:";
m_journal.trace << " Pays: " << saTakerPays.getFullText (); j_.trace << " Pays: " << saTakerPays.getFullText ();
m_journal.trace << " Gets: " << saTakerGets.getFullText (); j_.trace << " Gets: " << saTakerGets.getFullText ();
} }
// For 'fill or kill' offers, failure to fully cross means that the // For 'fill or kill' offers, failure to fully cross means that the
// entire operation should be aborted, with only fees paid. // entire operation should be aborted, with only fees paid.
if (bFillOrKill) if (bFillOrKill)
{ {
m_journal.trace << "Fill or Kill: offer killed"; j_.trace << "Fill or Kill: offer killed";
return { tesSUCCESS, false }; return { tesSUCCESS, false };
} }
@@ -751,7 +734,7 @@ public:
// placed - it gets cancelled and the operation succeeds. // placed - it gets cancelled and the operation succeeds.
if (bImmediateOrCancel) if (bImmediateOrCancel)
{ {
m_journal.trace << "Immediate or cancel: offer cancelled"; j_.trace << "Immediate or cancel: offer cancelled";
return { tesSUCCESS, true }; return { tesSUCCESS, true };
} }
@@ -764,7 +747,7 @@ public:
result = tecINSUF_RESERVE_OFFER; result = tecINSUF_RESERVE_OFFER;
if (result != tesSUCCESS) if (result != tesSUCCESS)
m_journal.debug << "final result: " << transToken (result); j_.debug << "final result: " << transToken (result);
return { result, true }; return { result, true };
} }
@@ -788,7 +771,7 @@ public:
// Update owner count. // Update owner count.
adjustOwnerCount(view, sleCreator, 1); adjustOwnerCount(view, sleCreator, 1);
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"adding to book: " << to_string (saTakerPays.issue ()) << "adding to book: " << to_string (saTakerPays.issue ()) <<
" : " << to_string (saTakerGets.issue ()); " : " << to_string (saTakerGets.issue ());
@@ -827,46 +810,26 @@ public:
} }
if (result != tesSUCCESS) if (result != tesSUCCESS)
m_journal.debug << "final result: " << transToken (result); j_.debug << "final result: " << transToken (result);
return { result, true }; 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 TER
transact_CreateOffer ( CreateOffer::doApply()
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{ {
CrossType cross_type = CrossType::IouToIou; // This is the ledger view that we work against. Transactions are applied
// as we go on processing transactions.
bool const pays_xrp = txn.getFieldAmount (sfTakerPays).native (); MetaView view (ctx_.view(), ctx_.view().flags());
bool const gets_xrp = txn.getFieldAmount (sfTakerGets).native (); // This is a checkpoint with just the fees paid. If something goes wrong
// with this transaction, we roll back to this ledger.
if (pays_xrp && !gets_xrp) MetaView viewCancel (ctx_.view(), ctx_.view().flags());
cross_type = CrossType::IouToXrp; auto const result = applyGuts(view, viewCancel);
else if (gets_xrp && !pays_xrp) if (result.second)
cross_type = CrossType::XrpToIou; view.apply(ctx_.view());
else
return CreateOffer (cross_type, txn, params, engine).apply (); viewCancel.apply(ctx_.view());
return result.first;
} }
} }

View 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

View File

@@ -18,55 +18,44 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #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/basics/Log.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
namespace ripple { namespace ripple {
class CreateTicket TER
: public Transactor CreateTicket::preCheck ()
{ {
public: #if ! RIPPLE_ENABLE_TICKETS
CreateTicket ( if (! (view().flags() & tapENABLE_TESTING))
STTx const& txn, return temDISABLED;
ViewFlags params, #endif
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
deprecatedLogs().journal("CreateTicket"))
{
}
TER
preCheck () override
{
if (mTxn.isFieldPresent (sfExpiration)) if (mTxn.isFieldPresent (sfExpiration))
{ {
if (mTxn.getFieldU32 (sfExpiration) == 0) if (mTxn.getFieldU32 (sfExpiration) == 0)
{ {
m_journal.warning << j_.warning <<
"Malformed transaction: bad expiration"; "Malformed transaction: bad expiration";
return temBAD_EXPIRATION; return temBAD_EXPIRATION;
} }
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
/** Returns the reserve the account would have if an offer was added. */ STAmount
STAmount CreateTicket::getAccountReserve (SLE::pointer account)
getAccountReserve (SLE::pointer account) {
{ return STAmount (view().fees().accountReserve(
return STAmount (mEngine->view().fees().accountReserve(
account->getFieldU32 (sfOwnerCount) + 1)); account->getFieldU32 (sfOwnerCount) + 1));
} }
TER doApply () override TER
{ CreateTicket::doApply ()
{
assert (mTxnAccount); assert (mTxnAccount);
// A ticket counts against the reserve of the issuing account, but we // A ticket counts against the reserve of the issuing account, but we
@@ -81,7 +70,7 @@ public:
{ {
expiration = mTxn.getFieldU32 (sfExpiration); expiration = mTxn.getFieldU32 (sfExpiration);
if (mEngine->view().time() >= expiration) if (view().parentCloseTime() >= expiration)
return tesSUCCESS; return tesSUCCESS;
} }
@@ -91,13 +80,13 @@ public:
sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ()); sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ());
if (expiration != 0) if (expiration != 0)
sleTicket->setFieldU32 (sfExpiration, expiration); sleTicket->setFieldU32 (sfExpiration, expiration);
mEngine->view().insert (sleTicket); view().insert (sleTicket);
if (mTxn.isFieldPresent (sfTarget)) if (mTxn.isFieldPresent (sfTarget))
{ {
AccountID const target_account (mTxn.getAccountID (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. // Destination account does not exist.
if (!sleTarget) if (!sleTarget)
@@ -116,13 +105,13 @@ public:
ownerDirDescriber(p, b, mTxnAccountID); ownerDirDescriber(p, b, mTxnAccountID);
}; };
TER result = dirAdd(mEngine->view(), TER result = dirAdd(view(),
hint, hint,
getOwnerDirIndex (mTxnAccountID), getOwnerDirIndex (mTxnAccountID),
sleTicket->getIndex (), sleTicket->getIndex (),
describer); describer);
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Creating ticket " << to_string (sleTicket->getIndex ()) << "Creating ticket " << to_string (sleTicket->getIndex ()) <<
": " << transHuman (result); ": " << transHuman (result);
@@ -132,23 +121,9 @@ public:
sleTicket->setFieldU64(sfOwnerNode, hint); sleTicket->setFieldU64(sfOwnerNode, hint);
// If we succeeded, the new entry counts agains the creator's reserve. // If we succeeded, the new entry counts agains the creator's reserve.
adjustOwnerCount(mEngine->view(), mTxnAccount, 1); adjustOwnerCount(view(), mTxnAccount, 1);
return result; 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 ();
} }
} }

View 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

View File

@@ -23,13 +23,15 @@
namespace ripple { namespace ripple {
OfferStream::OfferStream (View& view, View& view_cancel, OfferStream::OfferStream (View& view, View& view_cancel,
BookRef book, Clock::time_point when, beast::Journal journal) BookRef book, Clock::time_point when,
: m_journal (journal) Config const& config, beast::Journal journal)
: j_ (journal)
, m_view (view) , m_view (view)
, m_view_cancel (view_cancel) , m_view_cancel (view_cancel)
, m_book (book) , m_book (book)
, m_when (when) , m_when (when)
, m_tip (view, book) , m_tip (view, book)
, config_ (config)
{ {
} }
@@ -46,7 +48,7 @@ OfferStream::erase (View& view)
if (p == nullptr) if (p == nullptr)
{ {
if (m_journal.error) m_journal.error << if (j_.error) j_.error <<
"Missing directory " << m_tip.dir() << "Missing directory " << m_tip.dir() <<
" for offer " << m_tip.index(); " for offer " << m_tip.index();
return; return;
@@ -57,7 +59,7 @@ OfferStream::erase (View& view)
if (it == v.end()) if (it == v.end())
{ {
if (m_journal.error) m_journal.error << if (j_.error) j_.error <<
"Missing offer " << m_tip.index() << "Missing offer " << m_tip.index() <<
" for directory " << m_tip.dir(); " for directory " << m_tip.dir();
return; return;
@@ -67,7 +69,7 @@ OfferStream::erase (View& view)
p->setFieldV256 (sfIndexes, v); p->setFieldV256 (sfIndexes, v);
view.update (p); view.update (p);
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Missing offer " << m_tip.index() << "Missing offer " << m_tip.index() <<
" removed from directory " << m_tip.dir(); " removed from directory " << m_tip.dir();
} }
@@ -99,7 +101,7 @@ OfferStream::step ()
if (entry->isFieldPresent (sfExpiration) && if (entry->isFieldPresent (sfExpiration) &&
entry->getFieldU32 (sfExpiration) <= m_when) entry->getFieldU32 (sfExpiration) <= m_when)
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Removing expired offer " << entry->getIndex(); "Removing expired offer " << entry->getIndex();
offerDelete (view_cancel(), offerDelete (view_cancel(),
view_cancel().peek( view_cancel().peek(
@@ -114,7 +116,7 @@ OfferStream::step ()
// Remove if either amount is zero // Remove if either amount is zero
if (amount.empty()) if (amount.empty())
{ {
if (m_journal.warning) m_journal.warning << if (j_.warning) j_.warning <<
"Removing bad offer " << entry->getIndex(); "Removing bad offer " << entry->getIndex();
offerDelete (view_cancel(), offerDelete (view_cancel(),
view_cancel().peek( view_cancel().peek(
@@ -128,7 +130,7 @@ OfferStream::step ()
// looking up the funds twice? // looking up the funds twice?
auto const owner_funds = accountFunds(view(), auto const owner_funds = accountFunds(view(),
m_offer.owner(), amount.out, fhZERO_IF_FROZEN, m_offer.owner(), amount.out, fhZERO_IF_FROZEN,
getConfig()); config_);
// Check for unfunded offer // Check for unfunded offer
if (owner_funds <= zero) if (owner_funds <= zero)
@@ -138,18 +140,18 @@ OfferStream::step ()
// offer is "found unfunded" versus "became unfunded" // offer is "found unfunded" versus "became unfunded"
auto const original_funds = accountFunds(view_cancel(), auto const original_funds = accountFunds(view_cancel(),
m_offer.owner(), amount.out, fhZERO_IF_FROZEN, m_offer.owner(), amount.out, fhZERO_IF_FROZEN,
getConfig()); config_);
if (original_funds == owner_funds) if (original_funds == owner_funds)
{ {
offerDelete (view_cancel(), view_cancel().peek( offerDelete (view_cancel(), view_cancel().peek(
keylet::offer(entry->key()))); keylet::offer(entry->key())));
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Removing unfunded offer " << entry->getIndex(); "Removing unfunded offer " << entry->getIndex();
} }
else else
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Removing became unfunded offer " << entry->getIndex(); "Removing became unfunded offer " << entry->getIndex();
} }
m_offer = Offer{}; m_offer = Offer{};

View File

@@ -50,20 +50,23 @@ namespace ripple {
class OfferStream class OfferStream
{ {
private: private:
beast::Journal m_journal; beast::Journal j_;
std::reference_wrapper <View> m_view; std::reference_wrapper <View> m_view;
std::reference_wrapper <View> m_view_cancel; std::reference_wrapper <View> m_view_cancel;
Book m_book; Book m_book;
Clock::time_point m_when; Clock::time_point m_when;
BookTip m_tip; BookTip m_tip;
Offer m_offer; Offer m_offer;
Config const& config_;
void void
erase (View& view); erase (View& view);
public: public:
OfferStream (View& view, View& view_cancel, BookRef book, OfferStream (View& view, View& view_cancel,
Clock::time_point when, beast::Journal journal); BookRef book, Clock::time_point when,
Config const& config,
beast::Journal journal);
View& View&
view () noexcept view () noexcept

View File

@@ -18,8 +18,8 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Payment.h>
#include <ripple/app/paths/RippleCalc.h> #include <ripple/app/paths/RippleCalc.h>
#include <ripple/app/tx/impl/Transactor.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
@@ -27,36 +27,14 @@ namespace ripple {
// See https://ripple.com/wiki/Transaction_Format#Payment_.280.29 // See https://ripple.com/wiki/Transaction_Format#Payment_.280.29
class Payment TER
: public Transactor 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 (); std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfPaymentMask) if (uTxFlags & tfPaymentMask)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Invalid flags set."; "Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -94,25 +72,25 @@ public:
if (!uDstAccountID) if (!uDstAccountID)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Payment destination account not specified."; "Payment destination account not specified.";
return temDST_NEEDED; return temDST_NEEDED;
} }
if (bMax && maxSourceAmount <= zero) if (bMax && maxSourceAmount <= zero)
{ {
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"bad max amount: " << maxSourceAmount.getFullText (); "bad max amount: " << maxSourceAmount.getFullText ();
return temBAD_AMOUNT; return temBAD_AMOUNT;
} }
if (saDstAmount <= zero) if (saDstAmount <= zero)
{ {
m_journal.trace << "Malformed transaction: "<< j_.trace << "Malformed transaction: "<<
"bad dst amount: " << saDstAmount.getFullText (); "bad dst amount: " << saDstAmount.getFullText ();
return temBAD_AMOUNT; return temBAD_AMOUNT;
} }
if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency) if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
{ {
m_journal.trace <<"Malformed transaction: " << j_.trace <<"Malformed transaction: " <<
"Bad currency."; "Bad currency.";
return temBAD_CURRENCY; return temBAD_CURRENCY;
} }
@@ -120,7 +98,7 @@ public:
{ {
// You're signing yourself a payment. // You're signing yourself a payment.
// If bPaths is true, you might be trying some arbitrage. // 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) << "Redundant payment from " << to_string (mTxnAccountID) <<
" to self without path for " << to_string (uDstCurrency); " to self without path for " << to_string (uDstCurrency);
return temREDUNDANT; return temREDUNDANT;
@@ -128,44 +106,45 @@ public:
if (bXRPDirect && bMax) if (bXRPDirect && bMax)
{ {
// Consistent but redundant transaction. // Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"SendMax specified for XRP to XRP."; "SendMax specified for XRP to XRP.";
return temBAD_SEND_XRP_MAX; return temBAD_SEND_XRP_MAX;
} }
if (bXRPDirect && bPaths) if (bXRPDirect && bPaths)
{ {
// XRP is sent without paths. // XRP is sent without paths.
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Paths specified for XRP to XRP."; "Paths specified for XRP to XRP.";
return temBAD_SEND_XRP_PATHS; return temBAD_SEND_XRP_PATHS;
} }
if (bXRPDirect && partialPaymentAllowed) if (bXRPDirect && partialPaymentAllowed)
{ {
// Consistent but redundant transaction. // Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Partial payment specified for XRP to XRP."; "Partial payment specified for XRP to XRP.";
return temBAD_SEND_XRP_PARTIAL; return temBAD_SEND_XRP_PARTIAL;
} }
if (bXRPDirect && limitQuality) if (bXRPDirect && limitQuality)
{ {
// Consistent but redundant transaction. // Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"Limit quality specified for XRP to XRP."; "Limit quality specified for XRP to XRP.";
return temBAD_SEND_XRP_LIMIT; return temBAD_SEND_XRP_LIMIT;
} }
if (bXRPDirect && !defaultPathsAllowed) if (bXRPDirect && !defaultPathsAllowed)
{ {
// Consistent but redundant transaction. // Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " << j_.trace << "Malformed transaction: " <<
"No ripple direct specified for XRP to XRP."; "No ripple direct specified for XRP to XRP.";
return temBAD_SEND_XRP_NO_DIRECT; return temBAD_SEND_XRP_NO_DIRECT;
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
TER doApply () override TER
{ Payment::doApply ()
{
// Ripple if source or destination is non-native or if there are paths. // Ripple if source or destination is non-native or if there are paths.
std::uint32_t const uTxFlags = mTxn.getFlags (); std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment; bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
@@ -186,31 +165,32 @@ public:
saDstAmount.mantissa(), saDstAmount.exponent (), saDstAmount.mantissa(), saDstAmount.exponent (),
saDstAmount < zero); saDstAmount < zero);
m_journal.trace << j_.trace <<
"maxSourceAmount=" << maxSourceAmount.getFullText () << "maxSourceAmount=" << maxSourceAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText (); " saDstAmount=" << saDstAmount.getFullText ();
// Open a ledger for editing. // Open a ledger for editing.
auto const k = keylet::account(uDstAccountID); auto const k = keylet::account(uDstAccountID);
SLE::pointer sleDst = mEngine->view().peek (k); SLE::pointer sleDst = view().peek (k);
if (!sleDst) if (!sleDst)
{ {
// Destination account does not exist. // Destination account does not exist.
if (!saDstAmount.native ()) if (!saDstAmount.native ())
{ {
m_journal.trace << j_.trace <<
"Delay transaction: Destination account does not exist."; "Delay transaction: Destination account does not exist.";
// Another transaction could create the account and then this // Another transaction could create the account and then this
// transaction would succeed. // transaction would succeed.
return tecNO_DST; return tecNO_DST;
} }
else if (mParams & tapOPEN_LEDGER && partialPaymentAllowed) else if (view().open()
&& partialPaymentAllowed)
{ {
// You cannot fund an account with a partial payment. // You cannot fund an account with a partial payment.
// Make retry work smaller, by rejecting this. // Make retry work smaller, by rejecting this.
m_journal.trace << j_.trace <<
"Delay transaction: Partial payment not allowed to create account."; "Delay transaction: Partial payment not allowed to create account.";
@@ -218,11 +198,11 @@ public:
// transaction would succeed. // transaction would succeed.
return telNO_DST_PARTIAL; 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. // getReserve() is the minimum amount that an account can have.
// Reserve is not scaled by load. // Reserve is not scaled by load.
m_journal.trace << j_.trace <<
"Delay transaction: Destination account does not exist. " << "Delay transaction: Destination account does not exist. " <<
"Insufficent payment to create account."; "Insufficent payment to create account.";
@@ -236,7 +216,7 @@ public:
sleDst = std::make_shared<SLE>(k); sleDst = std::make_shared<SLE>(k);
sleDst->setAccountID (sfAccount, uDstAccountID); sleDst->setAccountID (sfAccount, uDstAccountID);
sleDst->setFieldU32 (sfSequence, 1); sleDst->setFieldU32 (sfSequence, 1);
mEngine->view().insert(sleDst); view().insert(sleDst);
} }
else if ((sleDst->getFlags () & lsfRequireDestTag) && else if ((sleDst->getFlags () & lsfRequireDestTag) &&
!mTxn.isFieldPresent (sfDestinationTag)) !mTxn.isFieldPresent (sfDestinationTag))
@@ -246,7 +226,7 @@ public:
// We didn't make this test for a newly-formed account because there's // We didn't make this test for a newly-formed account because there's
// no way for this field to be set. // 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; return tecDST_TAG_NEEDED;
} }
@@ -255,7 +235,7 @@ public:
// Tell the engine that we are intending to change the the destination // 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 // account. The source account gets always charged a fee so it's always
// marked as modified. // marked as modified.
mEngine->view().update (sleDst); view().update (sleDst);
} }
TER terResult; TER terResult;
@@ -278,7 +258,7 @@ public:
rcInput.defaultPathsAllowed = defaultPathsAllowed; rcInput.defaultPathsAllowed = defaultPathsAllowed;
rcInput.limitQuality = limitQuality; rcInput.limitQuality = limitQuality;
rcInput.deleteUnfundedOffers = true; rcInput.deleteUnfundedOffers = true;
rcInput.isLedgerOpen = static_cast<bool>(mParams & tapOPEN_LEDGER); rcInput.isLedgerOpen = view().open();
bool pathTooBig = spsPaths.size () > MaxPathSize; bool pathTooBig = spsPaths.size () > MaxPathSize;
@@ -294,9 +274,9 @@ public:
{ {
path::RippleCalc::Output rc; path::RippleCalc::Output rc;
{ {
PaymentView view (&mEngine->view()); PaymentView pv (view(), view().flags());
rc = path::RippleCalc::rippleCalculate ( rc = path::RippleCalc::rippleCalculate (
view, pv,
maxSourceAmount, maxSourceAmount,
saDstAmount, saDstAmount,
uDstAccountID, uDstAccountID,
@@ -306,13 +286,13 @@ public:
// VFALCO NOTE We might not need to apply, depending // VFALCO NOTE We might not need to apply, depending
// on the TER. But always applying *should* // on the TER. But always applying *should*
// be safe. // be safe.
view.apply(mEngine->view()); pv.apply(view());
} }
// TODO: is this right? If the amount is the correct amount, was // TODO: is this right? If the amount is the correct amount, was
// the delivered amount previously set? // the delivered amount previously set?
if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount) if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount)
mEngine->deliverAmount (rc.actualAmountOut); ctx_.deliverAmount (rc.actualAmountOut);
terResult = rc.result (); terResult = rc.result ();
} }
@@ -324,7 +304,7 @@ public:
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
m_journal.trace << j_.trace <<
"Caught throw: " << e.what (); "Caught throw: " << e.what ();
terResult = tefEXCEPTION; terResult = tefEXCEPTION;
@@ -340,7 +320,7 @@ public:
// This is the total reserve in drops. // This is the total reserve in drops.
auto const uReserve = auto const uReserve =
mEngine->view().fees().accountReserve(uOwnerCount); view().fees().accountReserve(uOwnerCount);
// mPriorBalance is the balance on the sending account BEFORE the // mPriorBalance is the balance on the sending account BEFORE the
// fees were charged. We want to make sure we have enough reserve // 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 // Vote no. However the transaction might succeed, if applied in
// a different order. // a different order.
m_journal.trace << "Delay transaction: Insufficient funds: " << j_.trace << "Delay transaction: Insufficient funds: " <<
" " << mPriorBalance.getText () << " " << mPriorBalance.getText () <<
" / " << (saDstAmount + mmm).getText () << " / " << (saDstAmount + mmm).getText () <<
" (" << uReserve << ")"; " (" << uReserve << ")";
@@ -381,7 +361,7 @@ public:
if (transResultInfo (terResult, strToken, strHuman)) if (transResultInfo (terResult, strToken, strHuman))
{ {
m_journal.trace << j_.trace <<
strToken << ": " << strHuman; strToken << ": " << strHuman;
} }
else else
@@ -390,16 +370,6 @@ public:
} }
return terResult; return terResult;
}
};
TER
transact_Payment (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{
return Payment(txn, params, engine).apply ();
} }
} // ripple } // ripple

View 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

View File

@@ -18,7 +18,7 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Transactor.h> #include <ripple/app/tx/impl/SetAccount.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/core/Config.h> #include <ripple/core/Config.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
@@ -27,33 +27,14 @@
namespace ripple { namespace ripple {
class SetAccount TER
: public Transactor 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 (); std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfAccountSetMask) if (uTxFlags & tfAccountSetMask)
{ {
m_journal.trace << "Malformed transaction: Invalid flags set."; j_.trace << "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -62,7 +43,7 @@ public:
if ((uSetFlag != 0) && (uSetFlag == uClearFlag)) 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; return temINVALID_FLAG;
} }
@@ -74,7 +55,7 @@ public:
if (bSetRequireAuth && bClearRequireAuth) if (bSetRequireAuth && bClearRequireAuth)
{ {
m_journal.trace << "Malformed transaction: Contradictory flags set."; j_.trace << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -86,7 +67,7 @@ public:
if (bSetRequireDest && bClearRequireDest) if (bSetRequireDest && bClearRequireDest)
{ {
m_journal.trace << "Malformed transaction: Contradictory flags set."; j_.trace << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -98,7 +79,7 @@ public:
if (bSetDisallowXRP && bClearDisallowXRP) if (bSetDisallowXRP && bClearDisallowXRP)
{ {
m_journal.trace << "Malformed transaction: Contradictory flags set."; j_.trace << "Malformed transaction: Contradictory flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -109,16 +90,17 @@ public:
if (uRate && (uRate < QUALITY_ONE)) 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 temBAD_TRANSFER_RATE;
} }
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
TER doApply () override TER
{ SetAccount::doApply ()
{
std::uint32_t const uTxFlags = mTxn.getFlags (); std::uint32_t const uTxFlags = mTxn.getFlags ();
std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags); std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
@@ -140,20 +122,20 @@ public:
// //
if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth)) if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
{ {
if (! dirIsEmpty (mEngine->view(), if (! dirIsEmpty (view(),
keylet::ownerDir(mTxnAccountID))) keylet::ownerDir(mTxnAccountID)))
{ {
m_journal.trace << "Retry: Owner directory not empty."; j_.trace << "Retry: Owner directory not empty.";
return (mParams & tapRETRY) ? terOWNERS : tecOWNERS; return (view().flags() & tapRETRY) ? terOWNERS : tecOWNERS;
} }
m_journal.trace << "Set RequireAuth."; j_.trace << "Set RequireAuth.";
uFlagsOut |= lsfRequireAuth; uFlagsOut |= lsfRequireAuth;
} }
if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth)) if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
{ {
m_journal.trace << "Clear RequireAuth."; j_.trace << "Clear RequireAuth.";
uFlagsOut &= ~lsfRequireAuth; uFlagsOut &= ~lsfRequireAuth;
} }
@@ -162,13 +144,13 @@ public:
// //
if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag)) if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
{ {
m_journal.trace << "Set lsfRequireDestTag."; j_.trace << "Set lsfRequireDestTag.";
uFlagsOut |= lsfRequireDestTag; uFlagsOut |= lsfRequireDestTag;
} }
if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag)) if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
{ {
m_journal.trace << "Clear lsfRequireDestTag."; j_.trace << "Clear lsfRequireDestTag.";
uFlagsOut &= ~lsfRequireDestTag; uFlagsOut &= ~lsfRequireDestTag;
} }
@@ -177,13 +159,13 @@ public:
// //
if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP)) if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
{ {
m_journal.trace << "Set lsfDisallowXRP."; j_.trace << "Set lsfDisallowXRP.";
uFlagsOut |= lsfDisallowXRP; uFlagsOut |= lsfDisallowXRP;
} }
if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP)) if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
{ {
m_journal.trace << "Clear lsfDisallowXRP."; j_.trace << "Clear lsfDisallowXRP.";
uFlagsOut &= ~lsfDisallowXRP; uFlagsOut &= ~lsfDisallowXRP;
} }
@@ -194,20 +176,20 @@ public:
{ {
if (!mSigMaster) 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; return tecNEED_MASTER_KEY;
} }
if (!mTxnAccount->isFieldPresent (sfRegularKey)) if (!mTxnAccount->isFieldPresent (sfRegularKey))
return tecNO_REGULAR_KEY; return tecNO_REGULAR_KEY;
m_journal.trace << "Set lsfDisableMaster."; j_.trace << "Set lsfDisableMaster.";
uFlagsOut |= lsfDisableMaster; uFlagsOut |= lsfDisableMaster;
} }
if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster)) if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
{ {
m_journal.trace << "Clear lsfDisableMaster."; j_.trace << "Clear lsfDisableMaster.";
uFlagsOut &= ~lsfDisableMaster; uFlagsOut &= ~lsfDisableMaster;
} }
@@ -230,18 +212,18 @@ public:
{ {
if (!mSigMaster && !(uFlagsIn & lsfDisableMaster)) 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; return tecNEED_MASTER_KEY;
} }
m_journal.trace << "Set NoFreeze flag"; j_.trace << "Set NoFreeze flag";
uFlagsOut |= lsfNoFreeze; uFlagsOut |= lsfNoFreeze;
} }
// Anyone may set global freeze // Anyone may set global freeze
if (uSetFlag == asfGlobalFreeze) if (uSetFlag == asfGlobalFreeze)
{ {
m_journal.trace << "Set GlobalFreeze flag"; j_.trace << "Set GlobalFreeze flag";
uFlagsOut |= lsfGlobalFreeze; uFlagsOut |= lsfGlobalFreeze;
} }
@@ -251,7 +233,7 @@ public:
if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) && if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
((uFlagsOut & lsfNoFreeze) == 0)) ((uFlagsOut & lsfNoFreeze) == 0))
{ {
m_journal.trace << "Clear GlobalFreeze flag"; j_.trace << "Clear GlobalFreeze flag";
uFlagsOut &= ~lsfGlobalFreeze; uFlagsOut &= ~lsfGlobalFreeze;
} }
@@ -260,13 +242,13 @@ public:
// //
if ((uSetFlag == asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID)) if ((uSetFlag == asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
{ {
m_journal.trace << "Set AccountTxnID"; j_.trace << "Set AccountTxnID";
mTxnAccount->makeFieldPresent (sfAccountTxnID); mTxnAccount->makeFieldPresent (sfAccountTxnID);
} }
if ((uClearFlag == asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID)) if ((uClearFlag == asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
{ {
m_journal.trace << "Clear AccountTxnID"; j_.trace << "Clear AccountTxnID";
mTxnAccount->makeFieldAbsent (sfAccountTxnID); mTxnAccount->makeFieldAbsent (sfAccountTxnID);
} }
@@ -279,12 +261,12 @@ public:
if (!uHash) if (!uHash)
{ {
m_journal.trace << "unset email hash"; j_.trace << "unset email hash";
mTxnAccount->makeFieldAbsent (sfEmailHash); mTxnAccount->makeFieldAbsent (sfEmailHash);
} }
else else
{ {
m_journal.trace << "set email hash"; j_.trace << "set email hash";
mTxnAccount->setFieldH128 (sfEmailHash, uHash); mTxnAccount->setFieldH128 (sfEmailHash, uHash);
} }
} }
@@ -298,12 +280,12 @@ public:
if (!uHash) if (!uHash)
{ {
m_journal.trace << "unset wallet locator"; j_.trace << "unset wallet locator";
mTxnAccount->makeFieldAbsent (sfWalletLocator); mTxnAccount->makeFieldAbsent (sfWalletLocator);
} }
else else
{ {
m_journal.trace << "set wallet locator"; j_.trace << "set wallet locator";
mTxnAccount->setFieldH256 (sfWalletLocator, uHash); mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
} }
} }
@@ -317,18 +299,18 @@ public:
if (messageKey.size () > PUBLIC_BYTES_MAX) if (messageKey.size () > PUBLIC_BYTES_MAX)
{ {
m_journal.trace << "message key too long"; j_.trace << "message key too long";
return telBAD_PUBLIC_KEY; return telBAD_PUBLIC_KEY;
} }
if (messageKey.empty ()) if (messageKey.empty ())
{ {
m_journal.debug << "set message key"; j_.debug << "set message key";
mTxnAccount->makeFieldAbsent (sfMessageKey); mTxnAccount->makeFieldAbsent (sfMessageKey);
} }
else else
{ {
m_journal.debug << "set message key"; j_.debug << "set message key";
mTxnAccount->setFieldVL (sfMessageKey, messageKey); mTxnAccount->setFieldVL (sfMessageKey, messageKey);
} }
} }
@@ -342,18 +324,18 @@ public:
if (domain.size () > DOMAIN_BYTES_MAX) if (domain.size () > DOMAIN_BYTES_MAX)
{ {
m_journal.trace << "domain too long"; j_.trace << "domain too long";
return telBAD_DOMAIN; return telBAD_DOMAIN;
} }
if (domain.empty ()) if (domain.empty ())
{ {
m_journal.trace << "unset domain"; j_.trace << "unset domain";
mTxnAccount->makeFieldAbsent (sfDomain); mTxnAccount->makeFieldAbsent (sfDomain);
} }
else else
{ {
m_journal.trace << "set domain"; j_.trace << "set domain";
mTxnAccount->setFieldVL (sfDomain, domain); mTxnAccount->setFieldVL (sfDomain, domain);
} }
} }
@@ -367,12 +349,12 @@ public:
if (uRate == 0 || uRate == QUALITY_ONE) if (uRate == 0 || uRate == QUALITY_ONE)
{ {
m_journal.trace << "unset transfer rate"; j_.trace << "unset transfer rate";
mTxnAccount->makeFieldAbsent (sfTransferRate); mTxnAccount->makeFieldAbsent (sfTransferRate);
} }
else if (uRate > QUALITY_ONE) else if (uRate > QUALITY_ONE)
{ {
m_journal.trace << "set transfer rate"; j_.trace << "set transfer rate";
mTxnAccount->setFieldU32 (sfTransferRate, uRate); mTxnAccount->setFieldU32 (sfTransferRate, uRate);
} }
} }
@@ -381,16 +363,6 @@ public:
mTxnAccount->setFieldU32 (sfFlags, uFlagsOut); mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);
return tesSUCCESS; return tesSUCCESS;
}
};
TER
transact_SetAccount (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{
return SetAccount(txn, params, engine).apply ();
} }
} }

View 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

View File

@@ -18,18 +18,16 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/Transactor.h> #include <ripple/app/tx/impl/SetRegularKey.h>
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
#include <ripple/protocol/types.h> #include <ripple/protocol/types.h>
namespace ripple { namespace ripple {
class SetRegularKey std::uint64_t
: public Transactor SetRegularKey::calculateBaseFee ()
{ {
std::uint64_t calculateBaseFee () override
{
if ( mTxnAccount if ( mTxnAccount
&& (! (mTxnAccount->getFlags () & lsfPasswordSpent)) && (! (mTxnAccount->getFlags () & lsfPasswordSpent))
&& (calcAccountID(mSigningPubKey) == mTxnAccountID)) && (calcAccountID(mSigningPubKey) == mTxnAccountID))
@@ -39,39 +37,27 @@ class SetRegularKey
} }
return Transactor::calculateBaseFee (); return Transactor::calculateBaseFee ();
} }
public: TER
SetRegularKey ( SetRegularKey::preCheck ()
STTx const& txn, {
ViewFlags params,
TransactionEngine* engine)
: Transactor (
txn,
params,
engine,
deprecatedLogs().journal("SetRegularKey"))
{
}
TER preCheck () override
{
std::uint32_t const uTxFlags = mTxn.getFlags (); std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfUniversalMask) if (uTxFlags & tfUniversalMask)
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Malformed transaction: Invalid flags set."; "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
TER doApply () override TER
{ SetRegularKey::doApply ()
{
if (mFeeDue == zero) if (mFeeDue == zero)
mTxnAccount->setFlag (lsfPasswordSpent); mTxnAccount->setFlag (lsfPasswordSpent);
@@ -88,16 +74,6 @@ public:
} }
return tesSUCCESS; return tesSUCCESS;
}
};
TER
transact_SetRegularKey (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{
return SetRegularKey(txn, params, engine).apply ();
} }
} }

View 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

View File

@@ -18,7 +18,8 @@
//============================================================================== //==============================================================================
#include <BeastConfig.h> #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/app/tx/impl/SignerEntries.h>
#include <ripple/protocol/STObject.h> #include <ripple/protocol/STObject.h>
#include <ripple/protocol/STArray.h> #include <ripple/protocol/STArray.h>
@@ -31,62 +32,6 @@
namespace ripple { 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 TER
SetSignerList::doApply () SetSignerList::doApply ()
{ {
@@ -116,6 +61,11 @@ SetSignerList::doApply ()
TER TER
SetSignerList::preCheck() 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. // We need the account ID later, so do this check first.
preCheckAccount (); preCheckAccount ();
@@ -127,7 +77,7 @@ SetSignerList::preCheck()
if (quorum_ && hasSignerEntries) if (quorum_ && hasSignerEntries)
{ {
SignerEntries::Decoded signers ( SignerEntries::Decoded signers (
SignerEntries::deserialize (mTxn, m_journal, "transaction")); SignerEntries::deserialize (mTxn, j_, "transaction"));
if (signers.ter != tesSUCCESS) if (signers.ter != tesSUCCESS)
return signers.ter; return signers.ter;
@@ -150,7 +100,7 @@ SetSignerList::preCheck()
else else
{ {
// Neither a set nor a destroy. Malformed. // 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."; "Malformed transaction: Invalid signer set list format.";
return temMALFORMED; return temMALFORMED;
} }
@@ -169,7 +119,7 @@ SetSignerList::validateQuorumAndSignerEntries (
if ((signerCount < SignerEntries::minEntries) if ((signerCount < SignerEntries::minEntries)
|| (signerCount > SignerEntries::maxEntries)) || (signerCount > SignerEntries::maxEntries))
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Too many or too few signers in signer list."; "Too many or too few signers in signer list.";
return temMALFORMED; return temMALFORMED;
} }
@@ -180,7 +130,7 @@ SetSignerList::validateQuorumAndSignerEntries (
if (std::adjacent_find ( if (std::adjacent_find (
signers.begin (), signers.end ()) != signers.end ()) signers.begin (), signers.end ()) != signers.end ())
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Duplicate signers in signer list"; "Duplicate signers in signer list";
return temBAD_SIGNER; return temBAD_SIGNER;
} }
@@ -194,7 +144,7 @@ SetSignerList::validateQuorumAndSignerEntries (
if (signer.account == mTxnAccountID) if (signer.account == mTxnAccountID)
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"A signer may not self reference account."; "A signer may not self reference account.";
return temBAD_SIGNER; return temBAD_SIGNER;
} }
@@ -204,7 +154,7 @@ SetSignerList::validateQuorumAndSignerEntries (
} }
if ((quorum <= 0) || (allSignersWeight < quorum)) if ((quorum <= 0) || (allSignersWeight < quorum))
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Quorum is unreachable"; "Quorum is unreachable";
return temBAD_QUORUM; return temBAD_QUORUM;
} }
@@ -225,7 +175,7 @@ SetSignerList::replaceSignerList (uint256 const& index)
std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ()); std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ());
auto const newReserve = auto const newReserve =
mEngine->view().fees().accountReserve( view().fees().accountReserve(
oldOwnerCount + addedOwnerCount); oldOwnerCount + addedOwnerCount);
// We check the reserve against the starting balance because we want to // 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. // Everything's ducky. Add the ltSIGNER_LIST to the ledger.
auto signerList = std::make_shared<SLE>(ltSIGNER_LIST, index); auto signerList = std::make_shared<SLE>(ltSIGNER_LIST, index);
mEngine->view().insert (signerList); view().insert (signerList);
writeSignersToLedger (signerList); writeSignersToLedger (signerList);
// Lambda for call to dirAdd. // Lambda for call to dirAdd.
@@ -247,10 +197,10 @@ SetSignerList::replaceSignerList (uint256 const& index)
// Add the signer list to the account's directory. // Add the signer list to the account's directory.
std::uint64_t hint; std::uint64_t hint;
TER result = dirAdd(mEngine->view (), TER result = dirAdd(ctx_.view (),
hint, getOwnerDirIndex (mTxnAccountID), index, describer); hint, getOwnerDirIndex (mTxnAccountID), index, describer);
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Create signer list for account " << "Create signer list for account " <<
mTxnAccountID << ": " << transHuman (result); mTxnAccountID << ": " << transHuman (result);
@@ -260,7 +210,7 @@ SetSignerList::replaceSignerList (uint256 const& index)
signerList->setFieldU64 (sfOwnerNode, hint); signerList->setFieldU64 (sfOwnerNode, hint);
// If we succeeded, the new entry counts against the creator's reserve. // If we succeeded, the new entry counts against the creator's reserve.
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
mTxnAccount, addedOwnerCount); mTxnAccount, addedOwnerCount);
return result; return result;
@@ -271,7 +221,7 @@ SetSignerList::destroySignerList (uint256 const& index)
{ {
// See if there's an ltSIGNER_LIST for this account. // See if there's an ltSIGNER_LIST for this account.
SLE::pointer signerList = 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 the signer list doesn't exist we've already succeeded in deleting it.
if (!signerList) if (!signerList)
@@ -282,7 +232,7 @@ SetSignerList::destroySignerList (uint256 const& index)
std::uint32_t removeFromOwnerCount = 0; std::uint32_t removeFromOwnerCount = 0;
auto const k = keylet::signers(mTxnAccountID); auto const k = keylet::signers(mTxnAccountID);
SLE::pointer accountSignersList = SLE::pointer accountSignersList =
mEngine->view().peek (k); view().peek (k);
if (accountSignersList) if (accountSignersList)
{ {
STArray const& actualList = STArray const& actualList =
@@ -293,14 +243,14 @@ SetSignerList::destroySignerList (uint256 const& index)
// Remove the node from the account directory. // Remove the node from the account directory.
std::uint64_t const hint (signerList->getFieldU64 (sfOwnerNode)); 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)); getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0));
if (result == tesSUCCESS) if (result == tesSUCCESS)
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
mTxnAccount, removeFromOwnerCount); mTxnAccount, removeFromOwnerCount);
mEngine->view ().erase (signerList); ctx_.view ().erase (signerList);
return result; return result;
} }
@@ -357,17 +307,4 @@ SetSignerList::ownerCountDelta (std::size_t entryCount)
return 2 + 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 } // namespace ripple

View 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

View File

@@ -19,36 +19,21 @@
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/protocol/Quality.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/basics/Log.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
namespace ripple { namespace ripple {
class SetTrust TER
: public Transactor 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 (); std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfTrustSetMask) if (uTxFlags & tfTrustSetMask)
{ {
m_journal.trace << j_.trace <<
"Malformed transaction: Invalid flags set."; "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
} }
@@ -60,7 +45,7 @@ public:
if (saLimitAmount.native ()) if (saLimitAmount.native ())
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Malformed transaction: specifies native limit " << "Malformed transaction: specifies native limit " <<
saLimitAmount.getFullText (); saLimitAmount.getFullText ();
return temBAD_LIMIT; return temBAD_LIMIT;
@@ -68,14 +53,14 @@ public:
if (badCurrency() == saLimitAmount.getCurrency ()) if (badCurrency() == saLimitAmount.getCurrency ())
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Malformed transaction: specifies XRP as IOU"; "Malformed transaction: specifies XRP as IOU";
return temBAD_CURRENCY; return temBAD_CURRENCY;
} }
if (saLimitAmount < zero) if (saLimitAmount < zero)
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Malformed transaction: Negative credit limit."; "Malformed transaction: Negative credit limit.";
return temBAD_LIMIT; return temBAD_LIMIT;
} }
@@ -85,16 +70,17 @@ public:
if (!issuer || issuer == noAccount()) if (!issuer || issuer == noAccount())
{ {
if (m_journal.trace) m_journal.trace << if (j_.trace) j_.trace <<
"Malformed transaction: no destination account."; "Malformed transaction: no destination account.";
return temDST_NEEDED; return temDST_NEEDED;
} }
return Transactor::preCheck (); return Transactor::preCheck ();
} }
TER doApply () override TER
{ SetTrust::doApply ()
{
TER terResult = tesSUCCESS; TER terResult = tesSUCCESS;
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount)); STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
@@ -123,7 +109,7 @@ public:
STAmount const reserveCreate ((uOwnerCount < 2) STAmount const reserveCreate ((uOwnerCount < 2)
? 0 ? 0
: mEngine->view().fees().accountReserve(uOwnerCount + 1)); : view().fees().accountReserve(uOwnerCount + 1));
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0); std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0); std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
@@ -141,7 +127,7 @@ public:
if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth)) if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth))
{ {
m_journal.trace << j_.trace <<
"Retry: Auth not required."; "Retry: Auth not required.";
return tefNO_AUTH_REQUIRED; return tefNO_AUTH_REQUIRED;
} }
@@ -152,31 +138,31 @@ public:
// trust line to oneself to be deleted. If no such trust // trust line to oneself to be deleted. If no such trust
// lines exist now, why not remove this code and simply // lines exist now, why not remove this code and simply
// return an error? // return an error?
SLE::pointer sleDelete = mEngine->view().peek ( SLE::pointer sleDelete = view().peek (
keylet::line(mTxnAccountID, uDstAccountID, currency)); keylet::line(mTxnAccountID, uDstAccountID, currency));
if (sleDelete) if (sleDelete)
{ {
m_journal.warning << j_.warning <<
"Clearing redundant line."; "Clearing redundant line.";
return trustDelete (mEngine->view(), return trustDelete (view(),
sleDelete, mTxnAccountID, uDstAccountID); sleDelete, mTxnAccountID, uDstAccountID);
} }
else else
{ {
m_journal.trace << j_.trace <<
"Malformed transaction: Can not extend credit to self."; "Malformed transaction: Can not extend credit to self.";
return temDST_IS_SRC; return temDST_IS_SRC;
} }
} }
SLE::pointer sleDst = SLE::pointer sleDst =
mEngine->view().peek (keylet::account(uDstAccountID)); view().peek (keylet::account(uDstAccountID));
if (!sleDst) if (!sleDst)
{ {
m_journal.trace << j_.trace <<
"Delay transaction: Destination account does not exist."; "Delay transaction: Destination account does not exist.";
return tecNO_DST; return tecNO_DST;
} }
@@ -184,7 +170,7 @@ public:
STAmount saLimitAllow = saLimitAmount; STAmount saLimitAllow = saLimitAmount;
saLimitAllow.setIssuer (mTxnAccountID); saLimitAllow.setIssuer (mTxnAccountID);
SLE::pointer sleRippleState = mEngine->view().peek ( SLE::pointer sleRippleState = view().peek (
keylet::line(mTxnAccountID, uDstAccountID, currency)); keylet::line(mTxnAccountID, uDstAccountID, currency));
if (sleRippleState) if (sleRippleState)
@@ -337,7 +323,7 @@ public:
if (bLowReserveSet && !bLowReserved) if (bLowReserveSet && !bLowReserved)
{ {
// Set reserve for low account. // Set reserve for low account.
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
sleLowAccount, 1); sleLowAccount, 1);
uFlagsOut |= lsfLowReserve; uFlagsOut |= lsfLowReserve;
@@ -348,7 +334,7 @@ public:
if (bLowReserveClear && bLowReserved) if (bLowReserveClear && bLowReserved)
{ {
// Clear reserve for low account. // Clear reserve for low account.
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
sleLowAccount, -1); sleLowAccount, -1);
uFlagsOut &= ~lsfLowReserve; uFlagsOut &= ~lsfLowReserve;
} }
@@ -356,7 +342,7 @@ public:
if (bHighReserveSet && !bHighReserved) if (bHighReserveSet && !bHighReserved)
{ {
// Set reserve for high account. // Set reserve for high account.
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
sleHighAccount, 1); sleHighAccount, 1);
uFlagsOut |= lsfHighReserve; uFlagsOut |= lsfHighReserve;
@@ -367,7 +353,7 @@ public:
if (bHighReserveClear && bHighReserved) if (bHighReserveClear && bHighReserved)
{ {
// Clear reserve for high account. // Clear reserve for high account.
adjustOwnerCount(mEngine->view(), adjustOwnerCount(view(),
sleHighAccount, -1); sleHighAccount, -1);
uFlagsOut &= ~lsfHighReserve; uFlagsOut &= ~lsfHighReserve;
} }
@@ -379,13 +365,13 @@ public:
{ {
// Delete. // Delete.
terResult = trustDelete (mEngine->view(), terResult = trustDelete (view(),
sleRippleState, uLowAccountID, uHighAccountID); sleRippleState, uLowAccountID, uHighAccountID);
} }
// Reserve is not scaled by load. // Reserve is not scaled by load.
else if (bReserveIncrease && mPriorBalance < reserveCreate) else if (bReserveIncrease && mPriorBalance < reserveCreate)
{ {
m_journal.trace << j_.trace <<
"Delay transaction: Insufficent reserve to add trust line."; "Delay transaction: Insufficent reserve to add trust line.";
// Another transaction could provide XRP to the account and then // Another transaction could provide XRP to the account and then
@@ -394,9 +380,9 @@ public:
} }
else else
{ {
mEngine->view().update (sleRippleState); view().update (sleRippleState);
m_journal.trace << "Modify ripple line"; j_.trace << "Modify ripple line";
} }
} }
// Line does not exist. // Line does not exist.
@@ -404,13 +390,13 @@ public:
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in. && (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out. && (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
{ {
m_journal.trace << j_.trace <<
"Redundant: Setting non-existent ripple line to defaults."; "Redundant: Setting non-existent ripple line to defaults.";
return tecNO_LINE_REDUNDANT; return tecNO_LINE_REDUNDANT;
} }
else if (mPriorBalance < reserveCreate) // Reserve is not scaled by load. 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."; "Delay transaction: Line does not exist. Insufficent reserve to create line.";
// Another transaction could create the account and then this transaction would succeed. // Another transaction could create the account and then this transaction would succeed.
@@ -424,12 +410,12 @@ public:
uint256 index (getRippleStateIndex ( uint256 index (getRippleStateIndex (
mTxnAccountID, uDstAccountID, currency)); mTxnAccountID, uDstAccountID, currency));
m_journal.trace << j_.trace <<
"doTrustSet: Creating ripple line: " << "doTrustSet: Creating ripple line: " <<
to_string (index); to_string (index);
// Create a new ripple line. // Create a new ripple line.
terResult = trustCreate (mEngine->view(), terResult = trustCreate (view(),
bHigh, bHigh,
mTxnAccountID, mTxnAccountID,
uDstAccountID, uDstAccountID,
@@ -445,16 +431,6 @@ public:
} }
return terResult; return terResult;
}
};
TER
transact_SetTrust (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine)
{
return SetTrust (txn, params, engine).apply ();
} }
} }

View 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

View File

@@ -515,23 +515,15 @@ BasicTaker::do_cross (
//============================================================================== //==============================================================================
std::uint32_t Taker::Taker (CrossType cross_type, View& view,
Taker::calculateRate ( AccountID const& account, Amounts const& offer,
View const& view, std::uint32_t flags, Config const& config,
AccountID const& issuer, beast::Journal journal)
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)
: BasicTaker (cross_type, account, offer, Quality(offer), flags, : BasicTaker (cross_type, account, offer, Quality(offer), flags,
calculateRate(view, offer.in.getIssuer(), account), calculateRate(view, offer.in.getIssuer(), account),
calculateRate(view, offer.out.getIssuer(), account), journal) calculateRate(view, offer.out.getIssuer(), account), journal)
, view_ (view) , view_ (view)
, config_ (config)
, xrp_flow_ (0) , xrp_flow_ (0)
, direct_crossings_ (0) , direct_crossings_ (0)
, bridge_crossings_ (0) , bridge_crossings_ (0)
@@ -587,7 +579,7 @@ STAmount
Taker::get_funds (AccountID const& account, STAmount const& amount) const Taker::get_funds (AccountID const& account, STAmount const& amount) const
{ {
return accountFunds(view_, account, amount, fhZERO_IF_FROZEN, return accountFunds(view_, account, amount, fhZERO_IF_FROZEN,
getConfig()); config_);
} }
TER Taker::transferXRP ( TER Taker::transferXRP (
@@ -779,4 +771,16 @@ Taker::cross (Offer const& leg1, Offer const& leg2)
return fill (ret.first, leg1, ret.second, 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

View File

@@ -21,6 +21,7 @@
#define RIPPLE_APP_BOOK_TAKER_H_INCLUDED #define RIPPLE_APP_BOOK_TAKER_H_INCLUDED
#include <ripple/app/tx/impl/Offer.h> #include <ripple/app/tx/impl/Offer.h>
#include <ripple/core/Config.h>
#include <ripple/ledger/View.h> #include <ripple/ledger/View.h>
#include <ripple/protocol/Quality.h> #include <ripple/protocol/Quality.h>
#include <ripple/protocol/TER.h> #include <ripple/protocol/TER.h>
@@ -239,48 +240,14 @@ public:
class Taker class Taker
: public BasicTaker : 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: public:
Taker () = delete; Taker () = delete;
Taker (Taker const&) = delete; Taker (Taker const&) = delete;
Taker (CrossType cross_type, View& view, AccountID const& account, Taker (CrossType cross_type, View& view,
Amounts const& offer, std::uint32_t flags, beast::Journal journal); AccountID const& account, Amounts const& offer,
std::uint32_t flags, Config const& config,
beast::Journal journal);
~Taker () = default; ~Taker () = default;
void void
@@ -318,6 +285,45 @@ public:
TER TER
cross (Offer const& leg1, Offer const& leg2); 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_;
}; };
} }

View File

@@ -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

View File

@@ -21,94 +21,36 @@
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/tx/impl/Transactor.h> #include <ripple/app/tx/impl/Transactor.h>
#include <ripple/app/tx/impl/SignerEntries.h> #include <ripple/app/tx/impl/SignerEntries.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h> #include <ripple/core/Config.h>
#include <ripple/core/LoadFeeTrack.h> #include <ripple/core/LoadFeeTrack.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
#include <ripple/protocol/types.h> #include <ripple/protocol/types.h>
namespace ripple { namespace ripple {
TER transact_Payment (STTx const& txn, ViewFlags params, TransactionEngine* engine); Transactor::Transactor(
TER transact_SetAccount (STTx const& txn, ViewFlags params, TransactionEngine* engine); ApplyContext& ctx)
TER transact_SetRegularKey (STTx const& txn, ViewFlags params, TransactionEngine* engine); : mTxn (ctx.tx)
TER transact_SetTrust (STTx const& txn, ViewFlags params, TransactionEngine* engine); , ctx_ (ctx)
TER transact_CreateOffer (STTx const& txn, ViewFlags params, TransactionEngine* engine); , j_ (ctx.journal)
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())
, mHasAuthKey (false) , mHasAuthKey (false)
, mSigMaster (false) , mSigMaster (false)
, m_journal (journal)
{ {
assert(mEngine->view().flags() == params);
} }
void Transactor::calculateFee () void Transactor::calculateFee ()
{ {
mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad( mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad(
calculateBaseFee(), mEngine->view().fees().base, calculateBaseFee(), view().fees().base,
mEngine->view().fees().units, mParams & tapADMIN)); view().fees().units, view().flags() & tapADMIN));
} }
std::uint64_t Transactor::calculateBaseFee () std::uint64_t Transactor::calculateBaseFee ()
{ {
// Returns the fee in fee units // Returns the fee in fee units
return getConfig ().TRANSACTION_FEE_BASE; return ctx_.config.TRANSACTION_FEE_BASE;
} }
TER Transactor::payFee () TER Transactor::payFee ()
@@ -119,9 +61,9 @@ TER Transactor::payFee ()
return temBAD_AMOUNT; return temBAD_AMOUNT;
// Only check fee is sufficient when the ledger is open. // 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 (); saPaid.getText () << "/" << mFeeDue.getText ();
return telINSUF_FEE_P; return telINSUF_FEE_P;
@@ -135,11 +77,11 @@ TER Transactor::payFee ()
if (mSourceBalance < saPaid) if (mSourceBalance < saPaid)
{ {
m_journal.trace << "Insufficient balance:" << j_.trace << "Insufficient balance:" <<
" balance=" << mSourceBalance.getText () << " balance=" << mSourceBalance.getText () <<
" paid=" << saPaid.getText (); " paid=" << saPaid.getText ();
if ((mSourceBalance > zero) && (!(mParams & tapOPEN_LEDGER))) if ((mSourceBalance > zero) && ! view().open())
{ {
// Closed ledger, non-zero balance, less than fee // Closed ledger, non-zero balance, less than fee
mSourceBalance.clear (); mSourceBalance.clear ();
@@ -156,6 +98,8 @@ TER Transactor::payFee ()
mSourceBalance -= saPaid; mSourceBalance -= saPaid;
mTxnAccount->setFieldAmount (sfBalance, mSourceBalance); mTxnAccount->setFieldAmount (sfBalance, mSourceBalance);
// VFALCO Should we call view().destroyCoins() here as well?
return tesSUCCESS; return tesSUCCESS;
} }
@@ -168,16 +112,16 @@ TER Transactor::checkSeq ()
{ {
if (a_seq < t_seq) if (a_seq < t_seq)
{ {
m_journal.trace << j_.trace <<
"applyTransaction: has future sequence number " << "applyTransaction: has future sequence number " <<
"a_seq=" << a_seq << " t_seq=" << t_seq; "a_seq=" << a_seq << " t_seq=" << t_seq;
return terPRE_SEQ; return terPRE_SEQ;
} }
if (mEngine->view().txExists(mTxn.getTransactionID ())) if (view().txExists(mTxn.getTransactionID ()))
return tefALREADY; 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; "a_seq=" << a_seq << " t_seq=" << t_seq;
return tefPAST_SEQ; return tefPAST_SEQ;
} }
@@ -187,7 +131,7 @@ TER Transactor::checkSeq ()
return tefWRONG_PRIOR; return tefWRONG_PRIOR;
if (mTxn.isFieldPresent (sfLastLedgerSequence) && if (mTxn.isFieldPresent (sfLastLedgerSequence) &&
(mEngine->getLedger()->getLedgerSeq() > mTxn.getFieldU32 (sfLastLedgerSequence))) (view().seq() > mTxn.getFieldU32 (sfLastLedgerSequence)))
return tefMAX_LEDGER; return tefMAX_LEDGER;
mTxnAccount->setFieldU32 (sfSequence, t_seq + 1); mTxnAccount->setFieldU32 (sfSequence, t_seq + 1);
@@ -214,7 +158,7 @@ TER Transactor::preCheckAccount ()
if (!mTxnAccountID) if (!mTxnAccountID)
{ {
m_journal.warning << "applyTransaction: bad transaction source id"; j_.warning << "applyTransaction: bad transaction source id";
return temBAD_SRC_ACCOUNT; return temBAD_SRC_ACCOUNT;
} }
return tesSUCCESS; return tesSUCCESS;
@@ -235,17 +179,17 @@ TER Transactor::preCheckSigningKey ()
if (!mTxn.isKnownGood ()) if (!mTxn.isKnownGood ())
{ {
if (mTxn.isKnownBad () || if (mTxn.isKnownBad () ||
(!(mParams & tapNO_CHECK_SIGN) && !mTxn.checkSign( (!(view().flags() & tapNO_CHECK_SIGN) && !mTxn.checkSign(
( (
#if RIPPLE_ENABLE_MULTI_SIGN #if RIPPLE_ENABLE_MULTI_SIGN
true true
#else #else
mEngine->view().flags() & tapENABLE_TESTING view().flags() & tapENABLE_TESTING
#endif #endif
)))) ))))
{ {
mTxn.setBad (); mTxn.setBad ();
m_journal.debug << "apply: Invalid transaction (bad signature)"; j_.debug << "apply: Invalid transaction (bad signature)";
return temINVALID; return temINVALID;
} }
@@ -269,7 +213,7 @@ TER Transactor::apply ()
return terResult; return terResult;
// Find source account // Find source account
mTxnAccount = mEngine->view().peek (keylet::account(mTxnAccountID)); mTxnAccount = view().peek (keylet::account(mTxnAccountID));
calculateFee (); calculateFee ();
@@ -279,7 +223,7 @@ TER Transactor::apply ()
{ {
if (mustHaveValidAccount ()) if (mustHaveValidAccount ())
{ {
m_journal.trace << j_.trace <<
"applyTransaction: delay: source account does not exist " << "applyTransaction: delay: source account does not exist " <<
toBase58(mTxn.getAccountID(sfAccount)); toBase58(mTxn.getAccountID(sfAccount));
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -305,7 +249,7 @@ TER Transactor::apply ()
if (terResult != tesSUCCESS) return (terResult); if (terResult != tesSUCCESS) return (terResult);
if (mTxnAccount) if (mTxnAccount)
mEngine->view().update (mTxnAccount); view().update (mTxnAccount);
return doApply (); return doApply ();
} }
@@ -314,7 +258,7 @@ TER Transactor::checkSign ()
{ {
#if RIPPLE_ENABLE_MULTI_SIGN #if RIPPLE_ENABLE_MULTI_SIGN
#else #else
if(mEngine->view().flags() & tapENABLE_TESTING) if(view().flags() & tapENABLE_TESTING)
#endif #endif
{ {
// If the mSigningPubKey is empty, then we must be multi-signing. // If the mSigningPubKey is empty, then we must be multi-signing.
@@ -347,13 +291,13 @@ TER Transactor::checkSingleSign ()
} }
else if (mHasAuthKey) else if (mHasAuthKey)
{ {
m_journal.trace << j_.trace <<
"applyTransaction: Delay: Not authorized to use account."; "applyTransaction: Delay: Not authorized to use account.";
return tefBAD_AUTH; return tefBAD_AUTH;
} }
else else
{ {
m_journal.trace << j_.trace <<
"applyTransaction: Invalid: Not authorized to use account."; "applyTransaction: Invalid: Not authorized to use account.";
return tefBAD_AUTH_MASTER; return tefBAD_AUTH_MASTER;
} }
@@ -372,15 +316,16 @@ struct GetSignerListResult
}; };
// We need the SignerList for every SigningFor while multi-signing. // We need the SignerList for every SigningFor while multi-signing.
static
GetSignerListResult GetSignerListResult
getSignerList ( getSignerList (AccountID signingForAcctID,
AccountID signingForAcctID, TransactionEngine* engine, beast::Journal journal) BasicView const& view, beast::Journal journal)
{ {
GetSignerListResult ret; GetSignerListResult ret;
auto const k = keylet::signers(signingForAcctID); auto const k = keylet::signers(signingForAcctID);
SLE::pointer accountSignersList = auto const accountSignersList =
engine->view().peek (k); view.read (k);
// If the signer list doesn't exist the account is not multi-signing. // If the signer list doesn't exist the account is not multi-signing.
if (!accountSignersList) if (!accountSignersList)
@@ -414,7 +359,7 @@ CheckSigningAccountsResult
checkSigningAccounts ( checkSigningAccounts (
std::vector<SignerEntries::SignerEntry> signerEntries, std::vector<SignerEntries::SignerEntry> signerEntries,
STArray const& signingAccounts, STArray const& signingAccounts,
TransactionEngine* engine, ApplyContext& ctx,
beast::Journal journal) beast::Journal journal)
{ {
CheckSigningAccountsResult ret; CheckSigningAccountsResult ret;
@@ -489,8 +434,8 @@ checkSigningAccounts (
// In any of these cases we need to know whether the account is in // In any of these cases we need to know whether the account is in
// the ledger. Determine that now. // the ledger. Determine that now.
SLE::pointer signersAccountRoot = auto signersAccountRoot =
engine->view().peek (keylet::account(signingAcctID)); ctx.view().read (keylet::account(signingAcctID));
if (signingAcctIDFromPubKey == signingAcctID) if (signingAcctIDFromPubKey == signingAcctID)
{ {
@@ -553,7 +498,7 @@ TER Transactor::checkMultiSign ()
// Get mTxnAccountID's SignerList and Quorum. // Get mTxnAccountID's SignerList and Quorum.
using namespace TransactorDetail; using namespace TransactorDetail;
GetSignerListResult const outer = GetSignerListResult const outer =
getSignerList (mTxnAccountID, mEngine, m_journal); getSignerList (mTxnAccountID, view(), j_);
if (outer.ter != tesSUCCESS) if (outer.ter != tesSUCCESS)
return outer.ter; return outer.ter;
@@ -587,7 +532,7 @@ TER Transactor::checkMultiSign ()
// from these signers directly effect the quorum. // from these signers directly effect the quorum.
CheckSigningAccountsResult const outerSigningAccountsResult = CheckSigningAccountsResult const outerSigningAccountsResult =
checkSigningAccounts ( checkSigningAccounts (
outer.signerEntries, signingAccounts, mEngine, m_journal); outer.signerEntries, signingAccounts, ctx_, j_);
if (outerSigningAccountsResult.ter != tesSUCCESS) if (outerSigningAccountsResult.ter != tesSUCCESS)
return outerSigningAccountsResult.ter; return outerSigningAccountsResult.ter;
@@ -602,7 +547,7 @@ TER Transactor::checkMultiSign ()
{ {
if (++signerEntriesItr == outer.signerEntries.end ()) if (++signerEntriesItr == outer.signerEntries.end ())
{ {
m_journal.trace << j_.trace <<
"applyTransaction: Invalid SigningFor.Account."; "applyTransaction: Invalid SigningFor.Account.";
return tefBAD_SIGNATURE; return tefBAD_SIGNATURE;
} }
@@ -610,21 +555,21 @@ TER Transactor::checkMultiSign ()
if (signerEntriesItr->account != signingForID) if (signerEntriesItr->account != signingForID)
{ {
// The signingForID is not in the SignerEntries. // The signingForID is not in the SignerEntries.
m_journal.trace << j_.trace <<
"applyTransaction: Invalid SigningFor.Account."; "applyTransaction: Invalid SigningFor.Account.";
return tefBAD_SIGNATURE; return tefBAD_SIGNATURE;
} }
if (signerEntriesItr->weight <= 0) if (signerEntriesItr->weight <= 0)
{ {
// The SigningFor entry needs a weight greater than zero. // The SigningFor entry needs a weight greater than zero.
m_journal.trace << j_.trace <<
"applyTransaction: SigningFor.Account needs weight > 0."; "applyTransaction: SigningFor.Account needs weight > 0.";
return tefBAD_SIGNATURE; return tefBAD_SIGNATURE;
} }
// See if the signingForID has a SignerList. // See if the signingForID has a SignerList.
GetSignerListResult const inner = GetSignerListResult const inner =
getSignerList (signingForID, mEngine, m_journal); getSignerList (signingForID, view(), j_);
if (inner.ter != tesSUCCESS) if (inner.ter != tesSUCCESS)
return inner.ter; return inner.ter;
@@ -632,7 +577,7 @@ TER Transactor::checkMultiSign ()
// Results from these signers indirectly effect the quorum. // Results from these signers indirectly effect the quorum.
CheckSigningAccountsResult const innerSigningAccountsResult = CheckSigningAccountsResult const innerSigningAccountsResult =
checkSigningAccounts ( checkSigningAccounts (
inner.signerEntries, signingAccounts, mEngine, m_journal); inner.signerEntries, signingAccounts, ctx_, j_);
if (innerSigningAccountsResult.ter != tesSUCCESS) if (innerSigningAccountsResult.ter != tesSUCCESS)
return innerSigningAccountsResult.ter; return innerSigningAccountsResult.ter;
@@ -652,7 +597,7 @@ TER Transactor::checkMultiSign ()
// -- January 2015 // -- January 2015
if (innerSigningAccountsResult.weightSum < inner.quorum) if (innerSigningAccountsResult.weightSum < inner.quorum)
{ {
m_journal.trace << j_.trace <<
"applyTransaction: Level-2 SigningFor did not make quorum."; "applyTransaction: Level-2 SigningFor did not make quorum.";
return tefBAD_QUORUM; return tefBAD_QUORUM;
} }
@@ -664,7 +609,7 @@ TER Transactor::checkMultiSign ()
// Cannot perform transaction if quorum is not met. // Cannot perform transaction if quorum is not met.
if (weightSum < outer.quorum) if (weightSum < outer.quorum)
{ {
m_journal.trace << j_.trace <<
"applyTransaction: MultiSignature failed to meet quorum."; "applyTransaction: MultiSignature failed to meet quorum.";
return tefBAD_QUORUM; return tefBAD_QUORUM;
} }
@@ -673,4 +618,173 @@ TER Transactor::checkMultiSign ()
return tesSUCCESS; 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;
}
} }

View File

@@ -20,27 +20,17 @@
#ifndef RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED #ifndef RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
#define 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 { namespace ripple {
class Transactor class Transactor
{ {
public:
static
TER
transact (
STTx const& txn,
ViewFlags params,
TransactionEngine* engine);
TER
apply ();
protected: protected:
STTx const& mTxn; STTx const& mTxn;
TransactionEngine* mEngine; ApplyContext& ctx_;
ViewFlags const mParams; beast::Journal j_;
AccountID mTxnAccountID; AccountID mTxnAccountID;
STAmount mFeeDue; STAmount mFeeDue;
@@ -51,36 +41,53 @@ protected:
bool mSigMaster; bool mSigMaster;
RippleAddress mSigningPubKey; 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 preCheckAccount ();
TER preCheckSigningKey (); TER preCheckSigningKey ();
virtual TER checkSeq ();
virtual TER payFee ();
void calculateFee (); 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) // Returns the fee, not scaled for load (Should be in fee units. FIXME)
virtual std::uint64_t calculateBaseFee (); virtual std::uint64_t calculateBaseFee ();
virtual TER preCheck ();
virtual TER checkSeq ();
virtual TER payFee ();
virtual TER checkSign (); virtual TER checkSign ();
virtual TER doApply () = 0; virtual TER doApply () = 0;
Transactor (
const STTx& txn,
ViewFlags params,
TransactionEngine* engine,
beast::Journal journal = beast::Journal ());
virtual bool mustHaveValidAccount ()
{
return true;
}
private: private:
TER checkSingleSign (); TER checkSingleSign ();
TER checkMultiSign (); TER checkMultiSign ();

View 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

View File

@@ -55,7 +55,7 @@ public:
void testCanceledOffer () void testCanceledOffer ()
{ {
using namespace jtx; using namespace jtx;
Env env = *this; Env env (*this);
auto const gw = Account ("gateway"); auto const gw = Account ("gateway");
auto const USD = gw["USD"]; auto const USD = gw["USD"];

View File

@@ -20,6 +20,7 @@
#include <ripple/app/ledger/LedgerConsensus.h> #include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/LedgerTiming.h> #include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/app/ledger/tests/common_ledger.h> #include <ripple/app/ledger/tests/common_ledger.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/seconds_clock.h> #include <ripple/basics/seconds_clock.h>
#include <ripple/protocol/TxFormats.h> #include <ripple/protocol/TxFormats.h>
#include <ripple/protocol/TxFlags.h> #include <ripple/protocol/TxFlags.h>
@@ -90,12 +91,13 @@ TestLedger::TestLedger (
createGenesisLedger(startAmountDrops, masterAcct); 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. // Apply the transaction to the open ledger.
TransactionEngine engine(openLedger_); auto const r = apply(
auto r = engine.applyTransaction ( *openLedger_, tx, check ? tapNONE : tapNO_CHECK_SIGN,
tx, tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN)); getConfig(), beast::Journal{});
// Close the open ledger to see if the transaction was real committed. // Close the open ledger to see if the transaction was real committed.
// //

View File

@@ -26,6 +26,7 @@
#include <ripple/protocol/TER.h> #include <ripple/protocol/TER.h>
#include <ripple/core/Config.h> #include <ripple/core/Config.h>
#include <ripple/ledger/View.h> #include <ripple/ledger/View.h>
#include <beast/utility/Journal.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <functional> #include <functional>
#include <memory> #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 // Fields for closed ledgers
modification operations. There is no checkpointing // 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. or calculation of metadata.
A raw interace is provided for mutable ledgers.
*/ */
class BasicView class BasicView
{ {
@@ -80,24 +110,44 @@ public:
virtual ~BasicView() = default; 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. */ /** Returns the fees for the base ledger. */
virtual virtual
Fees const& Fees const&
fees() const = 0; 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. /** Determine if a state item exists.
@note This can be more efficient than calling read. @note This can be more efficient than calling read.
@@ -204,6 +254,18 @@ public:
void void
destroyCoins (std::uint64_t feeDrops) = 0; 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. */ /** Returns `true` if a tx exists in the tx map. */
virtual virtual
bool bool
@@ -214,10 +276,11 @@ public:
@param metaData Optional metadata (may be nullptr) @param metaData Optional metadata (may be nullptr)
*/ */
virtual virtual
bool void
txInsert (uint256 const& key, txInsert (uint256 const& key,
std::shared_ptr<Serializer const> const& txn, std::shared_ptr<Serializer const
std::shared_ptr<Serializer const> const& metaData) = 0; > const& txn, std::shared_ptr<
Serializer const> const& metaData) = 0;
// DEBUG ROUTINE // DEBUG ROUTINE
// Return a list of transaction keys in the tx map. // Return a list of transaction keys in the tx map.
@@ -255,11 +318,6 @@ enum ViewFlags
// //
tapENABLE_TESTING = 0x02, 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 // This is not the transaction's last pass
// Transaction can be retried, soft failures allowed // Transaction can be retried, soft failures allowed
tapRETRY = 0x20, tapRETRY = 0x20,
@@ -268,6 +326,27 @@ enum ViewFlags
tapADMIN = 0x400, 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. /** A contextual view into a ledger's state items.
This refinement of BasicView provides an interface where This refinement of BasicView provides an interface where
@@ -422,24 +501,18 @@ public:
{ {
} }
ViewInfo const&
info() const
{
return view_.info();
}
Fees const& Fees const&
fees() const override fees() const override
{ {
return view_.fees(); return view_.fees();
} }
LedgerIndex
seq() const override
{
return view_.seq();
}
std::uint32_t
time() const override
{
return view_.time();
}
bool bool
exists (Keylet const& k) const override exists (Keylet const& k) const override
{ {
@@ -488,20 +561,25 @@ public:
return view_.destroyCoins(feeDrops); return view_.destroyCoins(feeDrops);
} }
std::size_t
txCount() const override
{
return view_.txCount();
}
bool bool
txExists (uint256 const& key) const override txExists (uint256 const& key) const override
{ {
return view_.txExists(key); return view_.txExists(key);
} }
bool void
txInsert (uint256 const& key, txInsert (uint256 const& key,
std::shared_ptr<Serializer const std::shared_ptr<Serializer const
> const& txn, std::shared_ptr< > const& txn, std::shared_ptr<
Serializer const> const& metaData) override Serializer const> const& metaData) override
{ {
return view_.txInsert( view_.txInsert(key, txn, metaData);
key, txn, metaData);
} }
std::vector<uint256> std::vector<uint256>
@@ -528,24 +606,18 @@ public:
{ {
} }
ViewInfo const&
info() const
{
return view_.info();
}
Fees const& Fees const&
fees() const override fees() const override
{ {
return view_.fees(); return view_.fees();
} }
LedgerIndex
seq() const override
{
return view_.seq();
}
std::uint32_t
time() const override
{
return view_.time();
}
bool bool
exists (Keylet const& k) const override exists (Keylet const& k) const override
{ {
@@ -594,20 +666,25 @@ public:
return view_.destroyCoins(feeDrops); return view_.destroyCoins(feeDrops);
} }
std::size_t
txCount() const override
{
return view_.txCount();
}
bool bool
txExists (uint256 const& key) const override txExists (uint256 const& key) const override
{ {
return view_.txExists(key); return view_.txExists(key);
} }
bool void
txInsert (uint256 const& key, txInsert (uint256 const& key,
std::shared_ptr<Serializer const std::shared_ptr<Serializer const
> const& txn, std::shared_ptr< > const& txn, std::shared_ptr<
Serializer const> const& metaData) override Serializer const> const& metaData) override
{ {
return view_.txInsert( view_.txInsert(key, txn, metaData);
key, txn, metaData);
} }
std::vector<uint256> std::vector<uint256>

View File

@@ -1240,7 +1240,7 @@ accountSend (View& view,
{ {
// VFALCO Its laborious to have to mutate the // VFALCO Its laborious to have to mutate the
// TER based on params everywhere // TER based on params everywhere
terResult = (view.flags() & tapOPEN_LEDGER) terResult = view.open()
? telFAILED_PROCESSING ? telFAILED_PROCESSING
: tecFAILED_PROCESSING; : tecFAILED_PROCESSING;
} }
@@ -1497,7 +1497,7 @@ transferXRP (View& view,
// VFALCO Its unfortunate we have to keep // VFALCO Its unfortunate we have to keep
// mutating these TER everywhere // mutating these TER everywhere
// FIXME: this logic should be moved to callers maybe? // FIXME: this logic should be moved to callers maybe?
return (view.flags() & tapOPEN_LEDGER) return view.open()
? telFAILED_PROCESSING ? telFAILED_PROCESSING
: tecFAILED_PROCESSING; : tecFAILED_PROCESSING;
} }

View File

@@ -25,10 +25,11 @@
namespace ripple { namespace ripple {
// See https://ripple.com/wiki/Transaction_errors // 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. // Note: Range is stable. Exact numbers are currently unstable. Use tokens.

View File

@@ -304,7 +304,8 @@ ripplePathFind (RippleLineCache::pointer const& cache,
saMaxAmount.negate(); saMaxAmount.negate();
boost::optional<PaymentView> sandbox; boost::optional<PaymentView> sandbox;
sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER); sandbox.emplace(*lpLedger, tapNONE);
assert(sandbox->open());
auto rc = path::RippleCalc::rippleCalculate( auto rc = path::RippleCalc::rippleCalculate(
*sandbox, *sandbox,
@@ -329,7 +330,8 @@ ripplePathFind (RippleLineCache::pointer const& cache,
<< "Trying with an extra path element"; << "Trying with an extra path element";
spsComputed.push_back(fullLiquidityPath); spsComputed.push_back(fullLiquidityPath);
sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER); sandbox.emplace(*lpLedger, tapNONE);
assert(sandbox->open());
rc = path::RippleCalc::rippleCalculate( rc = path::RippleCalc::rippleCalculate(
*sandbox, *sandbox,
saMaxAmount, // --> Amount to send is unlimited saMaxAmount, // --> Amount to send is unlimited

View File

@@ -65,7 +65,7 @@ Json::Value doTransactionEntry (RPC::Context& context)
else else
{ {
Transaction::pointer tpTrans; Transaction::pointer tpTrans;
TransactionMetaSet::pointer tmTrans; TxMeta::pointer tmTrans;
if (!getTransaction (*lpLedger, uTransID, tpTrans, tmTrans, if (!getTransaction (*lpLedger, uTransID, tpTrans, tmTrans,
getApp().getMasterTransaction())) getApp().getMasterTransaction()))

View File

@@ -83,7 +83,7 @@ Json::Value doTx (RPC::Context& context)
} }
else else
{ {
TransactionMetaSet::pointer txMeta; TxMeta::pointer txMeta;
if (getTransactionMeta (*lgr, txn->getID (), txMeta)) if (getTransactionMeta (*lgr, txn->getID (), txMeta))
{ {

View File

@@ -27,7 +27,7 @@ addPaymentDeliveredAmount (
Json::Value& meta, Json::Value& meta,
RPC::Context& context, RPC::Context& context,
Transaction::pointer transaction, Transaction::pointer transaction,
TransactionMetaSet::pointer transactionMeta) TxMeta::pointer transactionMeta)
{ {
// We only want to add a "delivered_amount" field if the transaction // We only want to add a "delivered_amount" field if the transaction
// succeeded - otherwise nothing could have been delivered. // succeeded - otherwise nothing could have been delivered.

View File

@@ -28,7 +28,7 @@ addPaymentDeliveredAmount (
Json::Value&, Json::Value&,
RPC::Context&, RPC::Context&,
Transaction::pointer, Transaction::pointer,
TransactionMetaSet::pointer); TxMeta::pointer);
} // RPC } // RPC
} // ripple } // ripple

View File

@@ -27,6 +27,7 @@
#include <ripple/test/jtx/tags.h> #include <ripple/test/jtx/tags.h>
#include <ripple/app/ledger/Ledger.h> #include <ripple/app/ledger/Ledger.h>
#include <ripple/core/Config.h>
#include <ripple/json/json_value.h> #include <ripple/json/json_value.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
#include <ripple/protocol/Indexes.h> #include <ripple/protocol/Indexes.h>
@@ -117,6 +118,10 @@ class Env
public: public:
beast::unit_test::suite& test; beast::unit_test::suite& test;
/** Configuration used. */
// VFALCO NOTE Some code still calls getConfig()
Config const config;
/** The master account. */ /** The master account. */
Account const master; Account const master;

View File

@@ -28,8 +28,8 @@
#include <ripple/test/jtx/seq.h> #include <ripple/test/jtx/seq.h>
#include <ripple/test/jtx/sig.h> #include <ripple/test/jtx/sig.h>
#include <ripple/test/jtx/utility.h> #include <ripple/test/jtx/utility.h>
#include <ripple/app/tx/apply.h>
#include <ripple/app/paths/FindPaths.h> #include <ripple/app/paths/FindPaths.h>
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/basics/Slice.h> #include <ripple/basics/Slice.h>
#include <ripple/json/to_string.h> #include <ripple/json/to_string.h>
#include <ripple/protocol/ErrorCodes.h> #include <ripple/protocol/ErrorCodes.h>
@@ -198,11 +198,12 @@ Env::submit (JTx const& jt)
if (stx) if (stx)
{ {
ViewFlags flags = tapNONE; ViewFlags flags = tapNONE;
flags = flags | tapOPEN_LEDGER;
flags = flags | tapENABLE_TESTING; flags = flags | tapENABLE_TESTING;
TransactionEngine txe (ledger); // VFALCO Could wrap the log in a Journal here
std::tie(ter, didApply) = std::tie(ter, didApply) =
txe.applyTransaction(*stx, flags); ripple::apply(
*ledger, *stx, flags, config,
beast::Journal{});
} }
else else
{ {

View File

@@ -39,6 +39,7 @@
#include <ripple/app/ledger/impl/LedgerMaster.cpp> #include <ripple/app/ledger/impl/LedgerMaster.cpp>
#include <ripple/app/ledger/impl/LedgerTiming.cpp> #include <ripple/app/ledger/impl/LedgerTiming.cpp>
#include <ripple/app/ledger/impl/MetaView.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/common_ledger.cpp>
#include <ripple/app/ledger/tests/DeferredCredits.test.cpp> #include <ripple/app/ledger/tests/DeferredCredits.test.cpp>

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h> #include <BeastConfig.h>
#include <ripple/app/tx/impl/apply.cpp>
#include <ripple/app/tx/impl/BookTip.cpp> #include <ripple/app/tx/impl/BookTip.cpp>
#include <ripple/app/tx/impl/CancelOffer.cpp> #include <ripple/app/tx/impl/CancelOffer.cpp>
#include <ripple/app/tx/impl/CancelTicket.cpp> #include <ripple/app/tx/impl/CancelTicket.cpp>
@@ -37,8 +38,7 @@
#include <ripple/app/tx/impl/Taker.cpp> #include <ripple/app/tx/impl/Taker.cpp>
#include <ripple/app/tx/impl/TransactionMaster.cpp> #include <ripple/app/tx/impl/TransactionMaster.cpp>
#include <ripple/app/tx/impl/Transaction.cpp> #include <ripple/app/tx/impl/Transaction.cpp>
#include <ripple/app/tx/impl/TransactionEngine.cpp> #include <ripple/app/tx/impl/ApplyContext.cpp>
#include <ripple/app/tx/impl/TransactionMeta.cpp>
#include <ripple/app/tx/impl/TransactionAcquire.cpp> #include <ripple/app/tx/impl/TransactionAcquire.cpp>
#include <ripple/app/tx/impl/Transactor.cpp> #include <ripple/app/tx/impl/Transactor.cpp>