mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-18 18:15:50 +00:00
Transactor refactor:
* Allocate transactors on the stack instead of the heap. * Remove header files and reduce transactor public interface.
This commit is contained in:
@@ -126,8 +126,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\build\proto\ripple.pb.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BeastConfig.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\Arithmetic.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\asio\abstract_socket.cpp">
|
||||
@@ -304,14 +302,14 @@
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\MurmurHash.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\Sha256.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\sha2\sha2.c">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\beast\beast\crypto\impl\sha2\sha2.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\Sha256.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\UnsignedInteger.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -826,14 +824,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\text\StringPairArray.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\CriticalSection.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\DynamicLibrary.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\Process.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\ScopedLock.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\module\core\thread\DeadlineTimer.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -846,6 +836,14 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\thread\Workers.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\CriticalSection.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\DynamicLibrary.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\Process.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\ScopedLock.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\module\core\time\AtExitHook.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -1188,6 +1186,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\Version.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BeastConfig.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\hyperleveldb\db\builder.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -2386,53 +2386,33 @@
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\AddWallet.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\AddWallet.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CancelOffer.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CancelOffer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Change.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\Change.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOffer.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOffer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOfferBridged.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOfferBridged.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOfferDirect.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOfferDirect.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Payment.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\Payment.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetAccount.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetAccount.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetRegularKey.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetRegularKey.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetTrust.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetTrust.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Transactor.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -3943,57 +3923,6 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\third-party\rapidjson\reader.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\backupable\backupable_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\document_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\json_document.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\put.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\uint64add.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\redis\redis_lists.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_lists.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_exception.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_iterator.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\spatialdb\spatial_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\spatialdb\utils.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\util\arena.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -4167,6 +4096,57 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\util\xxhash.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\backupable\backupable_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\document_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\json_document.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\put.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\uint64add.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\redis\redis_lists.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_lists.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_exception.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_iterator.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\spatialdb\spatial_db.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\spatialdb\utils.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.cc">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\snappy\config\snappy-stubs-public.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\snappy\snappy\snappy-internal.h">
|
||||
|
||||
@@ -666,9 +666,6 @@
|
||||
<ClInclude Include="..\..\build\proto\ripple.pb.h">
|
||||
<Filter>build\proto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BeastConfig.h">
|
||||
<Filter>.</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\Arithmetic.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
@@ -900,15 +897,15 @@
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\MurmurHash.cpp">
|
||||
<Filter>beast\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\Sha256.cpp">
|
||||
<Filter>beast\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\sha2\sha2.c">
|
||||
<Filter>beast\crypto\impl\sha2</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\beast\beast\crypto\impl\sha2\sha2.h">
|
||||
<Filter>beast\crypto\impl\sha2</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\Sha256.cpp">
|
||||
<Filter>beast\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\beast\beast\crypto\impl\UnsignedInteger.cpp">
|
||||
<Filter>beast\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -1554,18 +1551,6 @@
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\text\StringPairArray.h">
|
||||
<Filter>beast\module\core\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\CriticalSection.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\DynamicLibrary.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\Process.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\ScopedLock.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\module\core\thread\DeadlineTimer.cpp">
|
||||
<Filter>beast\module\core\thread</Filter>
|
||||
</ClCompile>
|
||||
@@ -1581,6 +1566,18 @@
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\thread\Workers.h">
|
||||
<Filter>beast\module\core\thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\CriticalSection.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\DynamicLibrary.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\Process.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\beast\beast\module\core\threads\ScopedLock.h">
|
||||
<Filter>beast\module\core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\beast\beast\module\core\time\AtExitHook.cpp">
|
||||
<Filter>beast\module\core\time</Filter>
|
||||
</ClCompile>
|
||||
@@ -2019,6 +2016,9 @@
|
||||
<ClInclude Include="..\..\src\beast\beast\Version.h">
|
||||
<Filter>beast</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BeastConfig.h">
|
||||
<Filter>.</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\hyperleveldb\db\builder.cc">
|
||||
<Filter>hyperleveldb\db</Filter>
|
||||
</ClCompile>
|
||||
@@ -3489,63 +3489,33 @@
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\AddWallet.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\AddWallet.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CancelOffer.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CancelOffer.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Change.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\Change.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOffer.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOffer.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOfferBridged.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOfferBridged.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\CreateOfferDirect.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\CreateOfferDirect.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Payment.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\Payment.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetAccount.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetAccount.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetRegularKey.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetRegularKey.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\SetTrust.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\module\app\transactors\SetTrust.h">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\module\app\transactors\Transactor.cpp">
|
||||
<Filter>ripple\module\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
@@ -5412,66 +5382,6 @@
|
||||
<ClInclude Include="..\..\src\rocksdb2\third-party\rapidjson\reader.h">
|
||||
<Filter>rocksdb2\third-party\rapidjson</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\backupable\backupable_db.cc">
|
||||
<Filter>rocksdb2\utilities\backupable</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\document_db.cc">
|
||||
<Filter>rocksdb2\utilities\document</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\json_document.cc">
|
||||
<Filter>rocksdb2\utilities\document</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.cc">
|
||||
<Filter>rocksdb2\utilities\geodb</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.h">
|
||||
<Filter>rocksdb2\utilities\geodb</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators.h">
|
||||
<Filter>rocksdb2\utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\put.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.h">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.h">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\uint64add.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\redis\redis_lists.cc">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_lists.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_exception.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_iterator.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\spatialdb\spatial_db.cc">
|
||||
<Filter>rocksdb2\utilities\spatialdb</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\spatialdb\utils.h">
|
||||
<Filter>rocksdb2\utilities\spatialdb</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.cc">
|
||||
<Filter>rocksdb2\utilities\ttl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.h">
|
||||
<Filter>rocksdb2\utilities\ttl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\util\arena.cc">
|
||||
<Filter>rocksdb2\util</Filter>
|
||||
</ClCompile>
|
||||
@@ -5676,6 +5586,66 @@
|
||||
<ClInclude Include="..\..\src\rocksdb2\util\xxhash.h">
|
||||
<Filter>rocksdb2\util</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\backupable\backupable_db.cc">
|
||||
<Filter>rocksdb2\utilities\backupable</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\document_db.cc">
|
||||
<Filter>rocksdb2\utilities\document</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\document\json_document.cc">
|
||||
<Filter>rocksdb2\utilities\document</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.cc">
|
||||
<Filter>rocksdb2\utilities\geodb</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\geodb\geodb_impl.h">
|
||||
<Filter>rocksdb2\utilities\geodb</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators.h">
|
||||
<Filter>rocksdb2\utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\put.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend.h">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\merge_operators\string_append\stringappend2.h">
|
||||
<Filter>rocksdb2\utilities\merge_operators\string_append</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\merge_operators\uint64add.cc">
|
||||
<Filter>rocksdb2\utilities\merge_operators</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\redis\redis_lists.cc">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_lists.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_exception.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\redis\redis_list_iterator.h">
|
||||
<Filter>rocksdb2\utilities\redis</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\spatialdb\spatial_db.cc">
|
||||
<Filter>rocksdb2\utilities\spatialdb</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\spatialdb\utils.h">
|
||||
<Filter>rocksdb2\utilities\spatialdb</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.cc">
|
||||
<Filter>rocksdb2\utilities\ttl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\rocksdb2\utilities\ttl\db_ttl_impl.h">
|
||||
<Filter>rocksdb2\utilities\ttl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\snappy\config\snappy-stubs-public.h">
|
||||
<Filter>snappy\config</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -19,84 +19,110 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TER AddWallet::doApply ()
|
||||
class AddWallet
|
||||
: public Transactor
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
public:
|
||||
AddWallet (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("AddWallet"))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
Blob const vucPubKey = mTxn.getFieldVL (sfPublicKey);
|
||||
Blob const vucSignature = mTxn.getFieldVL (sfSignature);
|
||||
|
||||
auto const uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
|
||||
auto const naMasterPubKey =
|
||||
RippleAddress::createAccountPublic (vucPubKey);
|
||||
auto const uDstAccountID = naMasterPubKey.getAccountID ();
|
||||
|
||||
// FIXME: This should be moved to the transaction's signature check logic
|
||||
// and cached.
|
||||
if (!naMasterPubKey.accountPublicVerify (
|
||||
Serializer::getSHA512Half (uAuthKeyID.begin (), uAuthKeyID.size ()),
|
||||
vucSignature, ECDSA::not_strict))
|
||||
TER doApply () override
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Unauthorized: bad signature ";
|
||||
return tefBAD_ADD_AUTH;
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
Blob const vucPubKey = mTxn.getFieldVL (sfPublicKey);
|
||||
Blob const vucSignature = mTxn.getFieldVL (sfSignature);
|
||||
|
||||
auto const uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
|
||||
auto const naMasterPubKey =
|
||||
RippleAddress::createAccountPublic (vucPubKey);
|
||||
auto const uDstAccountID = naMasterPubKey.getAccountID ();
|
||||
|
||||
// FIXME: This should be moved to the transaction's signature check logic
|
||||
// and cached.
|
||||
if (!naMasterPubKey.accountPublicVerify (
|
||||
Serializer::getSHA512Half (uAuthKeyID.begin (), uAuthKeyID.size ()),
|
||||
vucSignature, ECDSA::not_strict))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Unauthorized: bad signature ";
|
||||
return tefBAD_ADD_AUTH;
|
||||
}
|
||||
|
||||
SLE::pointer sleDst (mEngine->entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
|
||||
|
||||
if (sleDst)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"account already created";
|
||||
return tefCREATED;
|
||||
}
|
||||
|
||||
// Direct XRP payment.
|
||||
|
||||
STAmount saDstAmount = mTxn.getFieldAmount (sfAmount);
|
||||
STAmount saPaid = mTxn.getTransactionFee ();
|
||||
STAmount const saSrcBalance = mTxnAccount->getFieldAmount (sfBalance);
|
||||
std::uint32_t const uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
|
||||
std::uint64_t const uReserve = mEngine->getLedger ()->getReserve (uOwnerCount);
|
||||
|
||||
|
||||
// Make sure have enough reserve to send. Allow final spend to use reserve
|
||||
// for fee.
|
||||
// Note: Reserve is not scaled by fee.
|
||||
if (saSrcBalance + saPaid < saDstAmount + uReserve)
|
||||
{
|
||||
// Vote no. However, transaction might succeed, if applied in a
|
||||
// different order.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Insufficient funds: %s / %s (%d)" <<
|
||||
saSrcBalance.getText () << " / " <<
|
||||
(saDstAmount + uReserve).getText () << " with reserve = " <<
|
||||
uReserve;
|
||||
return tecUNFUNDED_ADD;
|
||||
}
|
||||
|
||||
// Deduct initial balance from source account.
|
||||
mTxnAccount->setFieldAmount (sfBalance, saSrcBalance - saDstAmount);
|
||||
|
||||
// Create the account.
|
||||
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT,
|
||||
Ledger::getAccountRootIndex (uDstAccountID));
|
||||
|
||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
sleDst->setFieldAmount (sfBalance, saDstAmount);
|
||||
sleDst->setFieldAccount (sfRegularKey, uAuthKeyID);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
SLE::pointer sleDst (mEngine->entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
|
||||
|
||||
if (sleDst)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"account already created";
|
||||
return tefCREATED;
|
||||
}
|
||||
|
||||
// Direct XRP payment.
|
||||
|
||||
STAmount saDstAmount = mTxn.getFieldAmount (sfAmount);
|
||||
STAmount saPaid = mTxn.getTransactionFee ();
|
||||
STAmount const saSrcBalance = mTxnAccount->getFieldAmount (sfBalance);
|
||||
std::uint32_t const uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
|
||||
std::uint64_t const uReserve = mEngine->getLedger ()->getReserve (uOwnerCount);
|
||||
|
||||
|
||||
// Make sure have enough reserve to send. Allow final spend to use reserve
|
||||
// for fee.
|
||||
// Note: Reserve is not scaled by fee.
|
||||
if (saSrcBalance + saPaid < saDstAmount + uReserve)
|
||||
{
|
||||
// Vote no. However, transaction might succeed, if applied in a
|
||||
// different order.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Insufficient funds: %s / %s (%d)" <<
|
||||
saSrcBalance.getText () << " / " <<
|
||||
(saDstAmount + uReserve).getText () << " with reserve = " <<
|
||||
uReserve;
|
||||
return tecUNFUNDED_ADD;
|
||||
}
|
||||
|
||||
// Deduct initial balance from source account.
|
||||
mTxnAccount->setFieldAmount (sfBalance, saSrcBalance - saDstAmount);
|
||||
|
||||
// Create the account.
|
||||
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT,
|
||||
Ledger::getAccountRootIndex (uDstAccountID));
|
||||
|
||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
sleDst->setFieldAmount (sfBalance, saDstAmount);
|
||||
sleDst->setFieldAccount (sfRegularKey, uAuthKeyID);
|
||||
|
||||
return tesSUCCESS;
|
||||
TER
|
||||
transact_AddWallet (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return AddWallet (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_WALLETADD_H_INCLUDED
|
||||
#define RIPPLE_TX_WALLETADD_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class AddWallet
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
AddWallet (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("AddWallet"))
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply ();
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_AddWallet (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <AddWallet> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,54 +19,80 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
TER CancelOffer::doApply ()
|
||||
class CancelOffer
|
||||
: public Transactor
|
||||
{
|
||||
std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
|
||||
std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
|
||||
|
||||
m_journal.debug <<
|
||||
"uAccountSequenceNext=" << uAccountSequenceNext <<
|
||||
" uOfferSequence=" << uOfferSequence;
|
||||
|
||||
std::uint32_t const uTxFlags (mTxn.getFlags ());
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
public:
|
||||
CancelOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CancelOffer"))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
|
||||
}
|
||||
|
||||
if (!uOfferSequence || uAccountSequenceNext - 1 <= uOfferSequence)
|
||||
TER doApply () override
|
||||
{
|
||||
m_journal.trace <<
|
||||
std::uint32_t const uOfferSequence = mTxn.getFieldU32 (sfOfferSequence);
|
||||
std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
|
||||
|
||||
m_journal.debug <<
|
||||
"uAccountSequenceNext=" << uAccountSequenceNext <<
|
||||
" uOfferSequence=" << uOfferSequence;
|
||||
return temBAD_SEQUENCE;
|
||||
|
||||
std::uint32_t const uTxFlags (mTxn.getFlags ());
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (!uOfferSequence || uAccountSequenceNext - 1 <= uOfferSequence)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"uAccountSequenceNext=" << uAccountSequenceNext <<
|
||||
" uOfferSequence=" << uOfferSequence;
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
uint256 const offerIndex (
|
||||
Ledger::getOfferIndex (mTxnAccountID, uOfferSequence));
|
||||
|
||||
SLE::pointer sleOffer (
|
||||
mEngine->entryCache (ltOFFER, offerIndex));
|
||||
|
||||
if (sleOffer)
|
||||
{
|
||||
m_journal.debug <<
|
||||
"OfferCancel: uOfferSequence=" << uOfferSequence;
|
||||
|
||||
return mEngine->view ().offerDelete (sleOffer);
|
||||
}
|
||||
|
||||
m_journal.warning <<
|
||||
"OfferCancel: offer not found: " <<
|
||||
to_string (mTxnAccountID) <<
|
||||
" : " << uOfferSequence <<
|
||||
" : " << to_string (offerIndex);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
uint256 const offerIndex (
|
||||
Ledger::getOfferIndex (mTxnAccountID, uOfferSequence));
|
||||
|
||||
SLE::pointer sleOffer (
|
||||
mEngine->entryCache (ltOFFER, offerIndex));
|
||||
|
||||
if (sleOffer)
|
||||
{
|
||||
m_journal.debug <<
|
||||
"OfferCancel: uOfferSequence=" << uOfferSequence;
|
||||
|
||||
return mEngine->view ().offerDelete (sleOffer);
|
||||
}
|
||||
|
||||
m_journal.warning <<
|
||||
"OfferCancel: offer not found: " <<
|
||||
to_string (mTxnAccountID) <<
|
||||
" : " << uOfferSequence <<
|
||||
" : " << to_string (offerIndex);
|
||||
|
||||
return tesSUCCESS;
|
||||
TER
|
||||
transact_CancelOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return CancelOffer (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,57 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_OFFERCANCEL_H_INCLUDED
|
||||
#define RIPPLE_TX_OFFERCANCEL_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CancelOffer
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
CancelOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("CancelOffer"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_CancelOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <CancelOffer> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,134 +19,168 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TER Change::doApply ()
|
||||
class Change
|
||||
: public Transactor
|
||||
{
|
||||
if (mTxn.getTxnType () == ttAMENDMENT)
|
||||
return applyAmendment ();
|
||||
|
||||
if (mTxn.getTxnType () == ttFEE)
|
||||
return applyFee ();
|
||||
|
||||
return temUNKNOWN;
|
||||
}
|
||||
|
||||
TER Change::checkSig ()
|
||||
{
|
||||
if (mTxn.getFieldAccount160 (sfAccount).isNonZero ())
|
||||
public:
|
||||
Change (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Change"))
|
||||
{
|
||||
m_journal.warning << "Bad source account";
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
|
||||
if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ())
|
||||
TER doApply () override
|
||||
{
|
||||
m_journal.warning << "Bad signature";
|
||||
return temBAD_SIGNATURE;
|
||||
if (mTxn.getTxnType () == ttAMENDMENT)
|
||||
return applyAmendment ();
|
||||
|
||||
if (mTxn.getTxnType () == ttFEE)
|
||||
return applyFee ();
|
||||
|
||||
return temUNKNOWN;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER Change::checkSeq ()
|
||||
{
|
||||
if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID))
|
||||
TER checkSig () override
|
||||
{
|
||||
m_journal.warning << "Bad sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
if (mTxn.getFieldAccount160 (sfAccount).isNonZero ())
|
||||
{
|
||||
m_journal.warning << "Bad source account";
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
|
||||
if (!mTxn.getSigningPubKey ().empty () || !mTxn.getSignature ().empty ())
|
||||
{
|
||||
m_journal.warning << "Bad signature";
|
||||
return temBAD_SIGNATURE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER Change::payFee ()
|
||||
{
|
||||
if (mTxn.getTransactionFee () != STAmount ())
|
||||
TER checkSeq () override
|
||||
{
|
||||
m_journal.warning << "Non-zero fee";
|
||||
return temBAD_FEE;
|
||||
if ((mTxn.getSequence () != 0) || mTxn.isFieldPresent (sfPreviousTxnID))
|
||||
{
|
||||
m_journal.warning << "Bad sequence";
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER Change::preCheck ()
|
||||
{
|
||||
mTxnAccountID = mTxn.getSourceAccount ().getAccountID ();
|
||||
|
||||
if (mTxnAccountID.isNonZero ())
|
||||
TER payFee () override
|
||||
{
|
||||
m_journal.warning << "Bad source id";
|
||||
if (mTxn.getTransactionFee () != STAmount ())
|
||||
{
|
||||
m_journal.warning << "Non-zero fee";
|
||||
return temBAD_FEE;
|
||||
}
|
||||
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
if (mParams & tapOPEN_LEDGER)
|
||||
TER preCheck () override
|
||||
{
|
||||
m_journal.warning << "Change transaction against open ledger";
|
||||
return temINVALID;
|
||||
mTxnAccountID = mTxn.getSourceAccount ().getAccountID ();
|
||||
|
||||
if (mTxnAccountID.isNonZero ())
|
||||
{
|
||||
m_journal.warning << "Bad source id";
|
||||
|
||||
return temBAD_SRC_ACCOUNT;
|
||||
}
|
||||
|
||||
if (mParams & tapOPEN_LEDGER)
|
||||
{
|
||||
m_journal.warning << "Change transaction against open ledger";
|
||||
return temINVALID;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER Change::applyAmendment ()
|
||||
{
|
||||
uint256 amendment (mTxn.getFieldH256 (sfAmendment));
|
||||
|
||||
SLE::pointer amendmentObject (mEngine->entryCache (
|
||||
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex ()));
|
||||
|
||||
if (!amendmentObject)
|
||||
private:
|
||||
TER applyAmendment ()
|
||||
{
|
||||
amendmentObject = mEngine->entryCreate(
|
||||
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex());
|
||||
uint256 amendment (mTxn.getFieldH256 (sfAmendment));
|
||||
|
||||
SLE::pointer amendmentObject (mEngine->entryCache (
|
||||
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex ()));
|
||||
|
||||
if (!amendmentObject)
|
||||
{
|
||||
amendmentObject = mEngine->entryCreate(
|
||||
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex());
|
||||
}
|
||||
|
||||
STVector256 amendments (amendmentObject->getFieldV256 (sfAmendments));
|
||||
|
||||
if (amendments.hasValue (amendment))
|
||||
return tefALREADY;
|
||||
|
||||
amendments.addValue (amendment);
|
||||
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
||||
mEngine->entryModify (amendmentObject);
|
||||
|
||||
getApp().getAmendmentTable ().enable (amendment);
|
||||
|
||||
if (!getApp().getAmendmentTable ().isSupported (amendment))
|
||||
getApp().getOPs ().setAmendmentBlocked ();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
STVector256 amendments (amendmentObject->getFieldV256 (sfAmendments));
|
||||
TER applyFee ()
|
||||
{
|
||||
|
||||
if (amendments.hasValue (amendment))
|
||||
return tefALREADY;
|
||||
|
||||
amendments.addValue (amendment);
|
||||
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
||||
mEngine->entryModify (amendmentObject);
|
||||
|
||||
getApp().getAmendmentTable ().enable (amendment);
|
||||
|
||||
if (!getApp().getAmendmentTable ().isSupported (amendment))
|
||||
getApp().getOPs ().setAmendmentBlocked ();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER Change::applyFee ()
|
||||
{
|
||||
|
||||
SLE::pointer feeObject = mEngine->entryCache (
|
||||
ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
|
||||
|
||||
if (!feeObject)
|
||||
feeObject = mEngine->entryCreate (
|
||||
SLE::pointer feeObject = mEngine->entryCache (
|
||||
ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
|
||||
|
||||
m_journal.trace <<
|
||||
"Previous fee object: " << feeObject->getJson (0);
|
||||
if (!feeObject)
|
||||
feeObject = mEngine->entryCreate (
|
||||
ltFEE_SETTINGS, Ledger::getLedgerFeeIndex ());
|
||||
|
||||
feeObject->setFieldU64 (
|
||||
sfBaseFee, mTxn.getFieldU64 (sfBaseFee));
|
||||
feeObject->setFieldU32 (
|
||||
sfReferenceFeeUnits, mTxn.getFieldU32 (sfReferenceFeeUnits));
|
||||
feeObject->setFieldU32 (
|
||||
sfReserveBase, mTxn.getFieldU32 (sfReserveBase));
|
||||
feeObject->setFieldU32 (
|
||||
sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
|
||||
m_journal.trace <<
|
||||
"Previous fee object: " << feeObject->getJson (0);
|
||||
|
||||
mEngine->entryModify (feeObject);
|
||||
feeObject->setFieldU64 (
|
||||
sfBaseFee, mTxn.getFieldU64 (sfBaseFee));
|
||||
feeObject->setFieldU32 (
|
||||
sfReferenceFeeUnits, mTxn.getFieldU32 (sfReferenceFeeUnits));
|
||||
feeObject->setFieldU32 (
|
||||
sfReserveBase, mTxn.getFieldU32 (sfReserveBase));
|
||||
feeObject->setFieldU32 (
|
||||
sfReserveIncrement, mTxn.getFieldU32 (sfReserveIncrement));
|
||||
|
||||
m_journal.trace <<
|
||||
"New fee object: " << feeObject->getJson (0);
|
||||
m_journal.warning << "Fees have been changed";
|
||||
return tesSUCCESS;
|
||||
mEngine->entryModify (feeObject);
|
||||
|
||||
m_journal.trace <<
|
||||
"New fee object: " << feeObject->getJson (0);
|
||||
m_journal.warning << "Fees have been changed";
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// VFALCO TODO Can this be removed?
|
||||
bool mustHaveValidAccount () override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TER
|
||||
transact_Change (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return Change (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,71 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_CHANGE_H_INCLUDED
|
||||
#define RIPPLE_TX_CHANGE_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
class Change
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
Change (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Change"))
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply () override;
|
||||
TER checkSig () 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;
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_Change (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <Change> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,67 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_OFFERCREATE_H_INCLUDED
|
||||
#define RIPPLE_TX_OFFERCREATE_H_INCLUDED
|
||||
|
||||
#include <ripple/module/app/book/Amounts.h>
|
||||
#include <ripple/module/app/book/Types.h>
|
||||
|
||||
#include <beast/cxx14/memory.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateOffer
|
||||
: public Transactor
|
||||
{
|
||||
protected:
|
||||
/** Determine if we are authorized to hold the asset we want to get */
|
||||
TER checkAcceptAsset(IssueRef asset) const;
|
||||
|
||||
/** Fill offer as much as possible by consuming offers already on the books.
|
||||
We adjusts account balances and charges fees on top to taker.
|
||||
|
||||
@param taker_amount.in How much the taker offers
|
||||
@param taker_amount.out How much the taker wants
|
||||
|
||||
@return result.first crossing operation success/failure indicator.
|
||||
result.second amount of offer left unfilled - only meaningful
|
||||
if result.first is tesSUCCESS.
|
||||
*/
|
||||
virtual std::pair<TER, core::Amounts> crossOffers (
|
||||
core::LedgerView& view,
|
||||
core::Amounts const& taker_amount) = 0;
|
||||
|
||||
public:
|
||||
CreateOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine);
|
||||
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
std::unique_ptr <Transactor> make_CreateOffer (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace ripple {
|
||||
|
||||
std::pair<TER, core::Amounts>
|
||||
CreateOfferBridged::crossOffers (
|
||||
CreateOffer::crossOffersBridged (
|
||||
core::LedgerView& view,
|
||||
core::Amounts const& taker_amount)
|
||||
{
|
||||
|
||||
@@ -1,51 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_BRIDGE_OFFERCREATE_H_INCLUDED
|
||||
#define RIPPLE_TX_BRIDGE_OFFERCREATE_H_INCLUDED
|
||||
|
||||
#include <ripple/module/app/book/Amounts.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateOfferBridged
|
||||
: public CreateOffer
|
||||
{
|
||||
public:
|
||||
CreateOfferBridged (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: CreateOffer (
|
||||
txn,
|
||||
params,
|
||||
engine)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<TER, core::Amounts> crossOffers (
|
||||
core::LedgerView& view,
|
||||
core::Amounts const& taker_amount) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,19 +23,8 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Fill offer as much as possible by consuming offers already on the books.
|
||||
We adjusts account balances and charges fees on top to taker.
|
||||
|
||||
@param taker_amount.in How much the taker offers
|
||||
@param taker_amount.out How much the taker wants
|
||||
@param taker_flow.in What the taker actually paid, not including fees.
|
||||
@param taker_flow.out What the taker actually got, not including fees.
|
||||
|
||||
@return tesSUCCESS, terNO_ACCOUNT, telFAILED_PROCESSING, or
|
||||
tecFAILED_PROCESSING
|
||||
*/
|
||||
std::pair<TER, core::Amounts>
|
||||
CreateOfferDirect::crossOffers (
|
||||
CreateOffer::crossOffersDirect (
|
||||
core::LedgerView& view,
|
||||
core::Amounts const& taker_amount)
|
||||
{
|
||||
|
||||
@@ -1,51 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_DIRECT_OFFERCREATE_H_INCLUDED
|
||||
#define RIPPLE_TX_DIRECT_OFFERCREATE_H_INCLUDED
|
||||
|
||||
#include <ripple/module/app/book/Amounts.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CreateOfferDirect
|
||||
: public CreateOffer
|
||||
{
|
||||
public:
|
||||
CreateOfferDirect (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: CreateOffer (
|
||||
txn,
|
||||
params,
|
||||
engine)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<TER, core::Amounts> crossOffers (
|
||||
core::LedgerView& view,
|
||||
core::Amounts const& taker_amount) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,329 +21,362 @@ namespace ripple {
|
||||
|
||||
// See https://ripple.com/wiki/Transaction_Format#Payment_.280.29
|
||||
|
||||
TER Payment::doApply ()
|
||||
class Payment
|
||||
: public Transactor
|
||||
{
|
||||
// Ripple if source or destination is non-native or if there are paths.
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
|
||||
bool const limitQuality = uTxFlags & tfLimitQuality;
|
||||
bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect);
|
||||
bool const bPaths = mTxn.isFieldPresent (sfPaths);
|
||||
bool const bMax = mTxn.isFieldPresent (sfSendMax);
|
||||
Account const uDstAccountID (mTxn.getFieldAccount160 (sfDestination));
|
||||
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
|
||||
STAmount maxSourceAmount;
|
||||
if (bMax)
|
||||
maxSourceAmount = mTxn.getFieldAmount (sfSendMax);
|
||||
else if (saDstAmount.isNative ())
|
||||
maxSourceAmount = saDstAmount;
|
||||
else
|
||||
maxSourceAmount = STAmount (
|
||||
{saDstAmount.getCurrency (), mTxnAccountID},
|
||||
saDstAmount.getMantissa (), saDstAmount.getExponent (),
|
||||
saDstAmount < zero);
|
||||
auto const& uSrcCurrency = maxSourceAmount.getCurrency ();
|
||||
auto const& uDstCurrency = saDstAmount.getCurrency ();
|
||||
/* The largest number of paths we allow */
|
||||
static std::size_t const MaxPathSize = 6;
|
||||
|
||||
// isZero() is XRP. FIX!
|
||||
bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
|
||||
/* The longest path we allow */
|
||||
static std::size_t const MaxPathLength = 8;
|
||||
|
||||
m_journal.trace <<
|
||||
"maxSourceAmount=" << maxSourceAmount.getFullText () <<
|
||||
" saDstAmount=" << saDstAmount.getFullText ();
|
||||
|
||||
if (!saDstAmount.isLegalNet () || !maxSourceAmount.isLegalNet ())
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
if (uTxFlags & tfPaymentMask)
|
||||
public:
|
||||
Payment (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Payment"))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
else if (!uDstAccountID)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Payment destination account not specified.";
|
||||
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
else if (bMax && maxSourceAmount <= zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: bad max amount: " << maxSourceAmount.getFullText ();
|
||||
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (saDstAmount <= zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
|
||||
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Bad currency.";
|
||||
|
||||
return temBAD_CURRENCY;
|
||||
}
|
||||
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
|
||||
{
|
||||
// You're signing yourself a payment.
|
||||
// If bPaths is true, you might be trying some arbitrage.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Redundant transaction:" <<
|
||||
" src=" << to_string (mTxnAccountID) <<
|
||||
" dst=" << to_string (uDstAccountID) <<
|
||||
" src_cur=" << to_string (uSrcCurrency) <<
|
||||
" dst_cur=" << to_string (uDstCurrency);
|
||||
|
||||
return temREDUNDANT;
|
||||
}
|
||||
else if (bMax && maxSourceAmount == saDstAmount &&
|
||||
maxSourceAmount.getCurrency () == saDstAmount.getCurrency ())
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Redundant SendMax.";
|
||||
|
||||
return temREDUNDANT_SEND_MAX;
|
||||
}
|
||||
else if (bXRPDirect && bMax)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: SendMax specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_MAX;
|
||||
}
|
||||
else if (bXRPDirect && bPaths)
|
||||
{
|
||||
// XRP is sent without paths.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Paths specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_PATHS;
|
||||
}
|
||||
else if (bXRPDirect && partialPaymentAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Partial payment specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_PARTIAL;
|
||||
}
|
||||
else if (bXRPDirect && limitQuality)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Limit quality specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_LIMIT;
|
||||
}
|
||||
else if (bXRPDirect && !defaultPathsAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: No ripple direct specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_NO_DIRECT;
|
||||
}
|
||||
|
||||
//
|
||||
// Open a ledger for editing.
|
||||
auto const index = Ledger::getAccountRootIndex (uDstAccountID);
|
||||
SLE::pointer sleDst (mEngine->entryCache (ltACCOUNT_ROOT, index));
|
||||
|
||||
if (!sleDst)
|
||||
TER doApply () override
|
||||
{
|
||||
// Destination account does not exist.
|
||||
if (!saDstAmount.isNative ())
|
||||
// Ripple if source or destination is non-native or if there are paths.
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
|
||||
bool const limitQuality = uTxFlags & tfLimitQuality;
|
||||
bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect);
|
||||
bool const bPaths = mTxn.isFieldPresent (sfPaths);
|
||||
bool const bMax = mTxn.isFieldPresent (sfSendMax);
|
||||
Account const uDstAccountID (mTxn.getFieldAccount160 (sfDestination));
|
||||
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
|
||||
STAmount maxSourceAmount;
|
||||
if (bMax)
|
||||
maxSourceAmount = mTxn.getFieldAmount (sfSendMax);
|
||||
else if (saDstAmount.isNative ())
|
||||
maxSourceAmount = saDstAmount;
|
||||
else
|
||||
maxSourceAmount = STAmount (
|
||||
{saDstAmount.getCurrency (), mTxnAccountID},
|
||||
saDstAmount.getMantissa (), saDstAmount.getExponent (),
|
||||
saDstAmount < zero);
|
||||
auto const& uSrcCurrency = maxSourceAmount.getCurrency ();
|
||||
auto const& uDstCurrency = saDstAmount.getCurrency ();
|
||||
|
||||
// isZero() is XRP. FIX!
|
||||
bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
|
||||
|
||||
m_journal.trace <<
|
||||
"maxSourceAmount=" << maxSourceAmount.getFullText () <<
|
||||
" saDstAmount=" << saDstAmount.getFullText ();
|
||||
|
||||
if (!saDstAmount.isLegalNet () || !maxSourceAmount.isLegalNet ())
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
if (uTxFlags & tfPaymentMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return tecNO_DST;
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
else if (mParams & tapOPEN_LEDGER && partialPaymentAllowed)
|
||||
{
|
||||
// You cannot fund an account with a partial payment.
|
||||
// Make retry work smaller, by rejecting this.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Partial payment not allowed to create account.";
|
||||
|
||||
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return telNO_DST_PARTIAL;
|
||||
}
|
||||
else if (saDstAmount.getNValue () < mEngine->getLedger ()->getReserve (0))
|
||||
{
|
||||
// getReserve() is the minimum amount that an account can have.
|
||||
// Reserve is not scaled by load.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist. " <<
|
||||
"Insufficent payment to create account.";
|
||||
|
||||
// TODO: dedupe
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return tecNO_DST_INSUF_XRP;
|
||||
}
|
||||
|
||||
// Create the account.
|
||||
auto const newIndex = Ledger::getAccountRootIndex (uDstAccountID);
|
||||
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT, newIndex);
|
||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
}
|
||||
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
||||
!mTxn.isFieldPresent (sfDestinationTag))
|
||||
{
|
||||
// The tag is basically account-specific information we don't
|
||||
// understand, but we can require someone to fill it in.
|
||||
|
||||
// We didn't make this test for a newly-formed account because there's
|
||||
// no way for this field to be set.
|
||||
m_journal.trace << "Malformed transaction: DestinationTag required.";
|
||||
|
||||
return tefDST_TAG_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tell the engine that we are intending to change the the destination
|
||||
// account. The source account gets always charged a fee so it's always
|
||||
// marked as modified.
|
||||
mEngine->entryModify (sleDst);
|
||||
}
|
||||
|
||||
TER terResult;
|
||||
|
||||
bool const bRipple = bPaths || bMax || !saDstAmount.isNative ();
|
||||
// XXX Should bMax be sufficient to imply ripple?
|
||||
|
||||
if (bRipple)
|
||||
{
|
||||
// Ripple payment with at least one intermediate step and uses
|
||||
// transitive balances.
|
||||
|
||||
// Copy paths into an editable class.
|
||||
STPathSet spsPaths = mTxn.getFieldPathSet (sfPaths);
|
||||
|
||||
try
|
||||
{
|
||||
path::RippleCalc::Input rcInput;
|
||||
rcInput.partialPaymentAllowed = partialPaymentAllowed;
|
||||
rcInput.defaultPathsAllowed = defaultPathsAllowed;
|
||||
rcInput.limitQuality = limitQuality;
|
||||
rcInput.deleteUnfundedOffers = true;
|
||||
rcInput.isLedgerOpen = static_cast<bool>(mParams & tapOPEN_LEDGER);
|
||||
|
||||
bool pathTooBig = spsPaths.size () > MaxPathSize;
|
||||
|
||||
for (auto const& path : spsPaths)
|
||||
if (path.size () > MaxPathLength)
|
||||
pathTooBig = true;
|
||||
|
||||
if (rcInput.isLedgerOpen && pathTooBig)
|
||||
{
|
||||
terResult = telBAD_PATH_COUNT; // Too many paths for proposed ledger.
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rc = path::RippleCalc::rippleCalculate (
|
||||
mEngine->view (),
|
||||
maxSourceAmount,
|
||||
saDstAmount,
|
||||
uDstAccountID,
|
||||
mTxnAccountID,
|
||||
spsPaths,
|
||||
&rcInput);
|
||||
|
||||
// TODO: is this right? If the amount is the correct amount, was
|
||||
// the delivered amount previously set?
|
||||
if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount)
|
||||
mEngine->view ().setDeliveredAmount (rc.actualAmountOut);
|
||||
|
||||
terResult = rc.result ();
|
||||
}
|
||||
|
||||
// TODO(tom): what's going on here?
|
||||
if (isTerRetry (terResult))
|
||||
terResult = tecPATH_DRY;
|
||||
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
else if (!uDstAccountID)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Caught throw: " << e.what ();
|
||||
"Malformed transaction: Payment destination account not specified.";
|
||||
|
||||
terResult = tefEXCEPTION;
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct XRP payment.
|
||||
else if (bMax && maxSourceAmount <= zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: bad max amount: " << maxSourceAmount.getFullText ();
|
||||
|
||||
// uOwnerCount is the number of entries in this legder for this account
|
||||
// that require a reserve.
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (saDstAmount <= zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
|
||||
|
||||
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Bad currency.";
|
||||
|
||||
// This is the total reserve in drops.
|
||||
// TODO(tom): there should be a class for this.
|
||||
std::uint64_t const uReserve (mEngine->getLedger ()->getReserve (uOwnerCount));
|
||||
return temBAD_CURRENCY;
|
||||
}
|
||||
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
|
||||
{
|
||||
// You're signing yourself a payment.
|
||||
// If bPaths is true, you might be trying some arbitrage.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Redundant transaction:" <<
|
||||
" src=" << to_string (mTxnAccountID) <<
|
||||
" dst=" << to_string (uDstAccountID) <<
|
||||
" src_cur=" << to_string (uSrcCurrency) <<
|
||||
" dst_cur=" << to_string (uDstCurrency);
|
||||
|
||||
return temREDUNDANT;
|
||||
}
|
||||
else if (bMax && maxSourceAmount == saDstAmount &&
|
||||
maxSourceAmount.getCurrency () == saDstAmount.getCurrency ())
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Redundant SendMax.";
|
||||
|
||||
return temREDUNDANT_SEND_MAX;
|
||||
}
|
||||
else if (bXRPDirect && bMax)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: SendMax specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_MAX;
|
||||
}
|
||||
else if (bXRPDirect && bPaths)
|
||||
{
|
||||
// XRP is sent without paths.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Paths specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_PATHS;
|
||||
}
|
||||
else if (bXRPDirect && partialPaymentAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Partial payment specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_PARTIAL;
|
||||
}
|
||||
else if (bXRPDirect && limitQuality)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Limit quality specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_LIMIT;
|
||||
}
|
||||
else if (bXRPDirect && !defaultPathsAllowed)
|
||||
{
|
||||
// Consistent but redundant transaction.
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: No ripple direct specified for XRP to XRP.";
|
||||
|
||||
return temBAD_SEND_XRP_NO_DIRECT;
|
||||
}
|
||||
|
||||
// mPriorBalance is the balance on the sending account BEFORE the fees were charged.
|
||||
//
|
||||
// Make sure have enough reserve to send. Allow final spend to use
|
||||
// reserve for fee.
|
||||
auto const mmm = std::max(uReserve, mTxn.getTransactionFee ().getNValue ());
|
||||
if (mPriorBalance < saDstAmount + mmm)
|
||||
{
|
||||
// Vote no.
|
||||
// However, transaction might succeed, if applied in a different order.
|
||||
m_journal.trace << "Delay transaction: Insufficient funds: " <<
|
||||
" " << mPriorBalance.getText () <<
|
||||
" / " << (saDstAmount + uReserve).getText () <<
|
||||
" (" << uReserve << ")";
|
||||
// Open a ledger for editing.
|
||||
auto const index = Ledger::getAccountRootIndex (uDstAccountID);
|
||||
SLE::pointer sleDst (mEngine->entryCache (ltACCOUNT_ROOT, index));
|
||||
|
||||
terResult = tecUNFUNDED_PAYMENT;
|
||||
if (!sleDst)
|
||||
{
|
||||
// Destination account does not exist.
|
||||
if (!saDstAmount.isNative ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return tecNO_DST;
|
||||
}
|
||||
else if (mParams & tapOPEN_LEDGER && partialPaymentAllowed)
|
||||
{
|
||||
// You cannot fund an account with a partial payment.
|
||||
// Make retry work smaller, by rejecting this.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Partial payment not allowed to create account.";
|
||||
|
||||
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return telNO_DST_PARTIAL;
|
||||
}
|
||||
else if (saDstAmount.getNValue () < mEngine->getLedger ()->getReserve (0))
|
||||
{
|
||||
// getReserve() is the minimum amount that an account can have.
|
||||
// Reserve is not scaled by load.
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist. " <<
|
||||
"Insufficent payment to create account.";
|
||||
|
||||
// TODO: dedupe
|
||||
// Another transaction could create the account and then this
|
||||
// transaction would succeed.
|
||||
return tecNO_DST_INSUF_XRP;
|
||||
}
|
||||
|
||||
// Create the account.
|
||||
auto const newIndex = Ledger::getAccountRootIndex (uDstAccountID);
|
||||
sleDst = mEngine->entryCreate (ltACCOUNT_ROOT, newIndex);
|
||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
}
|
||||
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
||||
!mTxn.isFieldPresent (sfDestinationTag))
|
||||
{
|
||||
// The tag is basically account-specific information we don't
|
||||
// understand, but we can require someone to fill it in.
|
||||
|
||||
// We didn't make this test for a newly-formed account because there's
|
||||
// no way for this field to be set.
|
||||
m_journal.trace << "Malformed transaction: DestinationTag required.";
|
||||
|
||||
return tefDST_TAG_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The source account does have enough money, so do the arithmetic
|
||||
// for the transfer and make the ledger change.
|
||||
mTxnAccount->setFieldAmount (sfBalance, mSourceBalance - saDstAmount);
|
||||
sleDst->setFieldAmount (sfBalance, sleDst->getFieldAmount (sfBalance) + saDstAmount);
|
||||
|
||||
// Re-arm the password change fee if we can and need to.
|
||||
if ((sleDst->getFlags () & lsfPasswordSpent))
|
||||
sleDst->clearFlag (lsfPasswordSpent);
|
||||
|
||||
terResult = tesSUCCESS;
|
||||
// Tell the engine that we are intending to change the the destination
|
||||
// account. The source account gets always charged a fee so it's always
|
||||
// marked as modified.
|
||||
mEngine->entryModify (sleDst);
|
||||
}
|
||||
}
|
||||
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
TER terResult;
|
||||
|
||||
if (transResultInfo (terResult, strToken, strHuman))
|
||||
{
|
||||
m_journal.trace <<
|
||||
strToken << ": " << strHuman;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (false);
|
||||
}
|
||||
bool const bRipple = bPaths || bMax || !saDstAmount.isNative ();
|
||||
// XXX Should bMax be sufficient to imply ripple?
|
||||
|
||||
return terResult;
|
||||
if (bRipple)
|
||||
{
|
||||
// Ripple payment with at least one intermediate step and uses
|
||||
// transitive balances.
|
||||
|
||||
// Copy paths into an editable class.
|
||||
STPathSet spsPaths = mTxn.getFieldPathSet (sfPaths);
|
||||
|
||||
try
|
||||
{
|
||||
path::RippleCalc::Input rcInput;
|
||||
rcInput.partialPaymentAllowed = partialPaymentAllowed;
|
||||
rcInput.defaultPathsAllowed = defaultPathsAllowed;
|
||||
rcInput.limitQuality = limitQuality;
|
||||
rcInput.deleteUnfundedOffers = true;
|
||||
rcInput.isLedgerOpen = static_cast<bool>(mParams & tapOPEN_LEDGER);
|
||||
|
||||
bool pathTooBig = spsPaths.size () > MaxPathSize;
|
||||
|
||||
for (auto const& path : spsPaths)
|
||||
if (path.size () > MaxPathLength)
|
||||
pathTooBig = true;
|
||||
|
||||
if (rcInput.isLedgerOpen && pathTooBig)
|
||||
{
|
||||
terResult = telBAD_PATH_COUNT; // Too many paths for proposed ledger.
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rc = path::RippleCalc::rippleCalculate (
|
||||
mEngine->view (),
|
||||
maxSourceAmount,
|
||||
saDstAmount,
|
||||
uDstAccountID,
|
||||
mTxnAccountID,
|
||||
spsPaths,
|
||||
&rcInput);
|
||||
|
||||
// TODO: is this right? If the amount is the correct amount, was
|
||||
// the delivered amount previously set?
|
||||
if (rc.result () == tesSUCCESS && rc.actualAmountOut != saDstAmount)
|
||||
mEngine->view ().setDeliveredAmount (rc.actualAmountOut);
|
||||
|
||||
terResult = rc.result ();
|
||||
}
|
||||
|
||||
// TODO(tom): what's going on here?
|
||||
if (isTerRetry (terResult))
|
||||
terResult = tecPATH_DRY;
|
||||
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Caught throw: " << e.what ();
|
||||
|
||||
terResult = tefEXCEPTION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct XRP payment.
|
||||
|
||||
// uOwnerCount is the number of entries in this legder for this account
|
||||
// that require a reserve.
|
||||
|
||||
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
|
||||
|
||||
// This is the total reserve in drops.
|
||||
// TODO(tom): there should be a class for this.
|
||||
std::uint64_t const uReserve (mEngine->getLedger ()->getReserve (uOwnerCount));
|
||||
|
||||
// mPriorBalance is the balance on the sending account BEFORE the fees were charged.
|
||||
//
|
||||
// Make sure have enough reserve to send. Allow final spend to use
|
||||
// reserve for fee.
|
||||
auto const mmm = std::max(uReserve, mTxn.getTransactionFee ().getNValue ());
|
||||
if (mPriorBalance < saDstAmount + mmm)
|
||||
{
|
||||
// Vote no.
|
||||
// However, transaction might succeed, if applied in a different order.
|
||||
m_journal.trace << "Delay transaction: Insufficient funds: " <<
|
||||
" " << mPriorBalance.getText () <<
|
||||
" / " << (saDstAmount + uReserve).getText () <<
|
||||
" (" << uReserve << ")";
|
||||
|
||||
terResult = tecUNFUNDED_PAYMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The source account does have enough money, so do the arithmetic
|
||||
// for the transfer and make the ledger change.
|
||||
mTxnAccount->setFieldAmount (sfBalance, mSourceBalance - saDstAmount);
|
||||
sleDst->setFieldAmount (sfBalance, sleDst->getFieldAmount (sfBalance) + saDstAmount);
|
||||
|
||||
// Re-arm the password change fee if we can and need to.
|
||||
if ((sleDst->getFlags () & lsfPasswordSpent))
|
||||
sleDst->clearFlag (lsfPasswordSpent);
|
||||
|
||||
terResult = tesSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
if (transResultInfo (terResult, strToken, strHuman))
|
||||
{
|
||||
m_journal.trace <<
|
||||
strToken << ": " << strHuman;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (false);
|
||||
}
|
||||
|
||||
return terResult;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_Payment (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return Payment(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -1,63 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_PAYMENT_H_INCLUDED
|
||||
#define RIPPLE_TX_PAYMENT_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
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:
|
||||
Payment (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("Payment"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER doApply ();
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_Payment (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <Payment> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,298 +19,325 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TER SetAccount::doApply ()
|
||||
class SetAccount
|
||||
: public Transactor
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
|
||||
std::uint32_t uFlagsOut = uFlagsIn;
|
||||
|
||||
std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag);
|
||||
std::uint32_t const uClearFlag = mTxn.getFieldU32 (sfClearFlag);
|
||||
|
||||
if ((uSetFlag != 0) && (uSetFlag == uClearFlag))
|
||||
public:
|
||||
SetAccount (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetAccount"))
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Set and clear same flag";
|
||||
return temINVALID_FLAG;
|
||||
|
||||
}
|
||||
|
||||
// legacy AccountSet flags
|
||||
bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
|
||||
bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
|
||||
bool bSetRequireAuth = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
|
||||
bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
|
||||
bool bSetDisallowXRP = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
|
||||
bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);
|
||||
|
||||
if (uTxFlags & tfAccountSetMask)
|
||||
TER doApply () override
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
//
|
||||
// RequireAuth
|
||||
//
|
||||
std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
|
||||
std::uint32_t uFlagsOut = uFlagsIn;
|
||||
|
||||
if (bSetRequireAuth && bClearRequireAuth)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag);
|
||||
std::uint32_t const uClearFlag = mTxn.getFieldU32 (sfClearFlag);
|
||||
|
||||
if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
if (!mEngine->view().dirIsEmpty (Ledger::getOwnerDirIndex (mTxnAccountID)))
|
||||
if ((uSetFlag != 0) && (uSetFlag == uClearFlag))
|
||||
{
|
||||
m_journal.trace << "Retry: Owner directory not empty.";
|
||||
|
||||
return (mParams & tapRETRY) ? terOWNERS : tecOWNERS;
|
||||
m_journal.trace << "Malformed transaction: Set and clear same flag";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
m_journal.trace << "Set RequireAuth.";
|
||||
uFlagsOut |= lsfRequireAuth;
|
||||
}
|
||||
// legacy AccountSet flags
|
||||
bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
|
||||
bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
|
||||
bool bSetRequireAuth = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
|
||||
bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
|
||||
bool bSetDisallowXRP = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
|
||||
bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);
|
||||
|
||||
if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
m_journal.trace << "Clear RequireAuth.";
|
||||
uFlagsOut &= ~lsfRequireAuth;
|
||||
}
|
||||
|
||||
//
|
||||
// RequireDestTag
|
||||
//
|
||||
|
||||
if (bSetRequireDest && bClearRequireDest)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Set lsfRequireDestTag.";
|
||||
uFlagsOut |= lsfRequireDestTag;
|
||||
}
|
||||
|
||||
if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Clear lsfRequireDestTag.";
|
||||
uFlagsOut &= ~lsfRequireDestTag;
|
||||
}
|
||||
|
||||
//
|
||||
// DisallowXRP
|
||||
//
|
||||
|
||||
if (bSetDisallowXRP && bClearDisallowXRP)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Set lsfDisallowXRP.";
|
||||
uFlagsOut |= lsfDisallowXRP;
|
||||
}
|
||||
|
||||
if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisallowXRP.";
|
||||
uFlagsOut &= ~lsfDisallowXRP;
|
||||
}
|
||||
|
||||
//
|
||||
// DisableMaster
|
||||
//
|
||||
|
||||
if ((uSetFlag == asfDisableMaster) && (uClearFlag == asfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if ((uSetFlag == asfDisableMaster) && !(uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
if (!mTxnAccount->isFieldPresent (sfRegularKey))
|
||||
return tecNO_REGULAR_KEY;
|
||||
|
||||
m_journal.trace << "Set lsfDisableMaster.";
|
||||
uFlagsOut |= lsfDisableMaster;
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisableMaster.";
|
||||
uFlagsOut &= ~lsfDisableMaster;
|
||||
}
|
||||
|
||||
if ((uSetFlag == asfNoFreeze) && (uClearFlag != asfNoFreeze))
|
||||
{
|
||||
m_journal.trace << "Set NoFreeze flag";
|
||||
uFlagsOut |= lsfNoFreeze;
|
||||
}
|
||||
|
||||
// Anyone may set global freeze
|
||||
if ((uSetFlag == asfGlobalFreeze) && (uClearFlag != asfGlobalFreeze))
|
||||
{
|
||||
m_journal.trace << "Set GlobalFreeze flag";
|
||||
uFlagsOut |= lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
// If you have set NoFreeze, you may not clear GlobalFreeze
|
||||
// This prevents those who have set NoFreeze from using
|
||||
// GlobalFreeze strategically.
|
||||
if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
|
||||
((uFlagsOut & lsfNoFreeze) == 0))
|
||||
{
|
||||
m_journal.trace << "Clear GlobalFreeze flag";
|
||||
uFlagsOut &= ~lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
//
|
||||
// Track transaction IDs signed by this account in its root
|
||||
//
|
||||
|
||||
if ((uSetFlag == asfAccountTxnID) && (uClearFlag != asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Set AccountTxnID";
|
||||
mTxnAccount->makeFieldPresent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfAccountTxnID) && (uSetFlag != asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Clear AccountTxnID";
|
||||
mTxnAccount->makeFieldAbsent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
//
|
||||
// EmailHash
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfEmailHash))
|
||||
{
|
||||
uint128 uHash = mTxn.getFieldH128 (sfEmailHash);
|
||||
|
||||
if (!uHash)
|
||||
if (uTxFlags & tfAccountSetMask)
|
||||
{
|
||||
m_journal.trace << "unset email hash";
|
||||
mTxnAccount->makeFieldAbsent (sfEmailHash);
|
||||
m_journal.trace << "Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
else
|
||||
|
||||
//
|
||||
// RequireAuth
|
||||
//
|
||||
|
||||
if (bSetRequireAuth && bClearRequireAuth)
|
||||
{
|
||||
m_journal.trace << "set email hash";
|
||||
mTxnAccount->setFieldH128 (sfEmailHash, uHash);
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
if (!mEngine->view().dirIsEmpty (Ledger::getOwnerDirIndex (mTxnAccountID)))
|
||||
{
|
||||
m_journal.trace << "Retry: Owner directory not empty.";
|
||||
|
||||
return (mParams & tapRETRY) ? terOWNERS : tecOWNERS;
|
||||
}
|
||||
|
||||
m_journal.trace << "Set RequireAuth.";
|
||||
uFlagsOut |= lsfRequireAuth;
|
||||
}
|
||||
|
||||
if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
|
||||
{
|
||||
m_journal.trace << "Clear RequireAuth.";
|
||||
uFlagsOut &= ~lsfRequireAuth;
|
||||
}
|
||||
|
||||
//
|
||||
// RequireDestTag
|
||||
//
|
||||
|
||||
if (bSetRequireDest && bClearRequireDest)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Set lsfRequireDestTag.";
|
||||
uFlagsOut |= lsfRequireDestTag;
|
||||
}
|
||||
|
||||
if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
|
||||
{
|
||||
m_journal.trace << "Clear lsfRequireDestTag.";
|
||||
uFlagsOut &= ~lsfRequireDestTag;
|
||||
}
|
||||
|
||||
//
|
||||
// DisallowXRP
|
||||
//
|
||||
|
||||
if (bSetDisallowXRP && bClearDisallowXRP)
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Set lsfDisallowXRP.";
|
||||
uFlagsOut |= lsfDisallowXRP;
|
||||
}
|
||||
|
||||
if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisallowXRP.";
|
||||
uFlagsOut &= ~lsfDisallowXRP;
|
||||
}
|
||||
|
||||
//
|
||||
// DisableMaster
|
||||
//
|
||||
|
||||
if ((uSetFlag == asfDisableMaster) && (uClearFlag == asfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Malformed transaction: Contradictory flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if ((uSetFlag == asfDisableMaster) && !(uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
if (!mTxnAccount->isFieldPresent (sfRegularKey))
|
||||
return tecNO_REGULAR_KEY;
|
||||
|
||||
m_journal.trace << "Set lsfDisableMaster.";
|
||||
uFlagsOut |= lsfDisableMaster;
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
|
||||
{
|
||||
m_journal.trace << "Clear lsfDisableMaster.";
|
||||
uFlagsOut &= ~lsfDisableMaster;
|
||||
}
|
||||
|
||||
if ((uSetFlag == asfNoFreeze) && (uClearFlag != asfNoFreeze))
|
||||
{
|
||||
m_journal.trace << "Set NoFreeze flag";
|
||||
uFlagsOut |= lsfNoFreeze;
|
||||
}
|
||||
|
||||
// Anyone may set global freeze
|
||||
if ((uSetFlag == asfGlobalFreeze) && (uClearFlag != asfGlobalFreeze))
|
||||
{
|
||||
m_journal.trace << "Set GlobalFreeze flag";
|
||||
uFlagsOut |= lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
// If you have set NoFreeze, you may not clear GlobalFreeze
|
||||
// This prevents those who have set NoFreeze from using
|
||||
// GlobalFreeze strategically.
|
||||
if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
|
||||
((uFlagsOut & lsfNoFreeze) == 0))
|
||||
{
|
||||
m_journal.trace << "Clear GlobalFreeze flag";
|
||||
uFlagsOut &= ~lsfGlobalFreeze;
|
||||
}
|
||||
|
||||
//
|
||||
// Track transaction IDs signed by this account in its root
|
||||
//
|
||||
|
||||
if ((uSetFlag == asfAccountTxnID) && (uClearFlag != asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Set AccountTxnID";
|
||||
mTxnAccount->makeFieldPresent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
if ((uClearFlag == asfAccountTxnID) && (uSetFlag != asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
|
||||
{
|
||||
m_journal.trace << "Clear AccountTxnID";
|
||||
mTxnAccount->makeFieldAbsent (sfAccountTxnID);
|
||||
}
|
||||
|
||||
//
|
||||
// EmailHash
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfEmailHash))
|
||||
{
|
||||
uint128 uHash = mTxn.getFieldH128 (sfEmailHash);
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
m_journal.trace << "unset email hash";
|
||||
mTxnAccount->makeFieldAbsent (sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set email hash";
|
||||
mTxnAccount->setFieldH128 (sfEmailHash, uHash);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// WalletLocator
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfWalletLocator))
|
||||
{
|
||||
uint256 uHash = mTxn.getFieldH256 (sfWalletLocator);
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
m_journal.trace << "unset wallet locator";
|
||||
mTxnAccount->makeFieldAbsent (sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set wallet locator";
|
||||
mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MessageKey
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfMessageKey))
|
||||
{
|
||||
Blob vucPublic = mTxn.getFieldVL (sfMessageKey);
|
||||
|
||||
if (vucPublic.empty ())
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
|
||||
mTxnAccount->makeFieldAbsent (sfMessageKey);
|
||||
}
|
||||
if (vucPublic.size () > PUBLIC_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "message key too long";
|
||||
|
||||
return telBAD_PUBLIC_KEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
|
||||
mTxnAccount->setFieldVL (sfMessageKey, vucPublic);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Domain
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfDomain))
|
||||
{
|
||||
Blob vucDomain = mTxn.getFieldVL (sfDomain);
|
||||
|
||||
if (vucDomain.empty ())
|
||||
{
|
||||
m_journal.trace << "unset domain";
|
||||
|
||||
mTxnAccount->makeFieldAbsent (sfDomain);
|
||||
}
|
||||
else if (vucDomain.size () > DOMAIN_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "domain too long";
|
||||
|
||||
return telBAD_DOMAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set domain";
|
||||
|
||||
mTxnAccount->setFieldVL (sfDomain, vucDomain);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TransferRate
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfTransferRate))
|
||||
{
|
||||
std::uint32_t uRate = mTxn.getFieldU32 (sfTransferRate);
|
||||
|
||||
if (!uRate || uRate == QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "unset transfer rate";
|
||||
mTxnAccount->makeFieldAbsent (sfTransferRate);
|
||||
}
|
||||
else if (uRate > QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "set transfer rate";
|
||||
mTxnAccount->setFieldU32 (sfTransferRate, uRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "bad transfer rate";
|
||||
return temBAD_TRANSFER_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// WalletLocator
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfWalletLocator))
|
||||
{
|
||||
uint256 uHash = mTxn.getFieldH256 (sfWalletLocator);
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
m_journal.trace << "unset wallet locator";
|
||||
mTxnAccount->makeFieldAbsent (sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set wallet locator";
|
||||
mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MessageKey
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfMessageKey))
|
||||
{
|
||||
Blob vucPublic = mTxn.getFieldVL (sfMessageKey);
|
||||
|
||||
if (vucPublic.empty ())
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
|
||||
mTxnAccount->makeFieldAbsent (sfMessageKey);
|
||||
}
|
||||
if (vucPublic.size () > PUBLIC_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "message key too long";
|
||||
|
||||
return telBAD_PUBLIC_KEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << "set message key";
|
||||
|
||||
mTxnAccount->setFieldVL (sfMessageKey, vucPublic);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Domain
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfDomain))
|
||||
{
|
||||
Blob vucDomain = mTxn.getFieldVL (sfDomain);
|
||||
|
||||
if (vucDomain.empty ())
|
||||
{
|
||||
m_journal.trace << "unset domain";
|
||||
|
||||
mTxnAccount->makeFieldAbsent (sfDomain);
|
||||
}
|
||||
else if (vucDomain.size () > DOMAIN_BYTES_MAX)
|
||||
{
|
||||
m_journal.trace << "domain too long";
|
||||
|
||||
return telBAD_DOMAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "set domain";
|
||||
|
||||
mTxnAccount->setFieldVL (sfDomain, vucDomain);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TransferRate
|
||||
//
|
||||
|
||||
if (mTxn.isFieldPresent (sfTransferRate))
|
||||
{
|
||||
std::uint32_t uRate = mTxn.getFieldU32 (sfTransferRate);
|
||||
|
||||
if (!uRate || uRate == QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "unset transfer rate";
|
||||
mTxnAccount->makeFieldAbsent (sfTransferRate);
|
||||
}
|
||||
else if (uRate > QUALITY_ONE)
|
||||
{
|
||||
m_journal.trace << "set transfer rate";
|
||||
mTxnAccount->setFieldU32 (sfTransferRate, uRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace << "bad transfer rate";
|
||||
return temBAD_TRANSFER_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);
|
||||
|
||||
return tesSUCCESS;
|
||||
TER
|
||||
transact_SetAccount (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return SetAccount(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,57 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_ACCOUNTSET_H_INCLUDED
|
||||
#define RIPPLE_TX_ACCOUNTSET_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetAccount
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
SetAccount (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetAccount"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER doApply () override;
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_SetAccount (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <SetAccount> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,50 +19,76 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
std::uint64_t SetRegularKey::calculateBaseFee ()
|
||||
class SetRegularKey
|
||||
: public Transactor
|
||||
{
|
||||
if ( mTxnAccount
|
||||
&& (! (mTxnAccount->getFlags () & lsfPasswordSpent))
|
||||
&& (mSigningPubKey.getAccountID () == mTxnAccountID))
|
||||
std::uint64_t calculateBaseFee () override
|
||||
{
|
||||
// flag is armed and they signed with the right account
|
||||
return 0;
|
||||
if ( mTxnAccount
|
||||
&& (! (mTxnAccount->getFlags () & lsfPasswordSpent))
|
||||
&& (mSigningPubKey.getAccountID () == mTxnAccountID))
|
||||
{
|
||||
// flag is armed and they signed with the right account
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Transactor::calculateBaseFee ();
|
||||
}
|
||||
|
||||
return Transactor::calculateBaseFee ();
|
||||
}
|
||||
public:
|
||||
SetRegularKey (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetRegularKey"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER SetRegularKey::doApply ()
|
||||
TER doApply () override
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (mFeeDue == zero)
|
||||
{
|
||||
mTxnAccount->setFlag (lsfPasswordSpent);
|
||||
}
|
||||
|
||||
if (mTxn.isFieldPresent (sfRegularKey))
|
||||
{
|
||||
Account uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
|
||||
mTxnAccount->setFieldAccount (sfRegularKey, uAuthKeyID);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mTxnAccount->isFlag (lsfDisableMaster))
|
||||
return tecMASTER_DISABLED;
|
||||
mTxnAccount->makeFieldAbsent (sfRegularKey);
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
TER
|
||||
transact_SetRegularKey (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfUniversalMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (mFeeDue == zero)
|
||||
{
|
||||
mTxnAccount->setFlag (lsfPasswordSpent);
|
||||
}
|
||||
|
||||
if (mTxn.isFieldPresent (sfRegularKey))
|
||||
{
|
||||
Account uAuthKeyID = mTxn.getFieldAccount160 (sfRegularKey);
|
||||
mTxnAccount->setFieldAccount (sfRegularKey, uAuthKeyID);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mTxnAccount->isFlag (lsfDisableMaster))
|
||||
return tecMASTER_DISABLED;
|
||||
mTxnAccount->makeFieldAbsent (sfRegularKey);
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
return SetRegularKey(txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,60 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_REGULARSETKEY_H_INCLUDED
|
||||
#define RIPPLE_TX_REGULARSETKEY_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetRegularKey
|
||||
: public Transactor
|
||||
{
|
||||
std::uint64_t calculateBaseFee ();
|
||||
|
||||
public:
|
||||
SetRegularKey (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetRegularKey"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TER checkFee ();
|
||||
TER doApply ();
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_SetRegularKey (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <SetRegularKey> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,383 +19,417 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TER SetTrust::doApply ()
|
||||
class SetTrust
|
||||
: public Transactor
|
||||
{
|
||||
TER terResult = tesSUCCESS;
|
||||
|
||||
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
|
||||
bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn));
|
||||
bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut));
|
||||
|
||||
Currency const currency (saLimitAmount.getCurrency ());
|
||||
Account uDstAccountID (saLimitAmount.getIssuer ());
|
||||
|
||||
// true, iff current is high account.
|
||||
bool const bHigh = mTxnAccountID > uDstAccountID;
|
||||
|
||||
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
|
||||
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
|
||||
|
||||
if (!saLimitAmount.isLegalNet ())
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
if (bQualityIn && QUALITY_ONE == uQualityIn)
|
||||
uQualityIn = 0;
|
||||
|
||||
if (bQualityOut && QUALITY_ONE == uQualityOut)
|
||||
uQualityOut = 0;
|
||||
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
if (uTxFlags & tfTrustSetMask)
|
||||
public:
|
||||
SetTrust (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetTrust"))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
bool const bSetAuth = (uTxFlags & tfSetfAuth);
|
||||
bool const bSetNoRipple = (uTxFlags & tfSetNoRipple);
|
||||
bool const bClearNoRipple = (uTxFlags & tfClearNoRipple);
|
||||
bool const bSetFreeze = (uTxFlags & tfSetFreeze);
|
||||
bool const bClearFreeze = (uTxFlags & tfClearFreeze);
|
||||
|
||||
if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth))
|
||||
TER doApply () override
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Retry: Auth not required.";
|
||||
return tefNO_AUTH_REQUIRED;
|
||||
}
|
||||
TER terResult = tesSUCCESS;
|
||||
|
||||
if (saLimitAmount.isNative ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Native credit limit: " <<
|
||||
saLimitAmount.getFullText ();
|
||||
return temBAD_LIMIT;
|
||||
}
|
||||
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
|
||||
bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn));
|
||||
bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut));
|
||||
|
||||
if (saLimitAmount < zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Negative credit limit.";
|
||||
return temBAD_LIMIT;
|
||||
}
|
||||
Currency const currency (saLimitAmount.getCurrency ());
|
||||
Account uDstAccountID (saLimitAmount.getIssuer ());
|
||||
|
||||
// Check if destination makes sense.
|
||||
if (!uDstAccountID || uDstAccountID == noAccount())
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Destination account not specified.";
|
||||
// true, iff current is high account.
|
||||
bool const bHigh = mTxnAccountID > uDstAccountID;
|
||||
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
|
||||
|
||||
// The reserve required to create the line. Note that we allow up to
|
||||
// two trust lines without requiring a reserve because being able to
|
||||
// exchange currencies is a powerful Ripple feature.
|
||||
//
|
||||
// This is also a security feature: if you're a gateway and you want to
|
||||
// be able to let someone use your services, you would otherwise have to
|
||||
// give them enough XRP to cover the incremental reserve for their trust
|
||||
// line. If they had no intention of using your services, they could use
|
||||
// the XRP for their own purposes. So we make it possible for gateways
|
||||
// to fund accounts in a way where there's no incentive to trick them
|
||||
// into creating an account you have no intention of using.
|
||||
|
||||
if (mTxnAccountID == uDstAccountID)
|
||||
{
|
||||
SLE::pointer selDelete (
|
||||
mEngine->entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (
|
||||
mTxnAccountID, uDstAccountID, currency)));
|
||||
|
||||
if (selDelete)
|
||||
{
|
||||
m_journal.warning <<
|
||||
"Clearing redundant line.";
|
||||
|
||||
return mEngine->view ().trustDelete (
|
||||
selDelete, mTxnAccountID, uDstAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Can not extend credit to self.";
|
||||
return temDST_IS_SRC;
|
||||
}
|
||||
}
|
||||
|
||||
SLE::pointer sleDst (mEngine->entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
|
||||
|
||||
if (!sleDst)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
return tecNO_DST;
|
||||
}
|
||||
|
||||
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
|
||||
// The reserve required to create the line.
|
||||
std::uint64_t const uReserveCreate =
|
||||
(uOwnerCount < 2)
|
||||
std::uint64_t const uReserveCreate = (uOwnerCount < 2)
|
||||
? 0
|
||||
: mEngine->getLedger ()->getReserve (uOwnerCount + 1);
|
||||
|
||||
STAmount saLimitAllow = saLimitAmount;
|
||||
saLimitAllow.setIssuer (mTxnAccountID);
|
||||
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
|
||||
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
|
||||
|
||||
SLE::pointer sleRippleState (mEngine->entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, currency)));
|
||||
if (!saLimitAmount.isLegalNet ())
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
STAmount saLowBalance;
|
||||
STAmount saLowLimit;
|
||||
STAmount saHighBalance;
|
||||
STAmount saHighLimit;
|
||||
std::uint32_t uLowQualityIn;
|
||||
std::uint32_t uLowQualityOut;
|
||||
std::uint32_t uHighQualityIn;
|
||||
std::uint32_t uHighQualityOut;
|
||||
auto const& uLowAccountID = !bHigh ? mTxnAccountID : uDstAccountID;
|
||||
auto const& uHighAccountID = bHigh ? mTxnAccountID : uDstAccountID;
|
||||
SLE::ref sleLowAccount = !bHigh ? mTxnAccount : sleDst;
|
||||
SLE::ref sleHighAccount = bHigh ? mTxnAccount : sleDst;
|
||||
if (bQualityOut && QUALITY_ONE == uQualityOut)
|
||||
uQualityOut = 0;
|
||||
|
||||
//
|
||||
// Balances
|
||||
//
|
||||
std::uint32_t const uTxFlags = mTxn.getFlags ();
|
||||
|
||||
saLowBalance = sleRippleState->getFieldAmount (sfBalance);
|
||||
saHighBalance = -saLowBalance;
|
||||
|
||||
//
|
||||
// Limits
|
||||
//
|
||||
|
||||
sleRippleState->setFieldAmount (!bHigh ? sfLowLimit : sfHighLimit, saLimitAllow);
|
||||
|
||||
saLowLimit = !bHigh ? saLimitAllow : sleRippleState->getFieldAmount (sfLowLimit);
|
||||
saHighLimit = bHigh ? saLimitAllow : sleRippleState->getFieldAmount (sfHighLimit);
|
||||
|
||||
//
|
||||
// Quality in
|
||||
//
|
||||
|
||||
if (!bQualityIn)
|
||||
{
|
||||
// Not setting. Just get it.
|
||||
|
||||
uLowQualityIn = sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
else if (uQualityIn)
|
||||
{
|
||||
// Setting.
|
||||
|
||||
sleRippleState->setFieldU32 (!bHigh ? sfLowQualityIn : sfHighQualityIn, uQualityIn);
|
||||
|
||||
uLowQualityIn = !bHigh ? uQualityIn : sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = bHigh ? uQualityIn : sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clearing.
|
||||
|
||||
sleRippleState->makeFieldAbsent (!bHigh ? sfLowQualityIn : sfHighQualityIn);
|
||||
|
||||
uLowQualityIn = !bHigh ? 0 : sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = bHigh ? 0 : sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
|
||||
if (QUALITY_ONE == uLowQualityIn) uLowQualityIn = 0;
|
||||
|
||||
if (QUALITY_ONE == uHighQualityIn) uHighQualityIn = 0;
|
||||
|
||||
//
|
||||
// Quality out
|
||||
//
|
||||
|
||||
if (!bQualityOut)
|
||||
{
|
||||
// Not setting. Just get it.
|
||||
|
||||
uLowQualityOut = sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
else if (uQualityOut)
|
||||
{
|
||||
// Setting.
|
||||
|
||||
sleRippleState->setFieldU32 (!bHigh ? sfLowQualityOut : sfHighQualityOut, uQualityOut);
|
||||
|
||||
uLowQualityOut = !bHigh ? uQualityOut : sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = bHigh ? uQualityOut : sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clearing.
|
||||
|
||||
sleRippleState->makeFieldAbsent (!bHigh ? sfLowQualityOut : sfHighQualityOut);
|
||||
|
||||
uLowQualityOut = !bHigh ? 0 : sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = bHigh ? 0 : sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
|
||||
std::uint32_t const uFlagsIn (sleRippleState->getFieldU32 (sfFlags));
|
||||
std::uint32_t uFlagsOut (uFlagsIn);
|
||||
|
||||
if (bSetNoRipple && !bClearNoRipple && (bHigh ? saHighBalance : saLowBalance) >= zero)
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
else if (bClearNoRipple && !bSetNoRipple)
|
||||
{
|
||||
uFlagsOut &= ~(bHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
|
||||
if (bSetFreeze && !bClearFreeze && !mTxnAccount->isFlag (lsfNoFreeze))
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
else if (bClearFreeze && !bSetFreeze)
|
||||
{
|
||||
uFlagsOut &= ~(bHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
|
||||
if (QUALITY_ONE == uLowQualityOut) uLowQualityOut = 0;
|
||||
|
||||
if (QUALITY_ONE == uHighQualityOut) uHighQualityOut = 0;
|
||||
|
||||
|
||||
bool const bLowReserveSet = uLowQualityIn || uLowQualityOut ||
|
||||
(uFlagsOut & lsfLowNoRipple) ||
|
||||
(uFlagsOut & lsfLowFreeze) ||
|
||||
saLowLimit || saLowBalance > zero;
|
||||
bool const bLowReserveClear = !bLowReserveSet;
|
||||
|
||||
bool const bHighReserveSet = uHighQualityIn || uHighQualityOut ||
|
||||
(uFlagsOut & lsfHighNoRipple) ||
|
||||
(uFlagsOut & lsfHighFreeze) ||
|
||||
saHighLimit || saHighBalance > zero;
|
||||
bool const bHighReserveClear = !bHighReserveSet;
|
||||
|
||||
bool const bDefault = bLowReserveClear && bHighReserveClear;
|
||||
|
||||
bool const bLowReserved = (uFlagsIn & lsfLowReserve);
|
||||
bool const bHighReserved = (uFlagsIn & lsfHighReserve);
|
||||
|
||||
bool bReserveIncrease = false;
|
||||
|
||||
if (bSetAuth)
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighAuth : lsfLowAuth);
|
||||
}
|
||||
|
||||
if (bLowReserveSet && !bLowReserved)
|
||||
{
|
||||
// Set reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, 1, sleLowAccount);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
if (!bHigh)
|
||||
bReserveIncrease = true;
|
||||
}
|
||||
|
||||
if (bLowReserveClear && bLowReserved)
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, -1, sleLowAccount);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
}
|
||||
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
{
|
||||
// Set reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, 1, sleHighAccount);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
if (bHigh)
|
||||
bReserveIncrease = true;
|
||||
}
|
||||
|
||||
if (bHighReserveClear && bHighReserved)
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, -1, sleHighAccount);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
sleRippleState->setFieldU32 (sfFlags, uFlagsOut);
|
||||
|
||||
if (bDefault || badCurrency() == currency)
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult = mEngine->view ().trustDelete (sleRippleState, uLowAccountID, uHighAccountID);
|
||||
}
|
||||
else if (bReserveIncrease
|
||||
&& mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
|
||||
if (uTxFlags & tfTrustSetMask)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Insufficent reserve to add trust line.";
|
||||
"Malformed transaction: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
// Another transaction could provide XRP to the account and then
|
||||
// this transaction would succeed.
|
||||
terResult = tecINSUF_RESERVE_LINE;
|
||||
bool const bSetAuth = (uTxFlags & tfSetfAuth);
|
||||
bool const bSetNoRipple = (uTxFlags & tfSetNoRipple);
|
||||
bool const bClearNoRipple = (uTxFlags & tfClearNoRipple);
|
||||
bool const bSetFreeze = (uTxFlags & tfSetFreeze);
|
||||
bool const bClearFreeze = (uTxFlags & tfClearFreeze);
|
||||
|
||||
if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth))
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Retry: Auth not required.";
|
||||
return tefNO_AUTH_REQUIRED;
|
||||
}
|
||||
|
||||
if (saLimitAmount.isNative ())
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Native credit limit: " <<
|
||||
saLimitAmount.getFullText ();
|
||||
return temBAD_LIMIT;
|
||||
}
|
||||
|
||||
if (saLimitAmount < zero)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Negative credit limit.";
|
||||
return temBAD_LIMIT;
|
||||
}
|
||||
|
||||
// Check if destination makes sense.
|
||||
if (!uDstAccountID || uDstAccountID == noAccount())
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Destination account not specified.";
|
||||
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
|
||||
if (mTxnAccountID == uDstAccountID)
|
||||
{
|
||||
SLE::pointer selDelete (
|
||||
mEngine->entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (
|
||||
mTxnAccountID, uDstAccountID, currency)));
|
||||
|
||||
if (selDelete)
|
||||
{
|
||||
m_journal.warning <<
|
||||
"Clearing redundant line.";
|
||||
|
||||
return mEngine->view ().trustDelete (
|
||||
selDelete, mTxnAccountID, uDstAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Malformed transaction: Can not extend credit to self.";
|
||||
return temDST_IS_SRC;
|
||||
}
|
||||
}
|
||||
|
||||
SLE::pointer sleDst (mEngine->entryCache (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
|
||||
|
||||
if (!sleDst)
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Destination account does not exist.";
|
||||
return tecNO_DST;
|
||||
}
|
||||
|
||||
STAmount saLimitAllow = saLimitAmount;
|
||||
saLimitAllow.setIssuer (mTxnAccountID);
|
||||
|
||||
SLE::pointer sleRippleState (mEngine->entryCache (ltRIPPLE_STATE,
|
||||
Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, currency)));
|
||||
|
||||
if (sleRippleState)
|
||||
{
|
||||
STAmount saLowBalance;
|
||||
STAmount saLowLimit;
|
||||
STAmount saHighBalance;
|
||||
STAmount saHighLimit;
|
||||
std::uint32_t uLowQualityIn;
|
||||
std::uint32_t uLowQualityOut;
|
||||
std::uint32_t uHighQualityIn;
|
||||
std::uint32_t uHighQualityOut;
|
||||
auto const& uLowAccountID = !bHigh ? mTxnAccountID : uDstAccountID;
|
||||
auto const& uHighAccountID = bHigh ? mTxnAccountID : uDstAccountID;
|
||||
SLE::ref sleLowAccount = !bHigh ? mTxnAccount : sleDst;
|
||||
SLE::ref sleHighAccount = bHigh ? mTxnAccount : sleDst;
|
||||
|
||||
//
|
||||
// Balances
|
||||
//
|
||||
|
||||
saLowBalance = sleRippleState->getFieldAmount (sfBalance);
|
||||
saHighBalance = -saLowBalance;
|
||||
|
||||
//
|
||||
// Limits
|
||||
//
|
||||
|
||||
sleRippleState->setFieldAmount (!bHigh ? sfLowLimit : sfHighLimit, saLimitAllow);
|
||||
|
||||
saLowLimit = !bHigh ? saLimitAllow : sleRippleState->getFieldAmount (sfLowLimit);
|
||||
saHighLimit = bHigh ? saLimitAllow : sleRippleState->getFieldAmount (sfHighLimit);
|
||||
|
||||
//
|
||||
// Quality in
|
||||
//
|
||||
|
||||
if (!bQualityIn)
|
||||
{
|
||||
// Not setting. Just get it.
|
||||
|
||||
uLowQualityIn = sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
else if (uQualityIn)
|
||||
{
|
||||
// Setting.
|
||||
|
||||
sleRippleState->setFieldU32 (!bHigh ? sfLowQualityIn : sfHighQualityIn, uQualityIn);
|
||||
|
||||
uLowQualityIn = !bHigh ? uQualityIn : sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = bHigh ? uQualityIn : sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clearing.
|
||||
|
||||
sleRippleState->makeFieldAbsent (!bHigh ? sfLowQualityIn : sfHighQualityIn);
|
||||
|
||||
uLowQualityIn = !bHigh ? 0 : sleRippleState->getFieldU32 (sfLowQualityIn);
|
||||
uHighQualityIn = bHigh ? 0 : sleRippleState->getFieldU32 (sfHighQualityIn);
|
||||
}
|
||||
|
||||
if (QUALITY_ONE == uLowQualityIn) uLowQualityIn = 0;
|
||||
|
||||
if (QUALITY_ONE == uHighQualityIn) uHighQualityIn = 0;
|
||||
|
||||
//
|
||||
// Quality out
|
||||
//
|
||||
|
||||
if (!bQualityOut)
|
||||
{
|
||||
// Not setting. Just get it.
|
||||
|
||||
uLowQualityOut = sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
else if (uQualityOut)
|
||||
{
|
||||
// Setting.
|
||||
|
||||
sleRippleState->setFieldU32 (!bHigh ? sfLowQualityOut : sfHighQualityOut, uQualityOut);
|
||||
|
||||
uLowQualityOut = !bHigh ? uQualityOut : sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = bHigh ? uQualityOut : sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clearing.
|
||||
|
||||
sleRippleState->makeFieldAbsent (!bHigh ? sfLowQualityOut : sfHighQualityOut);
|
||||
|
||||
uLowQualityOut = !bHigh ? 0 : sleRippleState->getFieldU32 (sfLowQualityOut);
|
||||
uHighQualityOut = bHigh ? 0 : sleRippleState->getFieldU32 (sfHighQualityOut);
|
||||
}
|
||||
|
||||
std::uint32_t const uFlagsIn (sleRippleState->getFieldU32 (sfFlags));
|
||||
std::uint32_t uFlagsOut (uFlagsIn);
|
||||
|
||||
if (bSetNoRipple && !bClearNoRipple && (bHigh ? saHighBalance : saLowBalance) >= zero)
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
else if (bClearNoRipple && !bSetNoRipple)
|
||||
{
|
||||
uFlagsOut &= ~(bHigh ? lsfHighNoRipple : lsfLowNoRipple);
|
||||
}
|
||||
|
||||
if (bSetFreeze && !bClearFreeze && !mTxnAccount->isFlag (lsfNoFreeze))
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
else if (bClearFreeze && !bSetFreeze)
|
||||
{
|
||||
uFlagsOut &= ~(bHigh ? lsfHighFreeze : lsfLowFreeze);
|
||||
}
|
||||
|
||||
if (QUALITY_ONE == uLowQualityOut) uLowQualityOut = 0;
|
||||
|
||||
if (QUALITY_ONE == uHighQualityOut) uHighQualityOut = 0;
|
||||
|
||||
|
||||
bool const bLowReserveSet = uLowQualityIn || uLowQualityOut ||
|
||||
(uFlagsOut & lsfLowNoRipple) ||
|
||||
(uFlagsOut & lsfLowFreeze) ||
|
||||
saLowLimit || saLowBalance > zero;
|
||||
bool const bLowReserveClear = !bLowReserveSet;
|
||||
|
||||
bool const bHighReserveSet = uHighQualityIn || uHighQualityOut ||
|
||||
(uFlagsOut & lsfHighNoRipple) ||
|
||||
(uFlagsOut & lsfHighFreeze) ||
|
||||
saHighLimit || saHighBalance > zero;
|
||||
bool const bHighReserveClear = !bHighReserveSet;
|
||||
|
||||
bool const bDefault = bLowReserveClear && bHighReserveClear;
|
||||
|
||||
bool const bLowReserved = (uFlagsIn & lsfLowReserve);
|
||||
bool const bHighReserved = (uFlagsIn & lsfHighReserve);
|
||||
|
||||
bool bReserveIncrease = false;
|
||||
|
||||
if (bSetAuth)
|
||||
{
|
||||
uFlagsOut |= (bHigh ? lsfHighAuth : lsfLowAuth);
|
||||
}
|
||||
|
||||
if (bLowReserveSet && !bLowReserved)
|
||||
{
|
||||
// Set reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, 1, sleLowAccount);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
if (!bHigh)
|
||||
bReserveIncrease = true;
|
||||
}
|
||||
|
||||
if (bLowReserveClear && bLowReserved)
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uLowAccountID, -1, sleLowAccount);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
}
|
||||
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
{
|
||||
// Set reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, 1, sleHighAccount);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
if (bHigh)
|
||||
bReserveIncrease = true;
|
||||
}
|
||||
|
||||
if (bHighReserveClear && bHighReserved)
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
|
||||
mEngine->view ().ownerCountAdjust (uHighAccountID, -1, sleHighAccount);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
sleRippleState->setFieldU32 (sfFlags, uFlagsOut);
|
||||
|
||||
if (bDefault || badCurrency() == currency)
|
||||
{
|
||||
// Delete.
|
||||
|
||||
terResult = mEngine->view ().trustDelete (sleRippleState, uLowAccountID, uHighAccountID);
|
||||
}
|
||||
else if (bReserveIncrease
|
||||
&& mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Insufficent reserve to add trust line.";
|
||||
|
||||
// Another transaction could provide XRP to the account and then
|
||||
// this transaction would succeed.
|
||||
terResult = tecINSUF_RESERVE_LINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEngine->entryModify (sleRippleState);
|
||||
|
||||
m_journal.trace << "Modify ripple line";
|
||||
}
|
||||
}
|
||||
// Line does not exist.
|
||||
else if (!saLimitAmount // Setting default limit.
|
||||
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
|
||||
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Redundant: Setting non-existent ripple line to defaults.";
|
||||
return tecNO_LINE_REDUNDANT;
|
||||
}
|
||||
else if (mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Line does not exist. Insufficent reserve to create line.";
|
||||
|
||||
// Another transaction could create the account and then this transaction would succeed.
|
||||
terResult = tecNO_LINE_INSUF_RESERVE;
|
||||
}
|
||||
else if (badCurrency() == currency)
|
||||
{
|
||||
terResult = temBAD_CURRENCY;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEngine->entryModify (sleRippleState);
|
||||
// Zero balance in currency.
|
||||
STAmount saBalance ({currency, noAccount()});
|
||||
|
||||
m_journal.trace << "Modify ripple line";
|
||||
uint256 index (Ledger::getRippleStateIndex (
|
||||
mTxnAccountID, uDstAccountID, currency));
|
||||
|
||||
m_journal.trace <<
|
||||
"doTrustSet: Creating ripple line: " <<
|
||||
to_string (index);
|
||||
|
||||
// Create a new ripple line.
|
||||
terResult = mEngine->view ().trustCreate (
|
||||
bHigh,
|
||||
mTxnAccountID,
|
||||
uDstAccountID,
|
||||
index,
|
||||
mTxnAccount,
|
||||
bSetAuth,
|
||||
bSetNoRipple && !bClearNoRipple,
|
||||
bSetFreeze && !bClearFreeze,
|
||||
saBalance,
|
||||
saLimitAllow, // Limit for who is being charged.
|
||||
uQualityIn,
|
||||
uQualityOut);
|
||||
}
|
||||
}
|
||||
// Line does not exist.
|
||||
else if (!saLimitAmount // Setting default limit.
|
||||
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
|
||||
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Redundant: Setting non-existent ripple line to defaults.";
|
||||
return tecNO_LINE_REDUNDANT;
|
||||
}
|
||||
else if (mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
|
||||
{
|
||||
m_journal.trace <<
|
||||
"Delay transaction: Line does not exist. Insufficent reserve to create line.";
|
||||
|
||||
// Another transaction could create the account and then this transaction would succeed.
|
||||
terResult = tecNO_LINE_INSUF_RESERVE;
|
||||
return terResult;
|
||||
}
|
||||
else if (badCurrency() == currency)
|
||||
{
|
||||
terResult = temBAD_CURRENCY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Zero balance in currency.
|
||||
STAmount saBalance ({currency, noAccount()});
|
||||
};
|
||||
|
||||
uint256 index (Ledger::getRippleStateIndex (
|
||||
mTxnAccountID, uDstAccountID, currency));
|
||||
|
||||
m_journal.trace <<
|
||||
"doTrustSet: Creating ripple line: " <<
|
||||
to_string (index);
|
||||
|
||||
// Create a new ripple line.
|
||||
terResult = mEngine->view ().trustCreate (
|
||||
bHigh,
|
||||
mTxnAccountID,
|
||||
uDstAccountID,
|
||||
index,
|
||||
mTxnAccount,
|
||||
bSetAuth,
|
||||
bSetNoRipple && !bClearNoRipple,
|
||||
bSetFreeze && !bClearFreeze,
|
||||
saBalance,
|
||||
saLimitAllow, // Limit for who is being charged.
|
||||
uQualityIn,
|
||||
uQualityOut);
|
||||
}
|
||||
|
||||
return terResult;
|
||||
TER
|
||||
transact_SetTrust (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return SetTrust (txn, params, engine).apply ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_TRUSTSET_H_INCLUDED
|
||||
#define RIPPLE_TX_TRUSTSET_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SetTrust
|
||||
: public Transactor
|
||||
{
|
||||
public:
|
||||
SetTrust (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
: Transactor (
|
||||
txn,
|
||||
params,
|
||||
engine,
|
||||
deprecatedLogs().journal("SetTrust"))
|
||||
{
|
||||
}
|
||||
|
||||
TER doApply ();
|
||||
};
|
||||
|
||||
inline
|
||||
std::unique_ptr <Transactor>
|
||||
make_SetTrust (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
{
|
||||
return std::make_unique <SetTrust> (txn, params, engine);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,18 +18,20 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/module/app/transactors/Transactor.h>
|
||||
#include <ripple/module/app/transactors/AddWallet.h>
|
||||
#include <ripple/module/app/transactors/CancelOffer.h>
|
||||
#include <ripple/module/app/transactors/Change.h>
|
||||
#include <ripple/module/app/transactors/CreateOffer.h>
|
||||
#include <ripple/module/app/transactors/Payment.h>
|
||||
#include <ripple/module/app/transactors/SetAccount.h>
|
||||
#include <ripple/module/app/transactors/SetRegularKey.h>
|
||||
#include <ripple/module/app/transactors/SetTrust.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
std::unique_ptr<Transactor> Transactor::makeTransactor (
|
||||
TER transact_Payment (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_SetAccount (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_SetRegularKey (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_SetTrust (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_CreateOffer (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_CancelOffer (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_AddWallet (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
TER transact_Change (SerializedTransaction const& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||
|
||||
TER
|
||||
Transactor::transact (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine)
|
||||
@@ -37,36 +39,35 @@ std::unique_ptr<Transactor> Transactor::makeTransactor (
|
||||
switch (txn.getTxnType ())
|
||||
{
|
||||
case ttPAYMENT:
|
||||
return make_Payment (txn, params, engine);
|
||||
return transact_Payment (txn, params, engine);
|
||||
|
||||
case ttACCOUNT_SET:
|
||||
return make_SetAccount (txn, params, engine);
|
||||
return transact_SetAccount (txn, params, engine);
|
||||
|
||||
case ttREGULAR_KEY_SET:
|
||||
return make_SetRegularKey (txn, params, engine);
|
||||
return transact_SetRegularKey (txn, params, engine);
|
||||
|
||||
case ttTRUST_SET:
|
||||
return make_SetTrust (txn, params, engine);
|
||||
return transact_SetTrust (txn, params, engine);
|
||||
|
||||
case ttOFFER_CREATE:
|
||||
return make_CreateOffer (txn, params, engine);
|
||||
return transact_CreateOffer (txn, params, engine);
|
||||
|
||||
case ttOFFER_CANCEL:
|
||||
return make_CancelOffer (txn, params, engine);
|
||||
return transact_CancelOffer (txn, params, engine);
|
||||
|
||||
case ttWALLET_ADD:
|
||||
return make_AddWallet (txn, params, engine);
|
||||
return transact_AddWallet (txn, params, engine);
|
||||
|
||||
case ttAMENDMENT:
|
||||
case ttFEE:
|
||||
return make_Change (txn, params, engine);
|
||||
return transact_Change (txn, params, engine);
|
||||
|
||||
default:
|
||||
return std::unique_ptr<Transactor> ();
|
||||
return temUNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Transactor::Transactor (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
|
||||
@@ -25,12 +25,15 @@ namespace ripple {
|
||||
class Transactor
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<Transactor> makeTransactor (
|
||||
static
|
||||
TER
|
||||
transact (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
TransactionEngine* engine);
|
||||
|
||||
TER apply ();
|
||||
TER
|
||||
apply ();
|
||||
|
||||
protected:
|
||||
SerializedTransaction const& mTxn;
|
||||
|
||||
@@ -70,8 +70,10 @@ void TransactionEngine::txnWrite ()
|
||||
}
|
||||
}
|
||||
|
||||
TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, TransactionEngineParams params,
|
||||
bool& didApply)
|
||||
TER TransactionEngine::applyTransaction (
|
||||
SerializedTransaction const& txn,
|
||||
TransactionEngineParams params,
|
||||
bool& didApply)
|
||||
{
|
||||
WriteLog (lsTRACE, TransactionEngine) << "applyTransaction>";
|
||||
didApply = false;
|
||||
@@ -79,7 +81,6 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
mNodes.init (mLedger, txn.getTransactionID (), mLedger->getLedgerSeq (), params);
|
||||
|
||||
#ifdef BEAST_DEBUG
|
||||
|
||||
if (1)
|
||||
{
|
||||
Serializer ser;
|
||||
@@ -89,39 +90,46 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
|
||||
if (!s2.isEquivalent (txn))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) << "Transaction serdes mismatch";
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Transaction serdes mismatch";
|
||||
Json::StyledStreamWriter ssw;
|
||||
WriteLog (lsINFO, TransactionEngine) << txn.getJson (0);
|
||||
WriteLog (lsFATAL, TransactionEngine) << s2.getJson (0);
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint256 txID = txn.getTransactionID ();
|
||||
|
||||
if (!txID)
|
||||
{
|
||||
WriteLog (lsWARNING, TransactionEngine) << "applyTransaction: invalid transaction id";
|
||||
WriteLog (lsWARNING, TransactionEngine) <<
|
||||
"applyTransaction: invalid transaction id";
|
||||
return temINVALID;
|
||||
}
|
||||
|
||||
std::unique_ptr<Transactor> transactor = Transactor::makeTransactor (txn, params, this);
|
||||
TER terResult = Transactor::transact (txn, params, this);
|
||||
|
||||
if (transactor.get () == nullptr)
|
||||
if (terResult == temUNKNOWN)
|
||||
{
|
||||
WriteLog (lsWARNING, TransactionEngine) << "applyTransaction: Invalid transaction: unknown transaction type";
|
||||
WriteLog (lsWARNING, TransactionEngine) <<
|
||||
"applyTransaction: Invalid transaction: unknown transaction type";
|
||||
return temUNKNOWN;
|
||||
}
|
||||
|
||||
TER terResult = transactor->apply ();
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
if (ShouldLog (lsINFO, TransactionEngine))
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
transResultInfo (terResult, strToken, strHuman);
|
||||
transResultInfo (terResult, strToken, strHuman);
|
||||
|
||||
WriteLog (lsINFO, TransactionEngine) << "applyTransaction: terResult=" << strToken << " : " << terResult << " : " << strHuman;
|
||||
WriteLog (lsINFO, TransactionEngine) <<
|
||||
"applyTransaction: terResult=" << strToken <<
|
||||
" : " << terResult <<
|
||||
" : " << strHuman;
|
||||
}
|
||||
|
||||
if (isTesSuccess (terResult))
|
||||
didApply = true;
|
||||
@@ -131,7 +139,8 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
WriteLog (lsDEBUG, TransactionEngine) << "Reprocessing to only claim fee";
|
||||
mNodes.clear ();
|
||||
|
||||
SLE::pointer txnAcct = entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (txn.getSourceAccount ()));
|
||||
SLE::pointer txnAcct = entryCache (ltACCOUNT_ROOT,
|
||||
Ledger::getAccountRootIndex (txn.getSourceAccount ()));
|
||||
|
||||
if (!txnAcct)
|
||||
terResult = terNO_ACCOUNT;
|
||||
@@ -177,16 +186,21 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
{
|
||||
if (!checkInvariants (terResult, txn, params))
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transaction succeeded fully or (retries are not allowed and the transaction could claim a fee)
|
||||
// Transaction succeeded fully or (retries are not allowed and the
|
||||
// transaction could claim a fee)
|
||||
Serializer m;
|
||||
mNodes.calcRawMeta (m, terResult, mTxnSeq++);
|
||||
|
||||
@@ -199,7 +213,8 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
{
|
||||
if (!mLedger->addTransaction (txID, s))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) << "Tried to add transaction to open ledger that already had it";
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Tried to add transaction to open ledger that already had it";
|
||||
assert (false);
|
||||
throw std::runtime_error ("Duplicate transaction applied");
|
||||
}
|
||||
@@ -208,7 +223,8 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
|
||||
{
|
||||
if (!mLedger->addTransaction (txID, s, m))
|
||||
{
|
||||
WriteLog (lsFATAL, TransactionEngine) << "Tried to add transaction to ledger that already had it";
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
"Tried to add transaction to ledger that already had it";
|
||||
assert (false);
|
||||
throw std::runtime_error ("Duplicate transaction applied to closed ledger");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user