mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'ripple/wamr' into ripple/wamr-host-functions
This commit is contained in:
@@ -188,14 +188,14 @@ enum LedgerSpecificFlags {
|
|||||||
lsfMPTCanTransfer = 0x00000020,
|
lsfMPTCanTransfer = 0x00000020,
|
||||||
lsfMPTCanClawback = 0x00000040,
|
lsfMPTCanClawback = 0x00000040,
|
||||||
|
|
||||||
lmfMPTCanMutateCanLock = 0x00000002,
|
lsmfMPTCanMutateCanLock = 0x00000002,
|
||||||
lmfMPTCanMutateRequireAuth = 0x00000004,
|
lsmfMPTCanMutateRequireAuth = 0x00000004,
|
||||||
lmfMPTCanMutateCanEscrow = 0x00000008,
|
lsmfMPTCanMutateCanEscrow = 0x00000008,
|
||||||
lmfMPTCanMutateCanTrade = 0x00000010,
|
lsmfMPTCanMutateCanTrade = 0x00000010,
|
||||||
lmfMPTCanMutateCanTransfer = 0x00000020,
|
lsmfMPTCanMutateCanTransfer = 0x00000020,
|
||||||
lmfMPTCanMutateCanClawback = 0x00000040,
|
lsmfMPTCanMutateCanClawback = 0x00000040,
|
||||||
lmfMPTCanMutateMetadata = 0x00010000,
|
lsmfMPTCanMutateMetadata = 0x00010000,
|
||||||
lmfMPTCanMutateTransferFee = 0x00020000,
|
lsmfMPTCanMutateTransferFee = 0x00020000,
|
||||||
|
|
||||||
// ltMPTOKEN
|
// ltMPTOKEN
|
||||||
lsfMPTAuthorized = 0x00000002,
|
lsfMPTAuthorized = 0x00000002,
|
||||||
|
|||||||
@@ -156,14 +156,14 @@ constexpr std::uint32_t const tfMPTokenIssuanceCreateMask =
|
|||||||
|
|
||||||
// MPTokenIssuanceCreate MutableFlags:
|
// MPTokenIssuanceCreate MutableFlags:
|
||||||
// Indicating specific fields or flags may be changed after issuance.
|
// Indicating specific fields or flags may be changed after issuance.
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanLock = lmfMPTCanMutateCanLock;
|
constexpr std::uint32_t const tmfMPTCanMutateCanLock = lsmfMPTCanMutateCanLock;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateRequireAuth = lmfMPTCanMutateRequireAuth;
|
constexpr std::uint32_t const tmfMPTCanMutateRequireAuth = lsmfMPTCanMutateRequireAuth;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanEscrow = lmfMPTCanMutateCanEscrow;
|
constexpr std::uint32_t const tmfMPTCanMutateCanEscrow = lsmfMPTCanMutateCanEscrow;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanTrade = lmfMPTCanMutateCanTrade;
|
constexpr std::uint32_t const tmfMPTCanMutateCanTrade = lsmfMPTCanMutateCanTrade;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanTransfer = lmfMPTCanMutateCanTransfer;
|
constexpr std::uint32_t const tmfMPTCanMutateCanTransfer = lsmfMPTCanMutateCanTransfer;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanClawback = lmfMPTCanMutateCanClawback;
|
constexpr std::uint32_t const tmfMPTCanMutateCanClawback = lsmfMPTCanMutateCanClawback;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateMetadata = lmfMPTCanMutateMetadata;
|
constexpr std::uint32_t const tmfMPTCanMutateMetadata = lsmfMPTCanMutateMetadata;
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateTransferFee = lmfMPTCanMutateTransferFee;
|
constexpr std::uint32_t const tmfMPTCanMutateTransferFee = lsmfMPTCanMutateTransferFee;
|
||||||
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask =
|
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask =
|
||||||
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow | tmfMPTCanMutateCanTrade
|
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow | tmfMPTCanMutateCanTrade
|
||||||
| tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
|
| tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo
|
|||||||
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(PermissionDelegation, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionDelegation, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
// Check flags in Credential transactions
|
// Check flags in Credential transactions
|
||||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
|
|||||||
@@ -30,15 +30,29 @@
|
|||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/beast/core/detect_ssl.hpp>
|
#include <boost/beast/core/detect_ssl.hpp>
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/core/tcp_stream.hpp>
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
#include <boost/container/flat_map.hpp>
|
#include <boost/container/flat_map.hpp>
|
||||||
|
#include <boost/predef.h>
|
||||||
|
|
||||||
|
#if !BOOST_OS_WINDOWS
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -98,10 +112,27 @@ private:
|
|||||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||||
bool ssl_;
|
bool ssl_;
|
||||||
bool plain_;
|
bool plain_;
|
||||||
|
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
|
||||||
|
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
|
||||||
|
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
|
||||||
|
boost::asio::steady_timer backoff_timer_;
|
||||||
|
static constexpr double FREE_FD_THRESHOLD = 0.70;
|
||||||
|
|
||||||
|
struct FDStats
|
||||||
|
{
|
||||||
|
std::uint64_t used{0};
|
||||||
|
std::uint64_t limit{0};
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
reOpen();
|
reOpen();
|
||||||
|
|
||||||
|
std::optional<FDStats>
|
||||||
|
query_fd_stats() const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
should_throttle_for_fds();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Door(
|
Door(
|
||||||
Handler& handler,
|
Handler& handler,
|
||||||
@@ -299,6 +330,7 @@ Door<Handler>::Door(
|
|||||||
, plain_(
|
, plain_(
|
||||||
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
|
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
|
||||||
port_.protocol.count("ws2"))
|
port_.protocol.count("ws2"))
|
||||||
|
, backoff_timer_(io_context)
|
||||||
{
|
{
|
||||||
reOpen();
|
reOpen();
|
||||||
}
|
}
|
||||||
@@ -323,6 +355,7 @@ Door<Handler>::close()
|
|||||||
return boost::asio::post(
|
return boost::asio::post(
|
||||||
strand_,
|
strand_,
|
||||||
std::bind(&Door<Handler>::close, this->shared_from_this()));
|
std::bind(&Door<Handler>::close, this->shared_from_this()));
|
||||||
|
backoff_timer_.cancel();
|
||||||
error_code ec;
|
error_code ec;
|
||||||
acceptor_.close(ec);
|
acceptor_.close(ec);
|
||||||
}
|
}
|
||||||
@@ -368,6 +401,17 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
|||||||
{
|
{
|
||||||
while (acceptor_.is_open())
|
while (acceptor_.is_open())
|
||||||
{
|
{
|
||||||
|
if (should_throttle_for_fds())
|
||||||
|
{
|
||||||
|
backoff_timer_.expires_after(accept_delay_);
|
||||||
|
boost::system::error_code tec;
|
||||||
|
backoff_timer_.async_wait(do_yield[tec]);
|
||||||
|
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
|
||||||
|
JLOG(j_.warn()) << "Throttling do_accept for "
|
||||||
|
<< accept_delay_.count() << "ms.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
endpoint_type remote_address;
|
endpoint_type remote_address;
|
||||||
stream_type stream(ioc_);
|
stream_type stream(ioc_);
|
||||||
@@ -377,15 +421,28 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
|||||||
{
|
{
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
break;
|
break;
|
||||||
JLOG(j_.error()) << "accept: " << ec.message();
|
|
||||||
if (ec == boost::asio::error::no_descriptors)
|
if (ec == boost::asio::error::no_descriptors ||
|
||||||
|
ec == boost::asio::error::no_buffer_space)
|
||||||
{
|
{
|
||||||
JLOG(j_.info()) << "re-opening acceptor";
|
JLOG(j_.warn()) << "accept: Too many open files. Pausing for "
|
||||||
reOpen();
|
<< accept_delay_.count() << "ms.";
|
||||||
|
|
||||||
|
backoff_timer_.expires_after(accept_delay_);
|
||||||
|
boost::system::error_code tec;
|
||||||
|
backoff_timer_.async_wait(do_yield[tec]);
|
||||||
|
|
||||||
|
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JLOG(j_.error()) << "accept error: " << ec.message();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accept_delay_ = INITIAL_ACCEPT_DELAY;
|
||||||
|
|
||||||
if (ssl_ && plain_)
|
if (ssl_ && plain_)
|
||||||
{
|
{
|
||||||
if (auto sp = ios().template emplace<Detector>(
|
if (auto sp = ios().template emplace<Detector>(
|
||||||
@@ -408,6 +465,60 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Handler>
|
||||||
|
std::optional<typename Door<Handler>::FDStats>
|
||||||
|
Door<Handler>::query_fd_stats() const
|
||||||
|
{
|
||||||
|
#if BOOST_OS_WINDOWS
|
||||||
|
return std::nullopt;
|
||||||
|
#else
|
||||||
|
FDStats s;
|
||||||
|
struct rlimit rl;
|
||||||
|
if (getrlimit(RLIMIT_NOFILE, &rl) != 0 || rl.rlim_cur == RLIM_INFINITY)
|
||||||
|
return std::nullopt;
|
||||||
|
s.limit = static_cast<std::uint64_t>(rl.rlim_cur);
|
||||||
|
#if BOOST_OS_LINUX
|
||||||
|
constexpr char const* kFdDir = "/proc/self/fd";
|
||||||
|
#else
|
||||||
|
constexpr char const* kFdDir = "/dev/fd";
|
||||||
|
#endif
|
||||||
|
if (DIR* d = ::opendir(kFdDir))
|
||||||
|
{
|
||||||
|
std::uint64_t cnt = 0;
|
||||||
|
while (::readdir(d) != nullptr)
|
||||||
|
++cnt;
|
||||||
|
::closedir(d);
|
||||||
|
// readdir counts '.', '..', and the DIR* itself shows in the list
|
||||||
|
s.used = (cnt >= 3) ? (cnt - 3) : 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Handler>
|
||||||
|
bool
|
||||||
|
Door<Handler>::should_throttle_for_fds()
|
||||||
|
{
|
||||||
|
#if BOOST_OS_WINDOWS
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
auto const stats = query_fd_stats();
|
||||||
|
if (!stats || stats->limit == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const& s = *stats;
|
||||||
|
auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull;
|
||||||
|
double const free_ratio =
|
||||||
|
static_cast<double>(free) / static_cast<double>(s.limit);
|
||||||
|
if (free_ratio < FREE_FD_THRESHOLD)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3126,7 +3126,7 @@ rippleUnlockEscrowMPT(
|
|||||||
{ // LCOV_EXCL_START
|
{ // LCOV_EXCL_START
|
||||||
JLOG(j.error())
|
JLOG(j.error())
|
||||||
<< "rippleUnlockEscrowMPT: MPToken not found for " << receiver;
|
<< "rippleUnlockEscrowMPT: MPToken not found for " << receiver;
|
||||||
return tecOBJECT_NOT_FOUND; // LCOV_EXCL_LINE
|
return tecOBJECT_NOT_FOUND;
|
||||||
} // LCOV_EXCL_STOP
|
} // LCOV_EXCL_STOP
|
||||||
|
|
||||||
auto current = sle->getFieldU64(sfMPTAmount);
|
auto current = sle->getFieldU64(sfMPTAmount);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace BuildInfo {
|
|||||||
// and follow the format described at http://semver.org/
|
// and follow the format described at http://semver.org/
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// clang-format off
|
// clang-format off
|
||||||
char const* const versionString = "2.6.1-rc1"
|
char const* const versionString = "2.6.1"
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(SANITIZER)
|
#if defined(DEBUG) || defined(SANITIZER)
|
||||||
|
|||||||
@@ -51,14 +51,18 @@ struct MPTMutabilityFlags
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr std::array<MPTMutabilityFlags, 6> mptMutabilityFlags = {
|
static constexpr std::array<MPTMutabilityFlags, 6> mptMutabilityFlags = {
|
||||||
{{tmfMPTSetCanLock, tmfMPTClearCanLock, lmfMPTCanMutateCanLock},
|
{{tmfMPTSetCanLock, tmfMPTClearCanLock, lsmfMPTCanMutateCanLock},
|
||||||
{tmfMPTSetRequireAuth, tmfMPTClearRequireAuth, lmfMPTCanMutateRequireAuth},
|
{tmfMPTSetRequireAuth,
|
||||||
{tmfMPTSetCanEscrow, tmfMPTClearCanEscrow, lmfMPTCanMutateCanEscrow},
|
tmfMPTClearRequireAuth,
|
||||||
{tmfMPTSetCanTrade, tmfMPTClearCanTrade, lmfMPTCanMutateCanTrade},
|
lsmfMPTCanMutateRequireAuth},
|
||||||
{tmfMPTSetCanTransfer, tmfMPTClearCanTransfer, lmfMPTCanMutateCanTransfer},
|
{tmfMPTSetCanEscrow, tmfMPTClearCanEscrow, lsmfMPTCanMutateCanEscrow},
|
||||||
|
{tmfMPTSetCanTrade, tmfMPTClearCanTrade, lsmfMPTCanMutateCanTrade},
|
||||||
|
{tmfMPTSetCanTransfer,
|
||||||
|
tmfMPTClearCanTransfer,
|
||||||
|
lsmfMPTCanMutateCanTransfer},
|
||||||
{tmfMPTSetCanClawback,
|
{tmfMPTSetCanClawback,
|
||||||
tmfMPTClearCanClawback,
|
tmfMPTClearCanClawback,
|
||||||
lmfMPTCanMutateCanClawback}}};
|
lsmfMPTCanMutateCanClawback}}};
|
||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
MPTokenIssuanceSet::preflight(PreflightContext const& ctx)
|
MPTokenIssuanceSet::preflight(PreflightContext const& ctx)
|
||||||
@@ -243,7 +247,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx)
|
|||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMutableFlag(lmfMPTCanMutateMetadata) &&
|
if (!isMutableFlag(lsmfMPTCanMutateMetadata) &&
|
||||||
ctx.tx.isFieldPresent(sfMPTokenMetadata))
|
ctx.tx.isFieldPresent(sfMPTokenMetadata))
|
||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
@@ -256,7 +260,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx)
|
|||||||
if (fee > 0u && !sleMptIssuance->isFlag(lsfMPTCanTransfer))
|
if (fee > 0u && !sleMptIssuance->isFlag(lsfMPTCanTransfer))
|
||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
if (!isMutableFlag(lmfMPTCanMutateTransferFee))
|
if (!isMutableFlag(lsmfMPTCanMutateTransferFee))
|
||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -660,14 +660,15 @@ Transactor::apply()
|
|||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkSign(
|
Transactor::checkSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
|
ApplyFlags flags,
|
||||||
AccountID const& idAccount,
|
AccountID const& idAccount,
|
||||||
STObject const& sigObject)
|
STObject const& sigObject,
|
||||||
|
beast::Journal const j)
|
||||||
{
|
{
|
||||||
auto const pkSigner = sigObject.getFieldVL(sfSigningPubKey);
|
auto const pkSigner = sigObject.getFieldVL(sfSigningPubKey);
|
||||||
// Ignore signature check on batch inner transactions
|
// Ignore signature check on batch inner transactions
|
||||||
if (sigObject.isFlag(tfInnerBatchTxn) &&
|
if (sigObject.isFlag(tfInnerBatchTxn) && view.rules().enabled(featureBatch))
|
||||||
ctx.view.rules().enabled(featureBatch))
|
|
||||||
{
|
{
|
||||||
// Defensive Check: These values are also checked in Batch::preflight
|
// Defensive Check: These values are also checked in Batch::preflight
|
||||||
if (sigObject.isFieldPresent(sfTxnSignature) || !pkSigner.empty() ||
|
if (sigObject.isFieldPresent(sfTxnSignature) || !pkSigner.empty() ||
|
||||||
@@ -678,7 +679,7 @@ Transactor::checkSign(
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ctx.flags & tapDRY_RUN) && pkSigner.empty() &&
|
if ((flags & tapDRY_RUN) && pkSigner.empty() &&
|
||||||
!sigObject.isFieldPresent(sfSigners))
|
!sigObject.isFieldPresent(sfSigners))
|
||||||
{
|
{
|
||||||
// simulate: skip signature validation when neither SigningPubKey nor
|
// simulate: skip signature validation when neither SigningPubKey nor
|
||||||
@@ -688,9 +689,9 @@ Transactor::checkSign(
|
|||||||
|
|
||||||
// If the pk is empty and not simulate or simulate and signers,
|
// If the pk is empty and not simulate or simulate and signers,
|
||||||
// then we must be multi-signing.
|
// then we must be multi-signing.
|
||||||
if (ctx.tx.isFieldPresent(sfSigners))
|
if (sigObject.isFieldPresent(sfSigners))
|
||||||
{
|
{
|
||||||
return checkMultiSign(ctx, idAccount, sigObject);
|
return checkMultiSign(view, flags, idAccount, sigObject, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Single Sign
|
// Check Single Sign
|
||||||
@@ -699,7 +700,7 @@ Transactor::checkSign(
|
|||||||
|
|
||||||
if (!publicKeyType(makeSlice(pkSigner)))
|
if (!publicKeyType(makeSlice(pkSigner)))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace()) << "checkSign: signing public key type is unknown";
|
JLOG(j.trace()) << "checkSign: signing public key type is unknown";
|
||||||
return tefBAD_AUTH; // FIXME: should be better error!
|
return tefBAD_AUTH; // FIXME: should be better error!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,11 +708,11 @@ Transactor::checkSign(
|
|||||||
auto const idSigner = pkSigner.empty()
|
auto const idSigner = pkSigner.empty()
|
||||||
? idAccount
|
? idAccount
|
||||||
: calcAccountID(PublicKey(makeSlice(pkSigner)));
|
: calcAccountID(PublicKey(makeSlice(pkSigner)));
|
||||||
auto const sleAccount = ctx.view.read(keylet::account(idAccount));
|
auto const sleAccount = view.read(keylet::account(idAccount));
|
||||||
if (!sleAccount)
|
if (!sleAccount)
|
||||||
return terNO_ACCOUNT;
|
return terNO_ACCOUNT;
|
||||||
|
|
||||||
return checkSingleSign(ctx, idSigner, idAccount, sleAccount);
|
return checkSingleSign(view, idSigner, idAccount, sleAccount, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
@@ -720,7 +721,7 @@ Transactor::checkSign(PreclaimContext const& ctx)
|
|||||||
auto const idAccount = ctx.tx.isFieldPresent(sfDelegate)
|
auto const idAccount = ctx.tx.isFieldPresent(sfDelegate)
|
||||||
? ctx.tx.getAccountID(sfDelegate)
|
? ctx.tx.getAccountID(sfDelegate)
|
||||||
: ctx.tx.getAccountID(sfAccount);
|
: ctx.tx.getAccountID(sfAccount);
|
||||||
return checkSign(ctx, idAccount, ctx.tx);
|
return checkSign(ctx.view, ctx.flags, idAccount, ctx.tx, ctx.j);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
@@ -735,7 +736,8 @@ Transactor::checkBatchSign(PreclaimContext const& ctx)
|
|||||||
Blob const& pkSigner = signer.getFieldVL(sfSigningPubKey);
|
Blob const& pkSigner = signer.getFieldVL(sfSigningPubKey);
|
||||||
if (pkSigner.empty())
|
if (pkSigner.empty())
|
||||||
{
|
{
|
||||||
if (ret = checkMultiSign(ctx, idAccount, signer);
|
if (ret = checkMultiSign(
|
||||||
|
ctx.view, ctx.flags, idAccount, signer, ctx.j);
|
||||||
!isTesSuccess(ret))
|
!isTesSuccess(ret))
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -759,7 +761,8 @@ Transactor::checkBatchSign(PreclaimContext const& ctx)
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret = checkSingleSign(ctx, idSigner, idAccount, sleAccount);
|
if (ret = checkSingleSign(
|
||||||
|
ctx.view, idSigner, idAccount, sleAccount, ctx.j);
|
||||||
!isTesSuccess(ret))
|
!isTesSuccess(ret))
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -769,14 +772,15 @@ Transactor::checkBatchSign(PreclaimContext const& ctx)
|
|||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkSingleSign(
|
Transactor::checkSingleSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
AccountID const& idSigner,
|
AccountID const& idSigner,
|
||||||
AccountID const& idAccount,
|
AccountID const& idAccount,
|
||||||
std::shared_ptr<SLE const> sleAccount)
|
std::shared_ptr<SLE const> sleAccount,
|
||||||
|
beast::Journal const j)
|
||||||
{
|
{
|
||||||
bool const isMasterDisabled = sleAccount->isFlag(lsfDisableMaster);
|
bool const isMasterDisabled = sleAccount->isFlag(lsfDisableMaster);
|
||||||
|
|
||||||
if (ctx.view.rules().enabled(fixMasterKeyAsRegularKey))
|
if (view.rules().enabled(fixMasterKeyAsRegularKey))
|
||||||
{
|
{
|
||||||
// Signed with regular key.
|
// Signed with regular key.
|
||||||
if ((*sleAccount)[~sfRegularKey] == idSigner)
|
if ((*sleAccount)[~sfRegularKey] == idSigner)
|
||||||
@@ -813,16 +817,14 @@ Transactor::checkSingleSign(
|
|||||||
else if (sleAccount->isFieldPresent(sfRegularKey))
|
else if (sleAccount->isFieldPresent(sfRegularKey))
|
||||||
{
|
{
|
||||||
// Signing key does not match master or regular key.
|
// Signing key does not match master or regular key.
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace()) << "checkSingleSign: Not authorized to use account.";
|
||||||
<< "checkSingleSign: Not authorized to use account.";
|
|
||||||
return tefBAD_AUTH;
|
return tefBAD_AUTH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No regular key on account and signing key does not match master key.
|
// No regular key on account and signing key does not match master key.
|
||||||
// FIXME: Why differentiate this case from tefBAD_AUTH?
|
// FIXME: Why differentiate this case from tefBAD_AUTH?
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace()) << "checkSingleSign: Not authorized to use account.";
|
||||||
<< "checkSingleSign: Not authorized to use account.";
|
|
||||||
return tefBAD_AUTH_MASTER;
|
return tefBAD_AUTH_MASTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,17 +833,19 @@ Transactor::checkSingleSign(
|
|||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkMultiSign(
|
Transactor::checkMultiSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
|
ApplyFlags flags,
|
||||||
AccountID const& id,
|
AccountID const& id,
|
||||||
STObject const& sigObject)
|
STObject const& sigObject,
|
||||||
|
beast::Journal const j)
|
||||||
{
|
{
|
||||||
// Get id's SignerList and Quorum.
|
// Get id's SignerList and Quorum.
|
||||||
std::shared_ptr<STLedgerEntry const> sleAccountSigners =
|
std::shared_ptr<STLedgerEntry const> sleAccountSigners =
|
||||||
ctx.view.read(keylet::signers(id));
|
view.read(keylet::signers(id));
|
||||||
// If the signer list doesn't exist the account is not multi-signing.
|
// If the signer list doesn't exist the account is not multi-signing.
|
||||||
if (!sleAccountSigners)
|
if (!sleAccountSigners)
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Invalid: Not a multi-signing account.";
|
<< "applyTransaction: Invalid: Not a multi-signing account.";
|
||||||
return tefNOT_MULTI_SIGNING;
|
return tefNOT_MULTI_SIGNING;
|
||||||
}
|
}
|
||||||
@@ -856,7 +860,7 @@ Transactor::checkMultiSign(
|
|||||||
"ripple::Transactor::checkMultiSign : signer list ID is 0");
|
"ripple::Transactor::checkMultiSign : signer list ID is 0");
|
||||||
|
|
||||||
auto accountSigners =
|
auto accountSigners =
|
||||||
SignerEntries::deserialize(*sleAccountSigners, ctx.j, "ledger");
|
SignerEntries::deserialize(*sleAccountSigners, j, "ledger");
|
||||||
if (!accountSigners)
|
if (!accountSigners)
|
||||||
return accountSigners.error();
|
return accountSigners.error();
|
||||||
|
|
||||||
@@ -880,7 +884,7 @@ Transactor::checkMultiSign(
|
|||||||
{
|
{
|
||||||
if (++iter == accountSigners->end())
|
if (++iter == accountSigners->end())
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Invalid SigningAccount.Account.";
|
<< "applyTransaction: Invalid SigningAccount.Account.";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
@@ -888,7 +892,7 @@ Transactor::checkMultiSign(
|
|||||||
if (iter->account != txSignerAcctID)
|
if (iter->account != txSignerAcctID)
|
||||||
{
|
{
|
||||||
// The SigningAccount is not in the SignerEntries.
|
// The SigningAccount is not in the SignerEntries.
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Invalid SigningAccount.Account.";
|
<< "applyTransaction: Invalid SigningAccount.Account.";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
@@ -902,13 +906,13 @@ Transactor::checkMultiSign(
|
|||||||
// STTx::checkMultiSign
|
// STTx::checkMultiSign
|
||||||
if (!spk.empty() && !publicKeyType(makeSlice(spk)))
|
if (!spk.empty() && !publicKeyType(makeSlice(spk)))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "checkMultiSign: signing public key type is unknown";
|
<< "checkMultiSign: signing public key type is unknown";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
(ctx.flags & tapDRY_RUN) || !spk.empty(),
|
(flags & tapDRY_RUN) || !spk.empty(),
|
||||||
"ripple::Transactor::checkMultiSign : non-empty signer or "
|
"ripple::Transactor::checkMultiSign : non-empty signer or "
|
||||||
"simulation");
|
"simulation");
|
||||||
AccountID const signingAcctIDFromPubKey = spk.empty()
|
AccountID const signingAcctIDFromPubKey = spk.empty()
|
||||||
@@ -940,8 +944,7 @@ Transactor::checkMultiSign(
|
|||||||
|
|
||||||
// In any of these cases we need to know whether the account is in
|
// In any of these cases we need to know whether the account is in
|
||||||
// the ledger. Determine that now.
|
// the ledger. Determine that now.
|
||||||
auto const sleTxSignerRoot =
|
auto const sleTxSignerRoot = view.read(keylet::account(txSignerAcctID));
|
||||||
ctx.view.read(keylet::account(txSignerAcctID));
|
|
||||||
|
|
||||||
if (signingAcctIDFromPubKey == txSignerAcctID)
|
if (signingAcctIDFromPubKey == txSignerAcctID)
|
||||||
{
|
{
|
||||||
@@ -954,7 +957,7 @@ Transactor::checkMultiSign(
|
|||||||
|
|
||||||
if (signerAccountFlags & lsfDisableMaster)
|
if (signerAccountFlags & lsfDisableMaster)
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Signer:Account lsfDisableMaster.";
|
<< "applyTransaction: Signer:Account lsfDisableMaster.";
|
||||||
return tefMASTER_DISABLED;
|
return tefMASTER_DISABLED;
|
||||||
}
|
}
|
||||||
@@ -966,21 +969,21 @@ Transactor::checkMultiSign(
|
|||||||
// Public key must hash to the account's regular key.
|
// Public key must hash to the account's regular key.
|
||||||
if (!sleTxSignerRoot)
|
if (!sleTxSignerRoot)
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace()) << "applyTransaction: Non-phantom signer "
|
JLOG(j.trace()) << "applyTransaction: Non-phantom signer "
|
||||||
"lacks account root.";
|
"lacks account root.";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sleTxSignerRoot->isFieldPresent(sfRegularKey))
|
if (!sleTxSignerRoot->isFieldPresent(sfRegularKey))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Account lacks RegularKey.";
|
<< "applyTransaction: Account lacks RegularKey.";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
if (signingAcctIDFromPubKey !=
|
if (signingAcctIDFromPubKey !=
|
||||||
sleTxSignerRoot->getAccountID(sfRegularKey))
|
sleTxSignerRoot->getAccountID(sfRegularKey))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace())
|
||||||
<< "applyTransaction: Account doesn't match RegularKey.";
|
<< "applyTransaction: Account doesn't match RegularKey.";
|
||||||
return tefBAD_SIGNATURE;
|
return tefBAD_SIGNATURE;
|
||||||
}
|
}
|
||||||
@@ -992,8 +995,7 @@ Transactor::checkMultiSign(
|
|||||||
// Cannot perform transaction if quorum is not met.
|
// Cannot perform transaction if quorum is not met.
|
||||||
if (weightSum < sleAccountSigners->getFieldU32(sfSignerQuorum))
|
if (weightSum < sleAccountSigners->getFieldU32(sfSignerQuorum))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(j.trace()) << "applyTransaction: Signers failed to meet quorum.";
|
||||||
<< "applyTransaction: Signers failed to meet quorum.";
|
|
||||||
return tefBAD_QUORUM;
|
return tefBAD_QUORUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -283,9 +283,11 @@ protected:
|
|||||||
|
|
||||||
static NotTEC
|
static NotTEC
|
||||||
checkSign(
|
checkSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
AccountID const& id,
|
ApplyFlags flags,
|
||||||
STObject const& sigObject);
|
AccountID const& idAccount,
|
||||||
|
STObject const& sigObject,
|
||||||
|
beast::Journal const j);
|
||||||
|
|
||||||
// Base class always returns true
|
// Base class always returns true
|
||||||
static bool
|
static bool
|
||||||
@@ -323,15 +325,18 @@ private:
|
|||||||
payFee();
|
payFee();
|
||||||
static NotTEC
|
static NotTEC
|
||||||
checkSingleSign(
|
checkSingleSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
AccountID const& idSigner,
|
AccountID const& idSigner,
|
||||||
AccountID const& idAccount,
|
AccountID const& idAccount,
|
||||||
std::shared_ptr<SLE const> sleAccount);
|
std::shared_ptr<SLE const> sleAccount,
|
||||||
|
beast::Journal const j);
|
||||||
static NotTEC
|
static NotTEC
|
||||||
checkMultiSign(
|
checkMultiSign(
|
||||||
PreclaimContext const& ctx,
|
ReadView const& view,
|
||||||
|
ApplyFlags flags,
|
||||||
AccountID const& id,
|
AccountID const& id,
|
||||||
STObject const& sigObject);
|
STObject const& sigObject,
|
||||||
|
beast::Journal const j);
|
||||||
|
|
||||||
void trapTransaction(uint256) const;
|
void trapTransaction(uint256) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user