mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-05 11:32:26 +00:00
Compare commits
26 Commits
copilot/co
...
3.2.0-b3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6a09a4d2c | ||
|
|
3adad49c86 | ||
|
|
f04943fc50 | ||
|
|
ab7f683b2f | ||
|
|
14749fdfb0 | ||
|
|
c6ddf6aa1c | ||
|
|
ee3a08c8d4 | ||
|
|
2dc705bd99 | ||
|
|
7315c57edc | ||
|
|
5a66086fce | ||
|
|
682dda8bfc | ||
|
|
aac17f588a | ||
|
|
cbc09b2999 | ||
|
|
453d94da17 | ||
|
|
b36aedb4d5 | ||
|
|
18540c97a5 | ||
|
|
8e3d87fce3 | ||
|
|
b83dc9aa16 | ||
|
|
0c76bf991a | ||
|
|
29aba28f5b | ||
|
|
b3f14c4052 | ||
|
|
e26624dcd1 | ||
|
|
885f7b8c33 | ||
|
|
dcf973bc50 | ||
|
|
68596f60d8 | ||
|
|
aac64d3b85 |
@@ -10,7 +10,6 @@
|
||||
#include <cctype>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
@@ -182,7 +181,7 @@ split_commas(FwdIt first, FwdIt last)
|
||||
|
||||
template <class Result = std::vector<std::string>>
|
||||
Result
|
||||
split_commas(std::string_view const& s)
|
||||
split_commas(boost::beast::string_view const& s)
|
||||
{
|
||||
return split_commas(s.begin(), s.end());
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class Value;
|
||||
|
||||
using Output = std::function<void(std::string_view const&)>;
|
||||
using Output = std::function<void(boost::beast::string_view const&)>;
|
||||
|
||||
inline Output
|
||||
stringOutput(std::string& s)
|
||||
{
|
||||
return [&](std::string_view const& b) { s.append(b.data(), b.size()); };
|
||||
return [&](boost::beast::string_view const& b) { s.append(b.data(), b.size()); };
|
||||
}
|
||||
|
||||
/** Writes a minimal representation of a Json value to an Output in O(n) time.
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -49,7 +48,8 @@ private:
|
||||
bool ping_active_ = false;
|
||||
boost::beast::websocket::ping_data payload_;
|
||||
error_code ec_;
|
||||
std::function<void(boost::beast::websocket::frame_type, std::string_view)> control_callback_;
|
||||
std::function<void(boost::beast::websocket::frame_type, boost::beast::string_view)>
|
||||
control_callback_;
|
||||
|
||||
public:
|
||||
template <class Body, class Headers>
|
||||
@@ -137,7 +137,7 @@ protected:
|
||||
on_ping(error_code const& ec);
|
||||
|
||||
void
|
||||
on_ping_pong(boost::beast::websocket::frame_type kind, std::string_view payload);
|
||||
on_ping_pong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload);
|
||||
|
||||
void
|
||||
on_timer(error_code ec);
|
||||
@@ -414,11 +414,11 @@ template <class Handler, class Impl>
|
||||
void
|
||||
BaseWSPeer<Handler, Impl>::on_ping_pong(
|
||||
boost::beast::websocket::frame_type kind,
|
||||
std::string_view payload)
|
||||
boost::beast::string_view payload)
|
||||
{
|
||||
if (kind == boost::beast::websocket::frame_type::pong)
|
||||
{
|
||||
std::string_view const p(payload_.begin(), payload_.size());
|
||||
boost::beast::string_view const p(payload_.begin());
|
||||
if (payload == p)
|
||||
{
|
||||
close_on_timer_ = false;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -88,14 +87,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
output(std::string_view const& bytes)
|
||||
output(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
output_(bytes);
|
||||
}
|
||||
|
||||
void
|
||||
stringOutput(std::string_view const& bytes)
|
||||
stringOutput(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
std::size_t position = 0, writtenUntil = 0;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace {
|
||||
// and follow the format described at http://semver.org/
|
||||
//------------------------------------------------------------------------------
|
||||
// clang-format off
|
||||
char const* const versionString = "3.2.0-b0"
|
||||
char const* const versionString = "3.2.0-b3"
|
||||
// clang-format on
|
||||
;
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
|
||||
if (!vault)
|
||||
return tecNO_ENTRY;
|
||||
|
||||
auto const amount = ctx.tx[sfAmount];
|
||||
auto const assets = ctx.tx[sfAmount];
|
||||
auto const vaultAsset = vault->at(sfAsset);
|
||||
auto const vaultShare = vault->at(sfShareMPTID);
|
||||
if (amount.asset() != vaultAsset && amount.asset() != vaultShare)
|
||||
if (assets.asset() != vaultAsset && assets.asset() != vaultShare)
|
||||
return tecWRONG_ASSET;
|
||||
|
||||
auto const& vaultAccount = vault->at(sfAccount);
|
||||
@@ -67,53 +67,8 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
if (ctx.view.rules().enabled(fixSecurity3_1_3) && amount.asset() == vaultShare)
|
||||
{
|
||||
// Post-fixSecurity3_1_3: if the user specified shares, convert
|
||||
// to the equivalent asset amount before checking withdrawal
|
||||
// limits. Pre-amendment the limit check was skipped for
|
||||
// share-denominated withdrawals.
|
||||
auto const sleIssuance = ctx.view.read(keylet::mptIssuance(vaultShare));
|
||||
if (!sleIssuance)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(ctx.j.error()) << "VaultWithdraw: missing issuance of vault shares.";
|
||||
return tefINTERNAL;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto const maybeAssets = sharesToAssetsWithdraw(vault, sleIssuance, amount);
|
||||
if (!maybeAssets)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
if (auto const ret = canWithdraw(
|
||||
ctx.view,
|
||||
account,
|
||||
dstAcct,
|
||||
*maybeAssets,
|
||||
ctx.tx.isFieldPresent(sfDestinationTag)))
|
||||
return ret;
|
||||
}
|
||||
catch (std::overflow_error const&)
|
||||
{
|
||||
// It's easy to hit this exception from Number with large enough Scale
|
||||
// so we avoid spamming the log and only use debug here.
|
||||
JLOG(ctx.j.debug()) //
|
||||
<< "VaultWithdraw: overflow error with"
|
||||
<< " scale=" << (int)vault->at(sfScale) //
|
||||
<< ", assetsTotal=" << vault->at(sfAssetsTotal)
|
||||
<< ", sharesTotal=" << sleIssuance->at(sfOutstandingAmount)
|
||||
<< ", amount=" << amount.value();
|
||||
return tecPATH_DRY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto const ret = canWithdraw(ctx.view, ctx.tx))
|
||||
return ret;
|
||||
}
|
||||
if (auto const ret = canWithdraw(ctx.view, ctx.tx))
|
||||
return ret;
|
||||
|
||||
// If sending to Account (i.e. not a transfer), we will also create (only
|
||||
// if authorized) a trust line or MPToken as needed, in doApply().
|
||||
|
||||
@@ -5231,102 +5231,6 @@ class Vault_test : public beast::unit_test::suite
|
||||
}
|
||||
}
|
||||
|
||||
// Reproduction: canWithdraw IOU limit check bypassed when
|
||||
// withdrawal amount is specified in shares (MPT) rather than in assets.
|
||||
void
|
||||
testBug6_LimitBypassWithShares()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
testcase("Bug6 - limit bypass with share-denominated withdrawal");
|
||||
|
||||
auto const allAmendments = testable_amendments() | featureSingleAssetVault;
|
||||
|
||||
for (auto const& features : {allAmendments, allAmendments - fixSecurity3_1_3})
|
||||
{
|
||||
bool const withFix = features[fixSecurity3_1_3];
|
||||
|
||||
Env env{*this, features};
|
||||
Account const owner{"owner"};
|
||||
Account const issuer{"issuer"};
|
||||
Account const depositor{"depositor"};
|
||||
Account const charlie{"charlie"};
|
||||
Vault const vault{env};
|
||||
|
||||
env.fund(XRP(1000), issuer, owner, depositor, charlie);
|
||||
env(fset(issuer, asfAllowTrustLineClawback));
|
||||
env.close();
|
||||
|
||||
PrettyAsset const asset = issuer["IOU"];
|
||||
env.trust(asset(1000), owner);
|
||||
env.trust(asset(1000), depositor);
|
||||
env(pay(issuer, owner, asset(200)));
|
||||
env(pay(issuer, depositor, asset(200)));
|
||||
env.close();
|
||||
|
||||
// Charlie gets a LOW trustline limit of 5
|
||||
env.trust(asset(5), charlie);
|
||||
env.close();
|
||||
|
||||
auto const [tx, keylet] = vault.create({.owner = owner, .asset = asset});
|
||||
env(tx);
|
||||
env.close();
|
||||
|
||||
auto const depositTx =
|
||||
vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)});
|
||||
env(depositTx);
|
||||
env.close();
|
||||
|
||||
// Get the share MPT info
|
||||
auto const vaultSle = env.le(keylet);
|
||||
if (!BEAST_EXPECT(vaultSle))
|
||||
return;
|
||||
auto const mptIssuanceID = vaultSle->at(sfShareMPTID);
|
||||
MPTIssue const shares(mptIssuanceID);
|
||||
PrettyAsset const share(shares);
|
||||
|
||||
// CONTROL: Withdraw 10 IOU (asset-denominated) to charlie.
|
||||
// Charlie's limit is 5, so this should be rejected with tecNO_LINE
|
||||
// regardless of the amendment.
|
||||
{
|
||||
auto withdrawTx =
|
||||
vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(10)});
|
||||
withdrawTx[sfDestination] = charlie.human();
|
||||
env(withdrawTx, ter{tecNO_LINE});
|
||||
env.close();
|
||||
}
|
||||
auto const charlieBalanceBefore = env.balance(charlie, asset.raw().get<Issue>());
|
||||
|
||||
// Withdraw the equivalent amount in shares to charlie.
|
||||
// Post-fix: rejected (tecNO_LINE) because the share amount is
|
||||
// converted to assets and the trustline limit is checked.
|
||||
// Pre-fix: succeeds (tesSUCCESS) because the limit check was
|
||||
// skipped for share-denominated withdrawals.
|
||||
{
|
||||
auto withdrawTx = vault.withdraw(
|
||||
{.depositor = depositor,
|
||||
.id = keylet.key,
|
||||
.amount = STAmount(share, 10'000'000)});
|
||||
withdrawTx[sfDestination] = charlie.human();
|
||||
env(withdrawTx, ter{withFix ? TER{tecNO_LINE} : TER{tesSUCCESS}});
|
||||
env.close();
|
||||
|
||||
auto const charlieBalanceAfter = env.balance(charlie, asset.raw().get<Issue>());
|
||||
if (withFix)
|
||||
{
|
||||
// Post-fix: charlie's balance is unchanged — the withdrawal
|
||||
// was correctly rejected despite being share-denominated.
|
||||
BEAST_EXPECT(charlieBalanceAfter == charlieBalanceBefore);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pre-fix: charlie received the assets, bypassing the
|
||||
// trustline limit.
|
||||
BEAST_EXPECT(charlieBalanceAfter > charlieBalanceBefore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
@@ -5347,7 +5251,6 @@ public:
|
||||
testVaultClawbackBurnShares();
|
||||
testVaultClawbackAssets();
|
||||
testAssetsMaximum();
|
||||
testBug6_LimitBypassWithShares();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ to_string(ProtocolVersion const& p)
|
||||
}
|
||||
|
||||
std::vector<ProtocolVersion>
|
||||
parseProtocolVersions(std::string_view const& value)
|
||||
parseProtocolVersions(boost::beast::string_view const& value)
|
||||
{
|
||||
static boost::regex const re(
|
||||
"^" // start of line
|
||||
@@ -126,7 +126,7 @@ negotiateProtocolVersion(std::vector<ProtocolVersion> const& versions)
|
||||
}
|
||||
|
||||
std::optional<ProtocolVersion>
|
||||
negotiateProtocolVersion(std::string_view const& versions)
|
||||
negotiateProtocolVersion(boost::beast::string_view const& versions)
|
||||
{
|
||||
auto const them = parseProtocolVersions(versions);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -38,7 +39,7 @@ to_string(ProtocolVersion const& p);
|
||||
no duplicates and will be sorted in ascending protocol order.
|
||||
*/
|
||||
std::vector<ProtocolVersion>
|
||||
parseProtocolVersions(std::string_view const& s);
|
||||
parseProtocolVersions(boost::beast::string_view const& s);
|
||||
|
||||
/** Given a list of supported protocol versions, choose the one we prefer. */
|
||||
std::optional<ProtocolVersion>
|
||||
@@ -46,7 +47,7 @@ negotiateProtocolVersion(std::vector<ProtocolVersion> const& versions);
|
||||
|
||||
/** Given a list of supported protocol versions, choose the one we prefer. */
|
||||
std::optional<ProtocolVersion>
|
||||
negotiateProtocolVersion(std::string_view const& versions);
|
||||
negotiateProtocolVersion(boost::beast::string_view const& versions);
|
||||
|
||||
/** The list of all the protocol versions we support. */
|
||||
std::string const&
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -230,7 +229,7 @@ ServerHandler::onHandoff(
|
||||
static inline Json::Output
|
||||
makeOutput(Session& session)
|
||||
{
|
||||
return [&](std::string_view const& b) { session.write(b.data(), b.size()); };
|
||||
return [&](boost::beast::string_view const& b) { session.write(b.data(), b.size()); };
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string>
|
||||
@@ -531,14 +530,11 @@ ServerHandler::processSession(
|
||||
makeOutput(*session),
|
||||
coro,
|
||||
forwardedFor(session->request()),
|
||||
[&]() -> std::string_view {
|
||||
[&] {
|
||||
auto const iter = session->request().find("X-User");
|
||||
if (iter != session->request().end())
|
||||
{
|
||||
auto const val = iter->value();
|
||||
return std::string_view(val.data(), val.size());
|
||||
}
|
||||
return std::string_view{};
|
||||
return iter->value();
|
||||
return boost::beast::string_view{};
|
||||
}());
|
||||
|
||||
if (beast::rfc2616::is_keep_alive(session->request()))
|
||||
|
||||
Reference in New Issue
Block a user