Compare commits

...

10 Commits

Author SHA1 Message Date
Valentin Balaschenko
ec16ea95e6 Merge branch 'develop' into vlntb/refactore-barrier-semaphore 2025-07-15 11:56:41 +01:00
yinyiqian1
8aa94ea09a fixAMMClawbackRounding: adjust last holder's LPToken balance (#5513)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance. This was fixed for `AMMWithdraw` in `fixAMMv1_1` by adjusting the LPTokenBalance to be the same as the trustline balance. Since `AMMClawback` is also performing a withdrawal, we need to adjust LPTokenBalance as well in `AMMClawback.`

This change includes:
1. Refactored `verifyAndAdjustLPTokenBalance` function in `AMMUtils`, which both`AMMWithdraw` and `AMMClawback` call to adjust LPTokenBalance.
2. Added the unit test `testLastHolderLPTokenBalance` to test the scenario.
3. Modify the existing unit tests for `fixAMMClawbackRounding`.
2025-07-11 20:03:28 +00:00
Bronek Kozicki
258ba71363 chore: Add gcc-12 workaround (#5554)
This change silences a dummy warning, which is breaking builds with GCC 12 (but not newer versions of GCC) in release mode only.
2025-07-11 18:57:09 +00:00
Shawn Xie
b8626ea3c6 Add MPT related txns into issuer's account history (#5530)
Currently there is no easy way to track MPT related transactions for the issuer. This change allows MPT transactions to show up on issuer's AccountTx RPC (to align with how IOUs work).
2025-07-11 17:50:03 +00:00
Vlad
6534757d85 chore: Remove unused headers (#5526) 2025-07-10 18:15:42 +00:00
Valentin Balaschenko
8d996904f4 Merge branch 'develop' into vlntb/refactore-barrier-semaphore 2025-07-10 17:48:35 +01:00
Denis Angell
8e94ea3154 fix: add allowTrustLineLocking flag for account_info (#5525)
* Update the `account_info` API so that the `allowTrustLineLocking` flag is included in the response.
* The proposed `TokenEscrow` amendment added an `allowTrustLineLocking` flag in the `AccountRoot` object.
* In the API response, under `account_flags`, there is now an `allowTrustLineLocking` field with a boolean (`true` or `false`) value.
* For reference, the XLS-85 Token-Enabled Escrows implementation can be found in https://github.com/XRPLF/rippled/pull/5185
2025-07-10 16:29:51 +00:00
Valentin Balaschenko
a7abb30fa3 Merge branch 'develop' into vlntb/refactore-barrier-semaphore 2025-07-07 10:40:27 +01:00
Valentin Balaschenko
27b0747889 Merge branch 'develop' into vlntb/refactore-barrier-semaphore 2025-06-25 19:34:10 +01:00
Valentin Balaschenko
2966efd025 move to std counting semaphore 2025-06-25 19:31:27 +01:00
67 changed files with 883 additions and 408 deletions

View File

@@ -25,6 +25,7 @@
#include <cstdint>
#include <cstring>
#include <memory>
namespace ripple {

View File

@@ -29,7 +29,6 @@
#include <array>
#include <cstdint>
#include <optional>
#include <sstream>
#include <string>
namespace ripple {

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_ALGORITHM_H_INCLUDED
#define RIPPLE_ALGORITHM_H_INCLUDED
#include <iterator>
#include <utility>
namespace ripple {

View File

@@ -24,12 +24,8 @@
#include <xrpl/beast/hash/xxhasher.h>
#include <cstdint>
#include <functional>
#include <mutex>
#include <random>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
namespace ripple {

View File

@@ -23,7 +23,6 @@
#include <cstdint>
#include <limits>
#include <optional>
#include <utility>
namespace ripple {
auto constexpr muldiv_max = std::numeric_limits<std::uint64_t>::max();

View File

@@ -24,10 +24,8 @@
#include <boost/operators.hpp>
#include <functional>
#include <iostream>
#include <type_traits>
#include <utility>
namespace ripple {

View File

@@ -20,9 +20,6 @@
#ifndef BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
#define BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
#include <chrono>
#include <string>
namespace beast {
/** Abstract interface to a clock.

View File

@@ -23,6 +23,8 @@
#include <xrpl/beast/clock/abstract_clock.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <chrono>
namespace beast {
/** Manual clock implementation.

View File

@@ -22,6 +22,7 @@
#include <xrpl/beast/container/aged_container.h>
#include <chrono>
#include <type_traits>
namespace beast {

View File

@@ -20,8 +20,6 @@
#ifndef BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
#define BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
#include <type_traits>
namespace beast {
namespace detail {

View File

@@ -33,7 +33,6 @@
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>

View File

@@ -29,11 +29,9 @@
#include <charconv>
#include <cstdlib>
#include <iterator>
#include <limits>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
namespace beast {

View File

@@ -45,7 +45,6 @@ Workaround for overzealous clang warning, which trips on libstdc++ headers
#endif
#include <functional>
#include <memory>
#if defined(__clang__)
#pragma clang diagnostic pop
@@ -53,10 +52,8 @@ Workaround for overzealous clang warning, which trips on libstdc++ headers
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <map>
#include <set>
#include <memory>
#include <string>
#include <system_error>
#include <tuple>

View File

@@ -29,11 +29,7 @@
#include <boost/asio/ip/address.hpp>
#include <boost/functional/hash.hpp>
#include <cstdint>
#include <ios>
#include <sstream>
#include <string>
#include <typeinfo>
//------------------------------------------------------------------------------

View File

@@ -24,12 +24,6 @@
#include <boost/asio/ip/address_v4.hpp>
#include <cstdint>
#include <functional>
#include <ios>
#include <string>
#include <utility>
namespace beast {
namespace IP {

View File

@@ -24,12 +24,6 @@
#include <boost/asio/ip/address_v6.hpp>
#include <cstdint>
#include <functional>
#include <ios>
#include <string>
#include <utility>
namespace beast {
namespace IP {

View File

@@ -25,7 +25,6 @@
#include <xrpl/beast/net/IPAddress.h>
#include <cstdint>
#include <ios>
#include <optional>
#include <string>

View File

@@ -28,10 +28,8 @@
#include <algorithm>
#include <cctype>
#include <cstdint>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
namespace beast {

View File

@@ -13,7 +13,6 @@
#include <boost/optional.hpp>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
#include <vector>

View File

@@ -16,7 +16,6 @@
#include <algorithm>
#include <chrono>
#include <functional>
#include <iomanip>
#include <iostream>
#include <sstream>

View File

@@ -13,7 +13,6 @@
#include <boost/assert.hpp>
#include <mutex>
#include <ostream>
#include <string>
namespace beast {

View File

@@ -48,8 +48,10 @@ rngfill(void* buffer, std::size_t bytes, Generator& g)
#ifdef __GNUC__
// gcc 11.1 (falsely) warns about an array-bounds overflow in release mode.
// gcc 12.1 (also falsely) warns about an string overflow in release mode.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
if (bytes > 0)

View File

@@ -26,7 +26,6 @@
#include <cstring>
#include <map>
#include <string>
#include <utility>
#include <vector>
/** \brief JSON (JavaScript Object Notation).

View File

@@ -29,7 +29,6 @@
#include <xrpl/protocol/json_get_or_throw.h>
#include <cstddef>
#include <mutex>
#include <optional>
#include <string>

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
#define RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
#include <functional>
#include <type_traits>
#include <utility>

View File

@@ -24,7 +24,6 @@
#include <boost/container/flat_map.hpp>
#include <array>
#include <bitset>
#include <map>
#include <optional>

View File

@@ -27,14 +27,9 @@
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/operators.hpp>
#include <cmath>
#include <ios>
#include <iosfwd>
#include <limits>
#include <optional>
#include <sstream>
#include <string>
#include <utility>
namespace ripple {

View File

@@ -32,6 +32,7 @@
#include <xrpl/protocol/jss.h>
#include <cstdint>
#include <set>
namespace ripple {

View File

@@ -24,9 +24,6 @@
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/UintTypes.h>
#include <functional>
#include <type_traits>
namespace ripple {
/** A currency issued by an account.

View File

@@ -28,7 +28,6 @@
#include <concepts>
#include <cstdlib>
#include <functional>
#include <limits>
#include <type_traits>
#include <utility>

View File

@@ -25,7 +25,6 @@
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
namespace ripple {
/**

View File

@@ -32,7 +32,6 @@
#include <cstring>
#include <optional>
#include <ostream>
#include <utility>
namespace ripple {

View File

@@ -25,7 +25,6 @@
#include <functional>
#include <initializer_list>
#include <memory>
#include <stdexcept>
namespace ripple {

View File

@@ -24,7 +24,6 @@
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/Serializer.h>
#include <memory>
#include <ostream>
#include <string>
#include <type_traits>

View File

@@ -27,7 +27,6 @@
#include <xrpl/protocol/STBase.h>
#include <cstring>
#include <memory>
namespace ripple {

View File

@@ -28,8 +28,6 @@
#include <xrpl/protocol/SecretKey.h>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <sstream>

View File

@@ -33,7 +33,6 @@
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <type_traits>
namespace ripple {

View File

@@ -25,8 +25,6 @@
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/SecretKey.h>
#include <utility>
namespace ripple {
/** Sign an STObject

View File

@@ -35,8 +35,6 @@
#include <boost/container/vector.hpp>
#include <cstddef>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace ripple {

View File

@@ -27,7 +27,6 @@
#include <boost/outcome.hpp>
#include <boost/outcome/result.hpp>
#include <cinttypes>
#include <span>
#include <system_error>
#include <tuple>

View File

@@ -35,6 +35,7 @@
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FIX (AMMClawbackRounding, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -25,7 +25,6 @@
#include <boost/endian/conversion.hpp>
#include <algorithm>
#include <array>
namespace ripple {

View File

@@ -10,7 +10,6 @@
#include <charconv>
#include <exception>
#include <optional>
#include <string>
namespace Json {
struct JsonMissingKeyError : std::exception

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_RESOURCE_CHARGE_H_INCLUDED
#define RIPPLE_RESOURCE_CHARGE_H_INCLUDED
#include <ios>
#include <string>
namespace ripple {

View File

@@ -22,6 +22,8 @@
#include <xrpl/beast/net/IPEndpoint.h>
#include <vector>
namespace ripple {
namespace Resource {

View File

@@ -41,7 +41,6 @@
#include <functional>
#include <memory>
#include <mutex>
#include <type_traits>
#include <vector>
namespace ripple {

View File

@@ -37,10 +37,8 @@
#include <boost/container/flat_map.hpp>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
namespace ripple {

View File

@@ -26,7 +26,6 @@
#include <functional>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <type_traits>
#include <utility>

View File

@@ -185,6 +185,18 @@ TxMeta::getAffectedAccounts() const
{
auto issuer = lim->getIssuer();
if (issuer.isNonZero())
list.insert(issuer);
}
}
else if (field.getFName() == sfMPTokenIssuanceID)
{
auto mptID =
dynamic_cast<STBitString<192> const*>(&field);
if (mptID != nullptr)
{
auto issuer = MPTIssue(mptID->value()).getIssuer();
if (issuer.isNonZero())
list.insert(issuer);
}

File diff suppressed because it is too large Load Diff

View File

@@ -99,40 +99,6 @@ class TxQPosNegFlows_test : public beast::unit_test::suite
return calcMedFeeLevel(feeLevel, feeLevel);
}
static std::unique_ptr<Config>
makeConfig(
std::map<std::string, std::string> extraTxQ = {},
std::map<std::string, std::string> extraVoting = {})
{
auto p = test::jtx::envconfig();
auto& section = p->section("transaction_queue");
section.set("ledgers_in_queue", "2");
section.set("minimum_queue_size", "2");
section.set("min_ledgers_to_compute_size_limit", "3");
section.set("max_ledger_counts_to_store", "100");
section.set("retry_sequence_percent", "25");
section.set("normal_consensus_increase_percent", "0");
for (auto const& [k, v] : extraTxQ)
section.set(k, v);
// Some tests specify different fee settings that are enabled by
// a FeeVote
if (!extraVoting.empty())
{
auto& votingSection = p->section("voting");
for (auto const& [k, v] : extraVoting)
{
votingSection.set(k, v);
}
// In order for the vote to occur, we must run as a validator
p->section("validation_seed")
.legacy("shUwVw52ofnCUX5m7kPTKzJdr4HEH");
}
return p;
}
std::size_t
initFee(
jtx::Env& env,

View File

@@ -127,6 +127,11 @@ addGrpcConfigWithSecureGateway(
std::unique_ptr<Config>,
std::string const& secureGateway);
std::unique_ptr<Config>
makeConfig(
std::map<std::string, std::string> extraTxQ = {},
std::map<std::string, std::string> extraVoting = {});
} // namespace jtx
} // namespace test
} // namespace ripple

View File

@@ -140,6 +140,39 @@ addGrpcConfigWithSecureGateway(
return cfg;
}
std::unique_ptr<Config>
makeConfig(
std::map<std::string, std::string> extraTxQ,
std::map<std::string, std::string> extraVoting)
{
auto p = test::jtx::envconfig();
auto& section = p->section("transaction_queue");
section.set("ledgers_in_queue", "2");
section.set("minimum_queue_size", "2");
section.set("min_ledgers_to_compute_size_limit", "3");
section.set("max_ledger_counts_to_store", "100");
section.set("retry_sequence_percent", "25");
section.set("normal_consensus_increase_percent", "0");
for (auto const& [k, v] : extraTxQ)
section.set(k, v);
// Some tests specify different fee settings that are enabled by
// a FeeVote
if (!extraVoting.empty())
{
auto& votingSection = p->section("voting");
for (auto const& [k, v] : extraVoting)
{
votingSection.set(k, v);
}
// In order for the vote to occur, we must run as a validator
p->section("validation_seed").legacy("shUwVw52ofnCUX5m7kPTKzJdr4HEH");
}
return p;
}
} // namespace jtx
} // namespace test
} // namespace ripple

View File

@@ -675,6 +675,30 @@ public:
BEAST_EXPECT(
!getAccountFlag(allowTrustLineClawbackFlag.first, bob));
}
static constexpr std::pair<std::string_view, std::uint32_t>
allowTrustLineLockingFlag{
"allowTrustLineLocking", asfAllowTrustLineLocking};
if (features[featureTokenEscrow])
{
auto const f1 =
getAccountFlag(allowTrustLineLockingFlag.first, bob);
BEAST_EXPECT(f1.has_value());
BEAST_EXPECT(!f1.value());
// Set allowTrustLineLocking
env(fset(bob, allowTrustLineLockingFlag.second));
env.close();
auto const f2 =
getAccountFlag(allowTrustLineLockingFlag.first, bob);
BEAST_EXPECT(f2.has_value());
BEAST_EXPECT(f2.value());
}
else
{
BEAST_EXPECT(!getAccountFlag(allowTrustLineLockingFlag.first, bob));
}
}
void
@@ -691,6 +715,9 @@ public:
testAccountFlags(allFeatures - featureDisallowIncoming);
testAccountFlags(
allFeatures - featureDisallowIncoming - featureClawback);
testAccountFlags(
allFeatures - featureDisallowIncoming - featureClawback -
featureTokenEscrow);
}
};

View File

@@ -18,9 +18,12 @@
//==============================================================================
#include <test/jtx.h>
#include <test/jtx/envconfig.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/jss.h>
#include <boost/container/flat_set.hpp>
@@ -753,6 +756,85 @@ class AccountTx_test : public beast::unit_test::suite
}
}
void
testMPT()
{
testcase("MPT");
using namespace test::jtx;
using namespace std::chrono_literals;
auto cfg = makeConfig();
cfg->FEES.reference_fee = 10;
Env env(*this, std::move(cfg));
Account const alice{"alice"};
Account const bob{"bob"};
Account const carol{"carol"};
MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
// check the latest mpt-related txn is in alice's account history
auto const checkAliceAcctTx = [&](size_t size,
Json::StaticString txType) {
Json::Value params;
params[jss::account] = alice.human();
params[jss::limit] = 100;
auto const jv =
env.rpc("json", "account_tx", to_string(params))[jss::result];
BEAST_EXPECT(jv[jss::transactions].size() == size);
auto const& tx0(jv[jss::transactions][0u][jss::tx]);
BEAST_EXPECT(tx0[jss::TransactionType] == txType);
std::string const txHash{
env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
BEAST_EXPECT(tx0[jss::hash] == txHash);
};
// alice creates issuance
mptAlice.create(
{.ownerCount = 1,
.holderCount = 0,
.flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer});
checkAliceAcctTx(3, jss::MPTokenIssuanceCreate);
// bob creates a MPToken;
mptAlice.authorize({.account = bob});
checkAliceAcctTx(4, jss::MPTokenAuthorize);
env.close();
// TODO: windows pipeline fails validation for the hardcoded ledger hash
// due to having different test config, it can be uncommented after
// figuring out what happened
//
// ledger hash should be fixed regardless any change to account history
// BEAST_EXPECT(
// to_string(env.closed()->info().hash) ==
// "0BD507BB87D3C0E73B462485E6E381798A8C82FC49BF17FE39C60E08A1AF035D");
// alice authorizes bob
mptAlice.authorize({.account = alice, .holder = bob});
checkAliceAcctTx(5, jss::MPTokenAuthorize);
// carol creates a MPToken;
mptAlice.authorize({.account = carol});
checkAliceAcctTx(6, jss::MPTokenAuthorize);
// alice authorizes carol
mptAlice.authorize({.account = alice, .holder = carol});
checkAliceAcctTx(7, jss::MPTokenAuthorize);
// alice pays bob 100 tokens
mptAlice.pay(alice, bob, 100);
checkAliceAcctTx(8, jss::Payment);
// bob pays carol 10 tokens
mptAlice.pay(bob, carol, 10);
checkAliceAcctTx(9, jss::Payment);
}
public:
void
run() override
@@ -761,6 +843,7 @@ public:
std::bind_front(&AccountTx_test::testParameters, this));
testContents();
testAccountDelete();
testMPT();
}
};
BEAST_DEFINE_TESTSUITE(AccountTx, rpc, ripple);

View File

@@ -125,6 +125,17 @@ isOnlyLiquidityProvider(
Issue const& ammIssue,
AccountID const& lpAccount);
/** Due to rounding, the LPTokenBalance of the last LP might
* not match the LP's trustline balance. If it's within the tolerance,
* update LPTokenBalance to match the LP's trustline balance.
*/
Expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
std::shared_ptr<SLE>& ammSle,
AccountID const& account);
} // namespace ripple
#endif // RIPPLE_APP_MISC_AMMUTILS_H_INCLUDED

View File

@@ -27,6 +27,7 @@
#include <xrpl/beast/container/aged_unordered_map.h>
#include <optional>
#include <set>
namespace ripple {

View File

@@ -17,6 +17,7 @@
*/
//==============================================================================
#include <xrpld/app/misc/AMMHelpers.h>
#include <xrpld/app/misc/AMMUtils.h>
#include <xrpld/ledger/Sandbox.h>
@@ -464,4 +465,32 @@ isOnlyLiquidityProvider(
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
}
Expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
std::shared_ptr<SLE>& ammSle,
AccountID const& account)
{
if (auto const res = isOnlyLiquidityProvider(sb, lpTokens.issue(), account);
!res)
return Unexpected<TER>(res.error());
else if (res.value())
{
if (withinRelativeDistance(
lpTokens,
ammSle->getFieldAmount(sfLPTokenBalance),
Number{1, -3}))
{
ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
sb.update(ammSle);
}
else
{
return Unexpected<TER>(tecAMM_INVALID_TOKENS);
}
}
return true;
}
} // namespace ripple

View File

@@ -151,6 +151,20 @@ AMMClawback::applyGuts(Sandbox& sb)
if (!accountSle)
return tecINTERNAL; // LCOV_EXCL_LINE
if (sb.rules().enabled(fixAMMClawbackRounding))
{
// retrieve LP token balance inside the amendment gate to avoid
// inconsistent error behavior
auto const lpTokenBalance = ammLPHolds(sb, *ammSle, holder, j_);
if (lpTokenBalance == beast::zero)
return tecAMM_BALANCE;
if (auto const res = verifyAndAdjustLPTokenBalance(
sb, lpTokenBalance, ammSle, holder);
!res)
return res.error(); // LCOV_EXCL_LINE
}
auto const expected = ammHolds(
sb,
*ammSle,
@@ -248,10 +262,11 @@ AMMClawback::equalWithdrawMatchingOneAmount(
STAmount const& amount)
{
auto frac = Number{amount} / amountBalance;
auto const amount2Withdraw = amount2Balance * frac;
auto amount2Withdraw = amount2Balance * frac;
auto const lpTokensWithdraw =
toSTAmount(lptAMMBalance.issue(), lptAMMBalance * frac);
if (lpTokensWithdraw > holdLPtokens)
// if lptoken balance less than what the issuer intended to clawback,
// clawback all the tokens. Because we are doing a two-asset withdrawal,
@@ -272,6 +287,42 @@ AMMClawback::equalWithdrawMatchingOneAmount(
mPriorBalance,
ctx_.journal);
auto const& rules = sb.rules();
if (rules.enabled(fixAMMClawbackRounding))
{
auto tokensAdj =
getRoundedLPTokens(rules, lptAMMBalance, frac, IsDeposit::No);
// LCOV_EXCL_START
if (tokensAdj == beast::zero)
return {
tecAMM_INVALID_TOKENS, STAmount{}, STAmount{}, std::nullopt};
// LCOV_EXCL_STOP
frac = adjustFracByTokens(rules, lptAMMBalance, tokensAdj, frac);
auto amount2Rounded =
getRoundedAsset(rules, amount2Balance, frac, IsDeposit::No);
auto amountRounded =
getRoundedAsset(rules, amountBalance, frac, IsDeposit::No);
return AMMWithdraw::withdraw(
sb,
ammSle,
ammAccount,
holder,
amountBalance,
amountRounded,
amount2Rounded,
lptAMMBalance,
tokensAdj,
0,
FreezeHandling::fhIGNORE_FREEZE,
WithdrawAll::No,
mPriorBalance,
ctx_.journal);
}
// Because we are doing a two-asset withdrawal,
// tfee is actually not used, so pass tfee as 0.
return AMMWithdraw::withdraw(

View File

@@ -311,24 +311,9 @@ AMMWithdraw::applyGuts(Sandbox& sb)
if (sb.rules().enabled(fixAMMv1_1))
{
if (auto const res =
isOnlyLiquidityProvider(sb, lpTokens.issue(), account_);
verifyAndAdjustLPTokenBalance(sb, lpTokens, ammSle, account_);
!res)
return {res.error(), false};
else if (res.value())
{
if (withinRelativeDistance(
lpTokens,
ammSle->getFieldAmount(sfLPTokenBalance),
Number{1, -3}))
{
ammSle->setFieldAmount(sfLPTokenBalance, lpTokens);
sb.update(ammSle);
}
else
{
return {tecAMM_INVALID_TOKENS, false};
}
}
}
auto const tfee = getTradingFee(ctx_.view(), *ammSle, account_);

View File

@@ -30,6 +30,8 @@
#include <boost/coroutine/all.hpp>
#include <set>
namespace ripple {
namespace perf {

View File

@@ -104,7 +104,7 @@ Workers::setNumberOfThreads(int numberOfThreads)
++m_pauseCount;
// Pausing a thread counts as one "internal task"
m_semaphore.notify();
m_semaphore.release();
}
}
@@ -128,7 +128,7 @@ Workers::stop()
void
Workers::addTask()
{
m_semaphore.notify();
m_semaphore.release();
}
int
@@ -213,7 +213,7 @@ Workers::Worker::run()
// Acquire a task or "internal task."
//
m_workers.m_semaphore.wait();
m_workers.m_semaphore.acquire();
// See if there's a pause request. This
// counts as an "internal task."

View File

@@ -20,13 +20,12 @@
#ifndef RIPPLE_CORE_WORKERS_H_INCLUDED
#define RIPPLE_CORE_WORKERS_H_INCLUDED
#include <xrpld/core/detail/semaphore.h>
#include <xrpl/beast/core/LockFreeStack.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <semaphore>
#include <string>
#include <thread>
@@ -223,10 +222,10 @@ private:
std::condition_variable m_cv; // signaled when all threads paused
std::mutex m_mut;
bool m_allPaused;
semaphore m_semaphore; // each pending task is 1 resource
int m_numberOfThreads; // how many we want active now
std::atomic<int> m_activeCount; // to know when all are paused
std::atomic<int> m_pauseCount; // how many threads need to pause now
std::counting_semaphore<> m_semaphore; // each pending task is 1 resource
int m_numberOfThreads; // how many we want active now
std::atomic<int> m_activeCount; // to know when all are paused
std::atomic<int> m_pauseCount; // how many threads need to pause now
std::atomic<int>
m_runningTaskCount; // how many calls to processTask() active
beast::LockFreeStack<Worker> m_everyone; // holds all created workers

View File

@@ -1,83 +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_CORE_SEMAPHORE_H_INCLUDED
#define RIPPLE_CORE_SEMAPHORE_H_INCLUDED
#include <condition_variable>
#include <mutex>
namespace ripple {
template <class Mutex, class CondVar>
class basic_semaphore
{
private:
Mutex m_mutex;
CondVar m_cond;
std::size_t m_count;
public:
using size_type = std::size_t;
/** Create the semaphore, with an optional initial count.
If unspecified, the initial count is zero.
*/
explicit basic_semaphore(size_type count = 0) : m_count(count)
{
}
/** Increment the count and unblock one waiting thread. */
void
notify()
{
std::lock_guard lock{m_mutex};
++m_count;
m_cond.notify_one();
}
/** Block until notify is called. */
void
wait()
{
std::unique_lock lock{m_mutex};
while (m_count == 0)
m_cond.wait(lock);
--m_count;
}
/** Perform a non-blocking wait.
@return `true` If the wait would be satisfied.
*/
bool
try_wait()
{
std::lock_guard lock{m_mutex};
if (m_count == 0)
return false;
--m_count;
return true;
}
};
using semaphore = basic_semaphore<std::mutex, std::condition_variable>;
} // namespace ripple
#endif

View File

@@ -27,7 +27,6 @@
#include <xrpl/protocol/AccountID.h>
#include <map>
#include <utility>
namespace ripple {

View File

@@ -108,6 +108,10 @@ doAccountInfo(RPC::JsonContext& context)
allowTrustLineClawbackFlag{
"allowTrustLineClawback", lsfAllowTrustLineClawback};
static constexpr std::pair<std::string_view, LedgerSpecificFlags>
allowTrustLineLockingFlag{
"allowTrustLineLocking", lsfAllowTrustLineLocking};
auto const sleAccepted = ledger->read(keylet::account(accountID));
if (sleAccepted)
{
@@ -140,6 +144,10 @@ doAccountInfo(RPC::JsonContext& context)
acctFlags[allowTrustLineClawbackFlag.first.data()] =
sleAccepted->isFlag(allowTrustLineClawbackFlag.second);
if (ledger->rules().enabled(featureTokenEscrow))
acctFlags[allowTrustLineLockingFlag.first.data()] =
sleAccepted->isFlag(allowTrustLineLockingFlag.second);
result[jss::account_flags] = std::move(acctFlags);
// The document[https://xrpl.org/account_info.html#account_info] states

View File

@@ -36,6 +36,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <set>
#include <stack>
#include <vector>