Rearrange sources

This commit is contained in:
Pretty Printer
2025-06-17 19:16:40 +09:00
committed by tequ
parent 6b5a7ec905
commit 6c1bc9052d
1035 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_AMMCORE_H_INCLUDED
#define RIPPLE_PROTOCOL_AMMCORE_H_INCLUDED
#include <ripple/basics/Number.h>
#include <ripple/protocol/AccountID.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/TER.h>
#include <ripple/protocol/UintTypes.h>
namespace ripple {
std::uint16_t constexpr TRADING_FEE_THRESHOLD = 1000; // 1%
// Auction slot
std::uint32_t constexpr TOTAL_TIME_SLOT_SECS = 24 * 3600;
std::uint16_t constexpr AUCTION_SLOT_TIME_INTERVALS = 20;
std::uint16_t constexpr AUCTION_SLOT_MAX_AUTH_ACCOUNTS = 4;
std::uint32_t constexpr AUCTION_SLOT_FEE_SCALE_FACTOR = 100000;
std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION = 10;
std::uint32_t constexpr AUCTION_SLOT_MIN_FEE_FRACTION = 25;
std::uint32_t constexpr AUCTION_SLOT_INTERVAL_DURATION =
TOTAL_TIME_SLOT_SECS / AUCTION_SLOT_TIME_INTERVALS;
// Votes
std::uint16_t constexpr VOTE_MAX_SLOTS = 8;
std::uint32_t constexpr VOTE_WEIGHT_SCALE_FACTOR = 100000;
class STObject;
class STAmount;
class Rules;
/** Calculate AMM account ID.
*/
AccountID
ammAccountID(
std::uint16_t prefix,
uint256 const& parentHash,
uint256 const& ammID);
/** Calculate Liquidity Provider Token (LPT) Currency.
*/
Currency
ammLPTCurrency(Currency const& cur1, Currency const& cur2);
/** Calculate LPT Issue from AMM asset pair.
*/
Issue
ammLPTIssue(
Currency const& cur1,
Currency const& cur2,
AccountID const& ammAccountID);
/** Validate the amount.
* If validZero is false and amount is beast::zero then invalid amount.
* Return error code if invalid amount.
* If pair then validate amount's issue matches one of the pair's issue.
*/
NotTEC
invalidAMMAmount(
STAmount const& amount,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt,
bool validZero = false);
NotTEC
invalidAMMAsset(
Issue const& issue,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
NotTEC
invalidAMMAssetPair(
Issue const& issue1,
Issue const& issue2,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
/** Get time slot of the auction slot.
*/
std::optional<std::uint8_t>
ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot);
/** Return true if required AMM amendments are enabled
*/
bool
ammEnabled(Rules const&);
/** Convert to the fee from the basis points
* @param tfee trading fee in {0, 1000}
* 1 = 1/10bps or 0.001%, 1000 = 1%
*/
inline Number
getFee(std::uint16_t tfee)
{
return Number{tfee} / AUCTION_SLOT_FEE_SCALE_FACTOR;
}
/** Get fee multiplier (1 - tfee)
* @tfee trading fee in basis points
*/
inline Number
feeMult(std::uint16_t tfee)
{
return 1 - getFee(tfee);
}
/** Get fee multiplier (1 - tfee / 2)
* @tfee trading fee in basis points
*/
inline Number
feeMultHalf(std::uint16_t tfee)
{
return 1 - getFee(tfee) / 2;
}
} // namespace ripple
#endif // RIPPLE_PROTOCOL_AMMCORE_H_INCLUDED

View File

@@ -0,0 +1,157 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2014 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_PROTOCOL_ACCOUNTID_H_INCLUDED
#define RIPPLE_PROTOCOL_ACCOUNTID_H_INCLUDED
#include <ripple/protocol/tokens.h>
// VFALCO Uncomment when the header issues are resolved
//#include <ripple/protocol/PublicKey.h>
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/basics/base_uint.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/json_get_or_throw.h>
#include <cstddef>
#include <mutex>
#include <optional>
#include <string>
namespace ripple {
namespace detail {
class AccountIDTag
{
public:
explicit AccountIDTag() = default;
};
} // namespace detail
/** A 160-bit unsigned that uniquely identifies an account. */
using AccountID = base_uint<160, detail::AccountIDTag>;
/** Convert AccountID to base58 checked string */
std::string
toBase58(AccountID const& v);
/** Parse AccountID from checked, base58 string.
@return std::nullopt if a parse error occurs
*/
template <>
std::optional<AccountID>
parseBase58(std::string const& s);
/** Compute AccountID from public key.
The account ID is computed as the 160-bit hash of the
public key data. This excludes the version byte and
guard bytes included in the base58 representation.
*/
// VFALCO In PublicKey.h for now
// AccountID
// calcAccountID (PublicKey const& pk);
/** A special account that's used as the "issuer" for XRP. */
AccountID const&
xrpAccount();
/** A placeholder for empty accounts. */
AccountID const&
noAccount();
/** Convert hex or base58 string to AccountID.
@return `true` if the parsing was successful.
*/
// DEPRECATED
bool
to_issuer(AccountID&, std::string const&);
// DEPRECATED Should be checking the currency or native flag
inline bool
isXRP(AccountID const& c)
{
return c == beast::zero;
}
// DEPRECATED
inline std::string
to_string(AccountID const& account)
{
return toBase58(account);
}
// DEPRECATED
inline std::ostream&
operator<<(std::ostream& os, AccountID const& x)
{
os << to_string(x);
return os;
}
/** Initialize the global cache used to map AccountID to base58 conversions.
The cache is optional and need not be initialized. But because conversion
is expensive (it requires a SHA-256 operation) in most cases the overhead
of the cache is worth the benefit.
@param count The number of entries the cache should accomodate. Zero will
disable the cache, releasing any memory associated with it.
@note The function will only initialize the cache the first time it is
invoked. Subsequent invocations do nothing.
*/
void
initAccountIdCache(std::size_t count);
} // namespace ripple
//------------------------------------------------------------------------------
namespace Json {
template <>
inline ripple::AccountID
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
std::string const b58 = getOrThrow<std::string>(v, field);
if (auto const r = parseBase58<AccountID>(b58))
return *r;
Throw<JsonTypeMismatchError>(field.getJsonName(), "AccountID");
}
} // namespace Json
//------------------------------------------------------------------------------
namespace std {
// DEPRECATED
// VFALCO Use beast::uhash or a hardened container
template <>
struct hash<ripple::AccountID> : ripple::AccountID::hasher
{
explicit hash() = default;
};
} // namespace std
#endif

View File

@@ -0,0 +1,220 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_AMOUNTCONVERSION_H_INCLUDED
#define RIPPLE_PROTOCOL_AMOUNTCONVERSION_H_INCLUDED
#include <ripple/basics/IOUAmount.h>
#include <ripple/basics/XRPAmount.h>
#include <ripple/protocol/STAmount.h>
#include <type_traits>
namespace ripple {
inline STAmount
toSTAmount(IOUAmount const& iou, Issue const& iss)
{
bool const isNeg = iou.signum() < 0;
std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa();
return STAmount(
iss,
umant,
iou.exponent(),
/*native*/ false,
isNeg,
STAmount::unchecked());
}
inline STAmount
toSTAmount(IOUAmount const& iou)
{
return toSTAmount(iou, noIssue());
}
inline STAmount
toSTAmount(XRPAmount const& xrp)
{
bool const isNeg = xrp.signum() < 0;
std::uint64_t const umant = isNeg ? -xrp.drops() : xrp.drops();
return STAmount(umant, isNeg);
}
inline STAmount
toSTAmount(XRPAmount const& xrp, Issue const& iss)
{
assert(isXRP(iss.account) && isXRP(iss.currency));
return toSTAmount(xrp);
}
template <class T>
T
toAmount(STAmount const& amt) = delete;
template <>
inline STAmount
toAmount<STAmount>(STAmount const& amt)
{
return amt;
}
template <>
inline IOUAmount
toAmount<IOUAmount>(STAmount const& amt)
{
assert(amt.mantissa() < std::numeric_limits<std::int64_t>::max());
bool const isNeg = amt.negative();
std::int64_t const sMant =
isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
assert(!isXRP(amt));
return IOUAmount(sMant, amt.exponent());
}
template <>
inline XRPAmount
toAmount<XRPAmount>(STAmount const& amt)
{
assert(amt.mantissa() < std::numeric_limits<std::int64_t>::max());
bool const isNeg = amt.negative();
std::int64_t const sMant =
isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
assert(isXRP(amt));
return XRPAmount(sMant);
}
template <class T>
T
toAmount(IOUAmount const& amt) = delete;
template <>
inline IOUAmount
toAmount<IOUAmount>(IOUAmount const& amt)
{
return amt;
}
template <class T>
T
toAmount(XRPAmount const& amt) = delete;
template <>
inline XRPAmount
toAmount<XRPAmount>(XRPAmount const& amt)
{
return amt;
}
template <typename T>
T
toAmount(
Issue const& issue,
Number const& n,
Number::rounding_mode mode = Number::getround())
{
saveNumberRoundMode rm(Number::getround());
if (isXRP(issue))
Number::setround(mode);
if constexpr (std::is_same_v<IOUAmount, T>)
return IOUAmount(n);
else if constexpr (std::is_same_v<XRPAmount, T>)
return XRPAmount(static_cast<std::int64_t>(n));
else if constexpr (std::is_same_v<STAmount, T>)
{
if (isXRP(issue))
return STAmount(issue, static_cast<std::int64_t>(n));
return STAmount(issue, n.mantissa(), n.exponent());
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
static_assert(alwaysFalse, "Unsupported type for toAmount");
}
}
template <typename T>
T
toMaxAmount(Issue const& issue)
{
if constexpr (std::is_same_v<IOUAmount, T>)
return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset);
else if constexpr (std::is_same_v<XRPAmount, T>)
return XRPAmount(static_cast<std::int64_t>(STAmount::cMaxNativeN));
else if constexpr (std::is_same_v<STAmount, T>)
{
if (isXRP(issue))
return STAmount(
issue, static_cast<std::int64_t>(STAmount::cMaxNativeN));
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset);
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
static_assert(alwaysFalse, "Unsupported type for toMaxAmount");
}
}
inline STAmount
toSTAmount(
Issue const& issue,
Number const& n,
Number::rounding_mode mode = Number::getround())
{
return toAmount<STAmount>(issue, n, mode);
}
template <typename T>
Issue
getIssue(T const& amt)
{
if constexpr (std::is_same_v<IOUAmount, T>)
return noIssue();
else if constexpr (std::is_same_v<XRPAmount, T>)
return xrpIssue();
else if constexpr (std::is_same_v<STAmount, T>)
return amt.issue();
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
static_assert(alwaysFalse, "Unsupported type for getIssue");
}
}
template <typename T>
constexpr T
get(STAmount const& a)
{
if constexpr (std::is_same_v<IOUAmount, T>)
return a.iou();
else if constexpr (std::is_same_v<XRPAmount, T>)
return a.xrp();
else if constexpr (std::is_same_v<STAmount, T>)
return a;
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
static_assert(alwaysFalse, "Unsupported type for get");
}
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_APIVERSION_H_INCLUDED
#define RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
#include <functional>
#include <type_traits>
#include <utility>
namespace ripple {
/**
* API version numbers used in later API versions
*
* Requests with a version number in the range
* [apiMinimumSupportedVersion, apiMaximumSupportedVersion]
* are supported.
*
* If [beta_rpc_api] is enabled in config, the version numbers
* in the range [apiMinimumSupportedVersion, apiBetaVersion]
* are supported.
*
* Network Requests without explicit version numbers use
* apiVersionIfUnspecified. apiVersionIfUnspecified is 1,
* because all the RPC requests with a version >= 2 must
* explicitly specify the version in the requests.
* Note that apiVersionIfUnspecified will be lower than
* apiMinimumSupportedVersion when we stop supporting API
* version 1.
*
* Command line Requests use apiCommandLineVersion.
*/
namespace RPC {
template <unsigned int Version>
constexpr static std::integral_constant<unsigned, Version> apiVersion = {};
constexpr static auto apiInvalidVersion = apiVersion<0>;
constexpr static auto apiMinimumSupportedVersion = apiVersion<1>;
constexpr static auto apiMaximumSupportedVersion = apiVersion<2>;
constexpr static auto apiVersionIfUnspecified = apiVersion<1>;
constexpr static auto apiCommandLineVersion =
apiVersion<1>; // TODO Bump to 2 later
constexpr static auto apiBetaVersion = apiVersion<3>;
constexpr static auto apiMaximumValidVersion = apiBetaVersion;
static_assert(apiInvalidVersion < apiMinimumSupportedVersion);
static_assert(
apiVersionIfUnspecified >= apiMinimumSupportedVersion &&
apiVersionIfUnspecified <= apiMaximumSupportedVersion);
static_assert(
apiCommandLineVersion >= apiMinimumSupportedVersion &&
apiCommandLineVersion <= apiMaximumSupportedVersion);
static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion);
static_assert(apiBetaVersion >= apiMaximumSupportedVersion);
static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion);
} // namespace RPC
template <unsigned minVer, unsigned maxVer, typename Fn, typename... Args>
void
forApiVersions(Fn const& fn, Args&&... args) requires //
(maxVer >= minVer) && //
(minVer >= RPC::apiMinimumSupportedVersion) && //
(RPC::apiMaximumValidVersion >= maxVer) &&
requires
{
fn(std::integral_constant<unsigned int, minVer>{},
std::forward<Args>(args)...);
fn(std::integral_constant<unsigned int, maxVer>{},
std::forward<Args>(args)...);
}
{
constexpr auto size = maxVer + 1 - minVer;
[&]<std::size_t... offset>(std::index_sequence<offset...>)
{
(((void)fn(
std::integral_constant<unsigned int, minVer + offset>{},
std::forward<Args>(args)...)),
...);
}
(std::make_index_sequence<size>{});
}
template <typename Fn, typename... Args>
void
forAllApiVersions(Fn const& fn, Args&&... args) requires requires
{
forApiVersions<
RPC::apiMinimumSupportedVersion,
RPC::apiMaximumValidVersion>(fn, std::forward<Args>(args)...);
}
{
forApiVersions<
RPC::apiMinimumSupportedVersion,
RPC::apiMaximumValidVersion>(fn, std::forward<Args>(args)...);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,175 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_BOOK_H_INCLUDED
#define RIPPLE_PROTOCOL_BOOK_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/Issue.h>
#include <boost/utility/base_from_member.hpp>
namespace ripple {
/** Specifies an order book.
The order book is a pair of Issues called in and out.
@see Issue.
*/
class Book final : public CountedObject<Book>
{
public:
Issue in;
Issue out;
Book()
{
}
Book(Issue const& in_, Issue const& out_) : in(in_), out(out_)
{
}
};
bool
isConsistent(Book const& book);
std::string
to_string(Book const& book);
std::ostream&
operator<<(std::ostream& os, Book const& x);
template <class Hasher>
void
hash_append(Hasher& h, Book const& b)
{
using beast::hash_append;
hash_append(h, b.in, b.out);
}
Book
reversed(Book const& book);
/** Equality comparison. */
/** @{ */
[[nodiscard]] inline constexpr bool
operator==(Book const& lhs, Book const& rhs)
{
return (lhs.in == rhs.in) && (lhs.out == rhs.out);
}
/** @} */
/** Strict weak ordering. */
/** @{ */
[[nodiscard]] inline constexpr std::weak_ordering
operator<=>(Book const& lhs, Book const& rhs)
{
if (auto const c{lhs.in <=> rhs.in}; c != 0)
return c;
return lhs.out <=> rhs.out;
}
/** @} */
} // namespace ripple
//------------------------------------------------------------------------------
namespace std {
template <>
struct hash<ripple::Issue>
: private boost::base_from_member<std::hash<ripple::Currency>, 0>,
private boost::base_from_member<std::hash<ripple::AccountID>, 1>
{
private:
using currency_hash_type =
boost::base_from_member<std::hash<ripple::Currency>, 0>;
using issuer_hash_type =
boost::base_from_member<std::hash<ripple::AccountID>, 1>;
public:
explicit hash() = default;
using value_type = std::size_t;
using argument_type = ripple::Issue;
value_type
operator()(argument_type const& value) const
{
value_type result(currency_hash_type::member(value.currency));
if (!isXRP(value.currency))
boost::hash_combine(
result, issuer_hash_type::member(value.account));
return result;
}
};
//------------------------------------------------------------------------------
template <>
struct hash<ripple::Book>
{
private:
using hasher = std::hash<ripple::Issue>;
hasher m_hasher;
public:
explicit hash() = default;
using value_type = std::size_t;
using argument_type = ripple::Book;
value_type
operator()(argument_type const& value) const
{
value_type result(m_hasher(value.in));
boost::hash_combine(result, m_hasher(value.out));
return result;
}
};
} // namespace std
//------------------------------------------------------------------------------
namespace boost {
template <>
struct hash<ripple::Issue> : std::hash<ripple::Issue>
{
explicit hash() = default;
using Base = std::hash<ripple::Issue>;
// VFALCO NOTE broken in vs2012
// using Base::Base; // inherit ctors
};
template <>
struct hash<ripple::Book> : std::hash<ripple::Book>
{
explicit hash() = default;
using Base = std::hash<ripple::Book>;
// VFALCO NOTE broken in vs2012
// using Base::Base; // inherit ctors
};
} // namespace boost
#endif

View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_BUILDINFO_H_INCLUDED
#define RIPPLE_PROTOCOL_BUILDINFO_H_INCLUDED
#include <cstdint>
#include <string>
namespace ripple {
/** Versioning information for this build. */
// VFALCO The namespace is deprecated
namespace BuildInfo {
/** Server version.
Follows the Semantic Versioning Specification:
http://semver.org/
*/
std::string const&
getVersionString();
/** Full server version string.
This includes the name of the server. It is used in the peer
protocol hello message and also the headers of some HTTP replies.
*/
std::string const&
getFullVersionString();
/** Encode an arbitrary server software version in a 64-bit integer.
The general format is:
........-........-........-........-........-........-........-........
XXXXXXXX-XXXXXXXX-YYYYYYYY-YYYYYYYY-YYYYYYYY-YYYYYYYY-YYYYYYYY-YYYYYYYY
X: 16 bits identifying the particular implementation
Y: 48 bits of data specific to the implementation
The rippled-specific format (implementation ID is: 0x18 0x3B) is:
00011000-00111011-MMMMMMMM-mmmmmmmm-pppppppp-TTNNNNNN-00000000-00000000
M: 8-bit major version (0-255)
m: 8-bit minor version (0-255)
p: 8-bit patch version (0-255)
T: 11 if neither an RC nor a beta
10 if an RC
01 if a beta
N: 6-bit rc/beta number (1-63)
@param the version string
@return the encoded version in a 64-bit integer
*/
std::uint64_t
encodeSoftwareVersion(char const* versionStr);
/** Returns this server's version packed in a 64-bit integer. */
std::uint64_t
getEncodedVersion();
/** Check if the encoded software version is a rippled software version.
@param version another node's encoded software version
@return true if the version is a rippled software version, false otherwise
*/
bool
isRippledVersion(std::uint64_t version);
/** Check if the version is newer than the local node's rippled software
version.
@param version another node's encoded software version
@return true if the version is newer than the local node's rippled software
version, false otherwise.
@note This function only understands version numbers that are generated by
rippled. Please see the encodeSoftwareVersion() function for detail.
*/
bool
isNewerVersion(std::uint64_t version);
} // namespace BuildInfo
} // namespace ripple
#endif

View File

@@ -0,0 +1,372 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012 - 2019 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_PROTOCOL_ERRORCODES_H_INCLUDED
#define RIPPLE_PROTOCOL_ERRORCODES_H_INCLUDED
#include <ripple/json/json_value.h>
#include <ripple/protocol/jss.h>
namespace ripple {
// VFALCO NOTE These are outside the RPC namespace
// NOTE: Although the precise numeric values of these codes were never
// intended to be stable, several API endpoints include the numeric values.
// Some users came to rely on the values, meaning that renumbering would be
// a breaking change for those users.
//
// We therefore treat the range of values as stable although they are not
// and are subject to change.
//
// Please only append to this table. Do not "fill-in" gaps and do not re-use
// or repurpose error code values.
enum error_code_i {
// -1 represents codes not listed in this enumeration
rpcUNKNOWN = -1,
rpcSUCCESS = 0,
rpcBAD_SYNTAX = 1,
rpcJSON_RPC = 2,
rpcFORBIDDEN = 3,
rpcWRONG_NETWORK = 4,
// Misc failure
// unused 5,
rpcNO_PERMISSION = 6,
rpcNO_EVENTS = 7,
// unused 8,
rpcTOO_BUSY = 9,
rpcSLOW_DOWN = 10,
rpcHIGH_FEE = 11,
rpcNOT_ENABLED = 12,
rpcNOT_READY = 13,
rpcAMENDMENT_BLOCKED = 14,
// Networking
rpcNO_CLOSED = 15,
rpcNO_CURRENT = 16,
rpcNO_NETWORK = 17,
rpcNOT_SYNCED = 18,
// Ledger state
rpcACT_NOT_FOUND = 19,
rpcNAMESPACE_NOT_FOUND = 20,
rpcLGR_NOT_FOUND = 21,
rpcLGR_NOT_VALIDATED = 22,
rpcMASTER_DISABLED = 23,
// unused 24,
// unused 25,
// unused 26,
// unused 27,
// unused 28,
rpcTXN_NOT_FOUND = 29,
rpcINVALID_HOTWALLET = 30,
// Malformed command
rpcINVALID_PARAMS = 31,
rpcUNKNOWN_COMMAND = 32,
rpcNO_PF_REQUEST = 33,
// Bad parameter
// NOT USED DO NOT USE AGAIN rpcACT_BITCOIN = 34,
rpcACT_MALFORMED = 35,
rpcALREADY_MULTISIG = 36,
rpcALREADY_SINGLE_SIG = 37,
rpcNAMESPACE_MALFORMED = 38,
// unused 39,
rpcBAD_FEATURE = 40,
rpcBAD_ISSUER = 41,
rpcBAD_MARKET = 42,
rpcBAD_SECRET = 43,
rpcBAD_SEED = 44,
rpcCHANNEL_MALFORMED = 45,
rpcCHANNEL_AMT_MALFORMED = 46,
rpcCOMMAND_MISSING = 47,
rpcDST_ACT_MALFORMED = 48,
rpcDST_ACT_MISSING = 49,
rpcDST_ACT_NOT_FOUND = 50,
rpcDST_AMT_MALFORMED = 51,
rpcDST_AMT_MISSING = 52,
rpcDST_ISR_MALFORMED = 53,
// unused 54,
// unused 55,
// unused 56,
rpcLGR_IDXS_INVALID = 57,
rpcLGR_IDX_MALFORMED = 58,
// unused 59,
// unused 60,
// unused 61,
rpcPUBLIC_MALFORMED = 62,
rpcSIGNING_MALFORMED = 63,
rpcSENDMAX_MALFORMED = 64,
rpcSRC_ACT_MALFORMED = 65,
rpcSRC_ACT_MISSING = 66,
rpcSRC_ACT_NOT_FOUND = 67,
// unused 68,
rpcSRC_CUR_MALFORMED = 69,
rpcSRC_ISR_MALFORMED = 70,
rpcSTREAM_MALFORMED = 71,
rpcATX_DEPRECATED = 72,
// Internal error (should never happen)
rpcINTERNAL = 73, // Generic internal error.
rpcNOT_IMPL = 74,
rpcNOT_SUPPORTED = 75,
rpcBAD_KEY_TYPE = 76,
rpcDB_DESERIALIZATION = 77,
rpcEXCESSIVE_LGR_RANGE = 78,
rpcINVALID_LGR_RANGE = 79,
rpcEXPIRED_VALIDATOR_LIST = 80,
// Reporting
rpcFAILED_TO_FORWARD = 90,
rpcREPORTING_UNSUPPORTED = 91,
rpcOBJECT_NOT_FOUND = 92,
rpcLEDGER_MISSING = 93,
// AMM
rpcISSUE_MALFORMED = 94,
// Oracle
rpcORACLE_MALFORMED = 95,
rpcLAST =
rpcORACLE_MALFORMED // rpcLAST should always equal the last code.=
};
/** Codes returned in the `warnings` array of certain RPC commands.
These values need to remain stable.
*/
enum warning_code_i {
warnRPC_UNSUPPORTED_MAJORITY = 1001,
warnRPC_AMENDMENT_BLOCKED = 1002,
warnRPC_EXPIRED_VALIDATOR_LIST = 1003,
warnRPC_REPORTING = 1004
};
//------------------------------------------------------------------------------
// VFALCO NOTE these should probably not be in the RPC namespace.
namespace RPC {
/** Maps an rpc error code to its token, default message, and HTTP status. */
struct ErrorInfo
{
// Default ctor needed to produce an empty std::array during constexpr eval.
constexpr ErrorInfo()
: code(rpcUNKNOWN)
, token("unknown")
, message("An unknown error code.")
, http_status(200)
{
}
constexpr ErrorInfo(
error_code_i code_,
char const* token_,
char const* message_)
: code(code_), token(token_), message(message_), http_status(200)
{
}
constexpr ErrorInfo(
error_code_i code_,
char const* token_,
char const* message_,
int http_status_)
: code(code_)
, token(token_)
, message(message_)
, http_status(http_status_)
{
}
error_code_i code;
Json::StaticString token;
Json::StaticString message;
int http_status;
};
/** Returns an ErrorInfo that reflects the error code. */
ErrorInfo const&
get_error_info(error_code_i code);
/** Add or update the json update to reflect the error code. */
/** @{ */
template <class JsonValue>
void
inject_error(error_code_i code, JsonValue& json)
{
ErrorInfo const& info(get_error_info(code));
json[jss::error] = info.token;
json[jss::error_code] = info.code;
json[jss::error_message] = info.message;
}
template <class JsonValue>
void
inject_error(int code, JsonValue& json)
{
inject_error(error_code_i(code), json);
}
template <class JsonValue>
void
inject_error(error_code_i code, std::string const& message, JsonValue& json)
{
ErrorInfo const& info(get_error_info(code));
json[jss::error] = info.token;
json[jss::error_code] = info.code;
json[jss::error_message] = message;
}
/** @} */
/** Returns a new json object that reflects the error code. */
/** @{ */
Json::Value
make_error(error_code_i code);
Json::Value
make_error(error_code_i code, std::string const& message);
/** @} */
/** Returns a new json object that indicates invalid parameters. */
/** @{ */
inline Json::Value
make_param_error(std::string const& message)
{
return make_error(rpcINVALID_PARAMS, message);
}
inline std::string
missing_field_message(std::string const& name)
{
return "Missing field '" + name + "'.";
}
inline Json::Value
missing_field_error(std::string const& name)
{
return make_param_error(missing_field_message(name));
}
inline Json::Value
missing_field_error(Json::StaticString name)
{
return missing_field_error(std::string(name));
}
inline std::string
object_field_message(std::string const& name)
{
return "Invalid field '" + name + "', not object.";
}
inline Json::Value
object_field_error(std::string const& name)
{
return make_param_error(object_field_message(name));
}
inline Json::Value
object_field_error(Json::StaticString name)
{
return object_field_error(std::string(name));
}
inline std::string
invalid_field_message(std::string const& name)
{
return "Invalid field '" + name + "'.";
}
inline std::string
invalid_field_message(Json::StaticString name)
{
return invalid_field_message(std::string(name));
}
inline Json::Value
invalid_field_error(std::string const& name)
{
return make_param_error(invalid_field_message(name));
}
inline Json::Value
invalid_field_error(Json::StaticString name)
{
return invalid_field_error(std::string(name));
}
inline std::string
expected_field_message(std::string const& name, std::string const& type)
{
return "Invalid field '" + name + "', not " + type + ".";
}
inline std::string
expected_field_message(Json::StaticString name, std::string const& type)
{
return expected_field_message(std::string(name), type);
}
inline Json::Value
expected_field_error(std::string const& name, std::string const& type)
{
return make_param_error(expected_field_message(name, type));
}
inline Json::Value
expected_field_error(Json::StaticString name, std::string const& type)
{
return expected_field_error(std::string(name), type);
}
inline Json::Value
not_validator_error()
{
return make_param_error("not a validator");
}
/** @} */
/** Returns `true` if the json contains an rpc error specification. */
bool
contains_error(Json::Value const& json);
/** Returns http status that corresponds to the error code. */
int
error_code_http_status(error_code_i code);
} // namespace RPC
/** Returns a single string with the contents of an RPC error. */
std::string
rpcErrorString(Json::Value const& jv);
} // namespace ripple
#endif

View File

@@ -0,0 +1,399 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_FEATURE_H_INCLUDED
#define RIPPLE_PROTOCOL_FEATURE_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <boost/container/flat_map.hpp>
#include <array>
#include <bitset>
#include <map>
#include <optional>
#include <string>
/**
* @page Feature How to add new features
*
* Steps required to add new features to the code:
*
* 1) In this file, increment `numFeatures` and add a uint256 declaration
* for the feature at the bottom
* 2) Add a uint256 definition for the feature to the corresponding source
* file (Feature.cpp). Use `registerFeature` to create the feature with
* the feature's name, `Supported::no`, and `VoteBehavior::DefaultNo`. This
* should be the only place the feature's name appears in code as a string.
* 3) Use the uint256 as the parameter to `view.rules.enabled()` to
* control flow into new code that this feature limits.
* 4) If the feature development is COMPLETE, and the feature is ready to be
* SUPPORTED, change the `registerFeature` parameter to Supported::yes.
* 5) When the feature is ready to be ENABLED, change the `registerFeature`
* parameter to `VoteBehavior::DefaultYes`.
* In general, any newly supported amendments (`Supported::yes`) should have
* a `VoteBehavior::DefaultNo` for at least one full release cycle. High
* priority bug fixes can be an exception to this rule of thumb.
*
* When a feature has been enabled for several years, the conditional code
* may be removed, and the feature "retired". To retire a feature:
* 1) Remove the uint256 declaration from this file.
* 2) MOVE the uint256 definition in Feature.cpp to the "retired features"
* section at the end of the file.
* 3) CHANGE the name of the variable to start with "retired".
* 4) CHANGE the parameters of the `registerFeature` call to `Supported::yes`
* and `VoteBehavior::DefaultNo`.
* The feature must remain registered and supported indefinitely because it
* still exists in the ledger, but there is no need to vote for it because
* there's nothing to vote for. If it is removed completely from the code, any
* instances running that code will get amendment blocked. Removing the
* feature from the ledger is beyond the scope of these instructions.
*
*/
namespace ripple {
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
/** All amendments libxrpl knows about. */
std::map<std::string, AmendmentSupport> const&
allAmendments();
namespace detail {
// This value SHOULD be equal to the number of amendments registered in
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 99;
/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
ledger */
std::map<std::string, VoteBehavior> const&
supportedAmendments();
/** Amendments that this server won't vote for by default.
This function is only used in unit tests.
*/
std::size_t
numDownVotedAmendments();
/** Amendments that this server will vote for by default.
This function is only used in unit tests.
*/
std::size_t
numUpVotedAmendments();
} // namespace detail
std::optional<uint256>
getRegisteredFeature(std::string const& name);
size_t
featureToBitsetIndex(uint256 const& f);
uint256
bitsetIndexToFeature(size_t i);
std::string
featureToName(uint256 const& f);
class FeatureBitset : private std::bitset<detail::numFeatures>
{
using base = std::bitset<detail::numFeatures>;
template <class... Fs>
void
initFromFeatures(uint256 const& f, Fs&&... fs)
{
set(f);
if constexpr (sizeof...(fs) > 0)
initFromFeatures(std::forward<Fs>(fs)...);
}
public:
using base::bitset;
using base::operator==;
using base::all;
using base::any;
using base::count;
using base::flip;
using base::none;
using base::reset;
using base::set;
using base::size;
using base::test;
using base::operator[];
using base::to_string;
using base::to_ullong;
using base::to_ulong;
FeatureBitset() = default;
explicit FeatureBitset(base const& b) : base(b)
{
assert(b.count() == count());
}
template <class... Fs>
explicit FeatureBitset(uint256 const& f, Fs&&... fs)
{
initFromFeatures(f, std::forward<Fs>(fs)...);
assert(count() == (sizeof...(fs) + 1));
}
template <class Col>
explicit FeatureBitset(Col const& fs)
{
for (auto const& f : fs)
set(featureToBitsetIndex(f));
assert(fs.size() == count());
}
auto
operator[](uint256 const& f)
{
return base::operator[](featureToBitsetIndex(f));
}
auto
operator[](uint256 const& f) const
{
return base::operator[](featureToBitsetIndex(f));
}
FeatureBitset&
set(uint256 const& f, bool value = true)
{
base::set(featureToBitsetIndex(f), value);
return *this;
}
FeatureBitset&
reset(uint256 const& f)
{
base::reset(featureToBitsetIndex(f));
return *this;
}
FeatureBitset&
flip(uint256 const& f)
{
base::flip(featureToBitsetIndex(f));
return *this;
}
FeatureBitset&
operator&=(FeatureBitset const& rhs)
{
base::operator&=(rhs);
return *this;
}
FeatureBitset&
operator|=(FeatureBitset const& rhs)
{
base::operator|=(rhs);
return *this;
}
FeatureBitset
operator~() const
{
return FeatureBitset{base::operator~()};
}
friend FeatureBitset
operator&(FeatureBitset const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{
static_cast<base const&>(lhs) & static_cast<base const&>(rhs)};
}
friend FeatureBitset
operator&(FeatureBitset const& lhs, uint256 const& rhs)
{
return lhs & FeatureBitset{rhs};
}
friend FeatureBitset
operator&(uint256 const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{lhs} & rhs;
}
friend FeatureBitset
operator|(FeatureBitset const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{
static_cast<base const&>(lhs) | static_cast<base const&>(rhs)};
}
friend FeatureBitset
operator|(FeatureBitset const& lhs, uint256 const& rhs)
{
return lhs | FeatureBitset{rhs};
}
friend FeatureBitset
operator|(uint256 const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{lhs} | rhs;
}
friend FeatureBitset
operator^(FeatureBitset const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{
static_cast<base const&>(lhs) ^ static_cast<base const&>(rhs)};
}
friend FeatureBitset
operator^(FeatureBitset const& lhs, uint256 const& rhs)
{
return lhs ^ FeatureBitset { rhs };
}
friend FeatureBitset
operator^(uint256 const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{lhs} ^ rhs;
}
// set difference
friend FeatureBitset
operator-(FeatureBitset const& lhs, FeatureBitset const& rhs)
{
return lhs & ~rhs;
}
friend FeatureBitset
operator-(FeatureBitset const& lhs, uint256 const& rhs)
{
return lhs - FeatureBitset{rhs};
}
friend FeatureBitset
operator-(uint256 const& lhs, FeatureBitset const& rhs)
{
return FeatureBitset{lhs} - rhs;
}
};
template <class F>
void
foreachFeature(FeatureBitset bs, F&& f)
{
for (size_t i = 0; i < bs.size(); ++i)
if (bs[i])
f(bitsetIndexToFeature(i));
}
extern uint256 const featureOwnerPaysFee;
extern uint256 const featureFlow;
extern uint256 const featureFlowCross;
extern uint256 const featureCryptoConditionsSuite;
extern uint256 const fix1513;
extern uint256 const featureDepositAuth;
extern uint256 const featureChecks;
extern uint256 const fix1571;
extern uint256 const fix1543;
extern uint256 const fix1623;
extern uint256 const featureDepositPreauth;
extern uint256 const fix1515;
extern uint256 const fix1578;
extern uint256 const featureMultiSignReserve;
extern uint256 const fixTakerDryOfferRemoval;
extern uint256 const fixMasterKeyAsRegularKey;
extern uint256 const fixCheckThreading;
extern uint256 const fixPayChanRecipientOwnerDir;
extern uint256 const featureDeletableAccounts;
extern uint256 const fixQualityUpperBound;
extern uint256 const featureRequireFullyCanonicalSig;
extern uint256 const fix1781;
extern uint256 const featureHardenedValidations;
extern uint256 const fixAmendmentMajorityCalc;
extern uint256 const featureNegativeUNL;
extern uint256 const featureTicketBatch;
extern uint256 const featureFlowSortStrands;
extern uint256 const fixSTAmountCanonicalize;
extern uint256 const fixRmSmallIncreasedQOffers;
extern uint256 const featureCheckCashMakesTrustLine;
extern uint256 const featureHooks;
extern uint256 const featureExpandedSignerList;
extern uint256 const featureNonFungibleTokensV1;
extern uint256 const fixNFTokenDirV1;
extern uint256 const fixNFTokenNegOffer;
extern uint256 const featureNonFungibleTokensV1_1;
extern uint256 const fixTrustLinesToSelf;
extern uint256 const featureBalanceRewards;
extern uint256 const featureDisallowIncoming;
extern uint256 const fixRemoveNFTokenAutoTrustLine;
extern uint256 const featureImmediateOfferKilled;
extern uint256 const featureDisallowIncoming;
extern uint256 const featurePaychanAndEscrowForTokens;
extern uint256 const featureURIToken;
extern uint256 const featureXRPFees;
extern uint256 const fixUniversalNumber;
extern uint256 const fixNonFungibleTokensV1_2;
extern uint256 const fixNFTokenRemint;
extern uint256 const featureImport;
extern uint256 const featureXahauGenesis;
extern uint256 const featureHooksUpdate1;
extern uint256 const fixXahauV1;
extern uint256 const fixXahauV2;
extern uint256 const featureRemit;
extern uint256 const featureZeroB2M;
extern uint256 const fixNSDelete;
extern uint256 const fix240819;
extern uint256 const fixPageCap;
extern uint256 const fix240911;
extern uint256 const fixFloatDivide;
extern uint256 const featureRemarks;
extern uint256 const featureTouch;
extern uint256 const fixReduceImport;
extern uint256 const fixXahauV3;
extern uint256 const fix20250131;
extern uint256 const featureHookCanEmit;
extern uint256 const fixRewardClaimFlags;
extern uint256 const fixReducedOffersV1;
extern uint256 const featureClawback;
extern uint256 const featureAMM;
extern uint256 const featureXChainBridge;
extern uint256 const fixDisallowIncomingV1;
extern uint256 const featureDID;
extern uint256 const fixFillOrKill;
extern uint256 const fixNFTokenReserve;
extern uint256 const fixInnerObjTemplate;
extern uint256 const fixAMMOverflowOffer;
extern uint256 const featurePriceOracle;
extern uint256 const fixEmptyDID;
extern uint256 const fixXChainRewardRounding;
extern uint256 const fixPreviousTxnID;
extern uint256 const fixAMMv1_1;
extern uint256 const featureNFTokenMintOffer;
extern uint256 const fixReducedOffersV2;
extern uint256 const fixEnforceNFTokenTrustline;
} // namespace ripple
#endif

View File

@@ -0,0 +1,57 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_FEES_H_INCLUDED
#define RIPPLE_PROTOCOL_FEES_H_INCLUDED
#include <ripple/basics/XRPAmount.h>
namespace ripple {
/** Reflects the fee settings for a particular ledger.
The fees are always the same for any transactions applied
to a ledger. Changes to fees occur in between ledgers.
*/
struct Fees
{
XRPAmount base{0}; // Reference tx cost (drops)
XRPAmount reserve{0}; // Reserve base (drops)
XRPAmount increment{0}; // Reserve increment (drops)
explicit Fees() = default;
Fees(Fees const&) = default;
Fees&
operator=(Fees const&) = default;
/** Returns the account reserve given the owner count, in drops.
The reserve is calculated as the reserve base plus
the reserve increment times the number of increments.
*/
XRPAmount
accountReserve(std::size_t ownerCount) const
{
return reserve + ownerCount * increment;
}
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,111 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_HASHPREFIX_H_INCLUDED
#define RIPPLE_PROTOCOL_HASHPREFIX_H_INCLUDED
#include <ripple/beast/hash/hash_append.h>
#include <cstdint>
namespace ripple {
namespace detail {
constexpr std::uint32_t
make_hash_prefix(char a, char b, char c)
{
return (static_cast<std::uint32_t>(a) << 24) +
(static_cast<std::uint32_t>(b) << 16) +
(static_cast<std::uint32_t>(c) << 8);
}
} // namespace detail
/** Prefix for hashing functions.
These prefixes are inserted before the source material used to generate
various hashes. This is done to put each hash in its own "space." This way,
two different types of objects with the same binary data will produce
different hashes.
Each prefix is a 4-byte value with the last byte set to zero and the first
three bytes formed from the ASCII equivalent of some arbitrary string. For
example "TXN".
@note Hash prefixes are part of the protocol; you cannot, arbitrarily,
change the type or the value of any of these without causing breakage.
*/
enum class HashPrefix : std::uint32_t {
/** transaction plus signature to give transaction ID */
transactionID = detail::make_hash_prefix('T', 'X', 'N'),
/** transaction plus metadata */
txNode = detail::make_hash_prefix('S', 'N', 'D'),
/** account state */
leafNode = detail::make_hash_prefix('M', 'L', 'N'),
/** inner node in V1 tree */
innerNode = detail::make_hash_prefix('M', 'I', 'N'),
/** ledger master data for signing */
ledgerMaster = detail::make_hash_prefix('L', 'W', 'R'),
/** inner transaction to sign */
txSign = detail::make_hash_prefix('S', 'T', 'X'),
/** inner transaction to multi-sign */
txMultiSign = detail::make_hash_prefix('S', 'M', 'T'),
/** validation for signing */
validation = detail::make_hash_prefix('V', 'A', 'L'),
/** proposal for signing */
proposal = detail::make_hash_prefix('P', 'R', 'P'),
/** Manifest */
manifest = detail::make_hash_prefix('M', 'A', 'N'),
/** Payment Channel Claim */
paymentChannelClaim = detail::make_hash_prefix('C', 'L', 'M'),
/** shard info for signing */
shardInfo = detail::make_hash_prefix('S', 'H', 'D'),
/** Emit Transaction Nonce */
emitTxnNonce = detail::make_hash_prefix('E', 'T', 'X'),
/** Random entropy for hook developers to use */
hookNonce = detail::make_hash_prefix('N', 'C', 'E'),
/* Hash of a Hook's actual code */
hookDefinition = detail::make_hash_prefix('W', 'S', 'M')
};
template <class Hasher>
void
hash_append(Hasher& h, HashPrefix const& hp) noexcept
{
using beast::hash_append;
hash_append(h, static_cast<std::uint32_t>(hp));
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,470 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_IMPORT_H_INCLUDED
#define RIPPLE_PROTOCOL_IMPORT_H_INCLUDED
// #include <ripple/basics/Log.h>
#include <ripple/app/misc/Manifest.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/base64.h>
#include <ripple/json/json_reader.h>
#include <charconv>
namespace ripple {
inline bool
isHex(std::string const& str)
{
return str.find_first_not_of("0123456789abcdefABCDEF") == std::string::npos;
}
inline bool
isBase58(std::string const& str)
{
return str.find_first_not_of(
"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz") ==
std::string::npos;
}
inline bool
isBase64(std::string const& str)
{
return str.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+"
"/=") == std::string::npos;
}
inline std::optional<uint64_t>
parse_uint64(std::string const& str)
{
uint64_t result;
auto [ptr, ec] =
std::from_chars(str.data(), str.data() + str.size(), result);
if (ec == std::errc())
return result;
return {};
}
inline bool
syntaxCheckProof(
Json::Value const& proof,
beast::Journal const& j,
int depth = 0)
{
if (depth > 64)
{
JLOG(j.warn())
<< "XPOP.transaction.proof list should be less than 64 entries";
return false;
}
if (proof.isArray())
{
// List form
if (proof.size() != 16)
{
JLOG(j.warn())
<< "XPOP.transaction.proof list should be exactly 16 entries";
return false;
}
for (const auto& entry : proof)
{
if (entry.isString())
{
if (!isHex(entry.asString()) || entry.asString().size() != 64)
{
JLOG(j.warn())
<< "XPOP.transaction.proof list entry missing "
"or wrong format "
<< "(should be hex string with 64 characters)";
return false;
}
}
else if (entry.isArray())
{
if (!syntaxCheckProof(entry, j, depth + 1))
return false;
}
else
{
JLOG(j.warn())
<< "XPOP.transaction.proof list entry has wrong format";
return false;
}
}
}
else if (proof.isObject())
{
// Tree form
if (depth == 0) // root is special case
{
if (!proof["hash"].isString() ||
proof["hash"].asString().size() != 64 ||
!proof["key"].isString() ||
proof["key"].asString().size() != 64 ||
!proof["children"].isObject())
{
JLOG(j.warn()) << "XPOP.transaction.proof tree node has wrong "
"format (root)";
return false;
}
return syntaxCheckProof(proof["children"], j, depth + 1);
}
for (const auto& branch : proof.getMemberNames())
{
if (branch.size() != 1 || !isHex(branch))
{
JLOG(j.warn())
<< "XPOP.transaction.proof child node was not 0-F "
"hex nibble";
return false;
}
const auto& node = proof[branch];
if (!node.isObject() || !node["hash"].isString() ||
node["hash"].asString().size() != 64 ||
!node["key"].isString() ||
node["key"].asString().size() != 64 ||
!node["children"].isObject())
{
JLOG(j.warn())
<< "XPOP.transaction.proof tree node has wrong format";
return false;
}
if (!syntaxCheckProof(node["children"], j, depth + 1))
{
JLOG(j.warn()) << "XPOP.transaction.proof bad children format";
return false;
}
}
}
else
{
JLOG(j.warn()) << "XPOP.transaction.proof has wrong format (should be "
"array or object)";
return false;
}
return true;
}
// does not check signature etc
inline std::optional<Json::Value>
syntaxCheckXPOP(Blob const& blob, beast::Journal const& j)
{
if (blob.empty())
return {};
std::string strJson(blob.begin(), blob.end());
if (strJson.empty())
return {};
try
{
Json::Value xpop;
Json::Reader reader;
if (!reader.parse(strJson, xpop))
{
JLOG(j.warn()) << "XPOP failed to parse string json";
return {};
}
if (!xpop.isObject())
{
JLOG(j.warn()) << "XPOP is not a JSON object";
return {};
}
if (!xpop["ledger"].isObject())
{
JLOG(j.warn()) << "XPOP.ledger is not a JSON object";
return {};
}
if (!xpop["transaction"].isObject())
{
JLOG(j.warn()) << "XPOP.transaction is not a JSON object";
return {};
}
if (!xpop["validation"].isObject())
{
JLOG(j.warn()) << "XPOP.validation is not a JSON object";
return {};
}
if (!xpop["ledger"]["acroot"].isString() ||
xpop["ledger"]["acroot"].asString().size() != 64 ||
!isHex(xpop["ledger"]["acroot"].asString()))
{
JLOG(j.warn())
<< "XPOP.ledger.acroot missing or wrong format (should "
"be hex string)";
return {};
}
if (!xpop["ledger"]["txroot"].isString() ||
xpop["ledger"]["txroot"].asString().size() != 64 ||
!isHex(xpop["ledger"]["txroot"].asString()))
{
JLOG(j.warn()) << "XPOP.ledger.txroot missing or wrong format "
"(should be hex string)";
return {};
}
if (!xpop["ledger"]["phash"].isString() ||
xpop["ledger"]["phash"].asString().size() != 64 ||
!isHex(xpop["ledger"]["phash"].asString()))
{
JLOG(j.warn()) << "XPOP.ledger.phash missing or wrong format "
"(should be hex string)";
return {};
}
if (!xpop["ledger"]["close"].isInt())
{
JLOG(j.warn()) << "XPOP.ledger.close missing or wrong format "
"(should be int)";
return {};
}
if (xpop["ledger"]["coins"].isInt())
{
// pass
}
else if (xpop["ledger"]["coins"].isString())
{
if (!parse_uint64(xpop["ledger"]["coins"].asString()))
{
JLOG(j.warn()) << "XPOP.ledger.coins missing or wrong format "
"(should be int or string)";
return {};
}
}
else
{
JLOG(j.warn()) << "XPOP.ledger.coins missing or wrong format "
"(should be int or string)";
return {};
}
if (!xpop["ledger"]["cres"].isInt())
{
JLOG(j.warn()) << "XPOP.ledger.cres missing or wrong format "
"(should be int)";
return {};
}
if (!xpop["ledger"]["index"].isInt())
{
JLOG(j.warn()) << "XPOP.ledger.index missing or wrong format "
"(should be int)";
return {};
}
if (!xpop["ledger"]["flags"].isInt())
{
JLOG(j.warn()) << "XPOP.ledger.flags missing or wrong format "
"(should be int)";
return {};
}
if (!xpop["ledger"]["pclose"].isInt())
{
JLOG(j.warn()) << "XPOP.ledger.pclose missing or wrong format "
"(should be int)";
return {};
}
if (!xpop["transaction"]["blob"].isString() ||
!isHex(xpop["transaction"]["blob"].asString()))
{
JLOG(j.warn()) << "XPOP.transaction.blob missing or wrong format "
"(should be hex string)";
return {};
}
if (!xpop["transaction"]["meta"].isString() ||
!isHex(xpop["transaction"]["meta"].asString()))
{
JLOG(j.warn()) << "XPOP.transaction.meta missing or wrong format "
"(should be hex string)";
return {};
}
if (!syntaxCheckProof(xpop["transaction"]["proof"], j))
{
JLOG(j.warn()) << "XPOP.transaction.proof failed syntax check "
"(tree/list form)";
return {};
}
if (!xpop["validation"]["data"].isObject())
{
JLOG(j.warn()) << "XPOP.validation.data missing or wrong format "
"(should be JSON object)";
return {};
}
if (!xpop["validation"]["unl"].isObject())
{
JLOG(j.warn()) << "XPOP.validation.unl missing or wrong format "
"(should be JSON object)";
return {};
}
for (const auto& key : xpop["validation"]["data"].getMemberNames())
{
const auto& value = xpop["validation"]["data"][key];
if (!isBase58(key) || !value.isString() || !isHex(value.asString()))
{
JLOG(j.warn()) << "XPOP.validation.data entry has wrong format "
<< "(key should be base58 string and value "
"should be hex string)";
return {};
}
}
uint32_t found = 0;
for (const auto& key : xpop["validation"]["unl"].getMemberNames())
{
const auto& value = xpop["validation"]["unl"][key];
if (key == "public_key")
{
if (!value.isString() || !isHex(value.asString()))
{
JLOG(j.warn())
<< "XPOP.validation.unl.public_key missing or "
"wrong format (should be hex string)";
return {};
}
auto pk = strUnHex(value.asString());
if (!publicKeyType(makeSlice(*pk)))
{
JLOG(j.warn())
<< "XPOP.validation.unl.public_key invalid key type.";
return {};
}
found |= 1;
}
else if (key == "manifest")
{
if (!value.isString() || !isBase64(value.asString()))
{
JLOG(j.warn()) << "XPOP.validation.unl.manifest missing or "
"wrong format (should be string)";
return {};
}
found |= 2;
}
else if (key == "blob")
{
if (!value.isString() || !isBase64(value.asString()))
{
JLOG(j.warn())
<< "XPOP.validation.unl.blob missing or wrong "
"format (should be base64 string)";
return {};
}
found |= 4;
}
else if (key == "signature")
{
if (!value.isString() || !isHex(value.asString()))
{
JLOG(j.warn())
<< "XPOP.validation.unl.signature missing or wrong "
"format (should be hex string)";
return {};
}
found |= 8;
}
else if (key == "version")
{
if (!value.isInt())
{
JLOG(j.warn()) << "XPOP.validation.unl.version missing or "
"wrong format (should be int)";
return {};
}
found |= 16;
}
else
{
if (!value.isObject() && !value.isString())
{
JLOG(j.warn())
<< "XPOP.validation.unl entry has wrong format";
return {};
}
}
}
if (found != 0b11111)
{
JLOG(j.warn()) << "XPOP.validation.unl entry has wrong format "
"(missing field/s)";
return {};
}
return xpop;
}
catch (...)
{
JLOG(j.warn()) << "An exception occurred during XPOP validation";
}
return {};
}
// <sequence, master key>
inline std::optional<std::pair<uint32_t, PublicKey>>
getVLInfo(Json::Value const& xpop, beast::Journal const& j)
{
auto const data =
base64_decode(xpop[jss::validation][jss::unl][jss::blob].asString());
Json::Reader r;
Json::Value list;
if (!r.parse(data, list))
{
JLOG(j.warn())
<< "Import: unl blob was not valid json (after base64 decoding)";
return {};
}
auto const sequence = list[jss::sequence].asUInt();
auto const m = deserializeManifest(base64_decode(
xpop[jss::validation][jss::unl][jss::manifest].asString()));
if (!m)
{
JLOG(j.warn()) << "Import: failed to deserialize manifest";
return {};
}
return {{sequence, m->masterKey}};
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,345 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_INDEXES_H_INCLUDED
#define RIPPLE_PROTOCOL_INDEXES_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/protocol/Book.h>
#include <ripple/protocol/Keylet.h>
#include <ripple/protocol/LedgerFormats.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/STXChainBridge.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/UintTypes.h>
#include <cstdint>
namespace ripple {
using UInt32or256 = std::variant<uint32_t, uint256>;
class SeqProxy;
/** Keylet computation funclets.
Entries in the ledger are located using 256-bit locators. The locators are
calculated using a wide range of parameters specific to the entry whose
locator we are calculating (e.g. an account's locator is derived from the
account's address, whereas the locator for an offer is derived from the
account and the offer sequence.)
To enhance type safety during lookup and make the code more robust, we use
keylets, which contain not only the locator of the object but also the type
of the object being referenced.
These functions each return a type-specific keylet.
*/
namespace keylet {
/** The (fixed) index of the object containing the emitted txns for the ledger.
*/
Keylet const&
emittedDir() noexcept;
Keylet
emittedTxn(uint256 const& id) noexcept;
Keylet
hookDefinition(uint256 const& hash) noexcept;
Keylet
hook(AccountID const& id) noexcept;
Keylet
hookState(AccountID const& id, uint256 const& key, uint256 const& ns) noexcept;
Keylet
hookStateDir(AccountID const& id, uint256 const& ns) noexcept;
/** AccountID root */
Keylet
account(AccountID const& id) noexcept;
/** The index of the amendment table */
Keylet const&
amendments() noexcept;
/** Any item that can be in an owner dir. */
Keylet
child(uint256 const& key) noexcept;
/** The index of the "short" skip list
The "short" skip list is a node (at a fixed index) that holds the hashes
of ledgers since the last flag ledger. It will contain, at most, 256 hashes.
*/
Keylet const&
skip() noexcept;
/** The index of the long skip for a particular ledger range.
The "long" skip list is a node that holds the hashes of (up to) 256 flag
ledgers.
It can be used to efficiently skip back to any ledger using only two hops:
the first hop gets the "long" skip list for the ledger it wants to retrieve
and uses it to get the hash of the flag ledger whose short skip list will
contain the hash of the requested ledger.
*/
Keylet
skip(LedgerIndex ledger) noexcept;
/** The (fixed) index of the object containing the ledger fees. */
Keylet const&
fees() noexcept;
/** The (fixed) index of the object containing the ledger negativeUNL. */
Keylet const&
negativeUNL() noexcept;
Keylet const&
UNLReport() noexcept;
/** The beginning of an order book */
struct book_t
{
explicit book_t() = default;
Keylet
operator()(Book const& b) const;
};
static book_t const book{};
/** The index of a trust line for a given currency
Note that a trustline is *shared* between two accounts (commonly referred
to as the issuer and the holder); if Alice sets up a trust line to Bob for
BTC, and Bob trusts Alice for BTC, here is only a single BTC trust line
between them.
*/
/** @{ */
Keylet
line(
AccountID const& id0,
AccountID const& id1,
Currency const& currency) noexcept;
inline Keylet
line(AccountID const& id, Issue const& issue) noexcept
{
return line(id, issue.account, issue.currency);
}
/** @} */
/** An offer from an account */
/** @{ */
Keylet
offer(AccountID const& id, UInt32or256 const& seq) noexcept;
inline Keylet
offer(uint256 const& key) noexcept
{
return {ltOFFER, key};
}
/** @} */
/** The initial directory page for a specific quality */
Keylet
quality(Keylet const& k, std::uint64_t q) noexcept;
/** The directory for the next lower quality */
struct next_t
{
explicit next_t() = default;
Keylet
operator()(Keylet const& k) const;
};
static next_t const next{};
/** A ticket belonging to an account */
struct ticket_t
{
explicit ticket_t() = default;
Keylet
operator()(AccountID const& id, std::uint32_t ticketSeq) const;
Keylet
operator()(AccountID const& id, SeqProxy ticketSeq) const;
Keylet
operator()(uint256 const& key) const
{
return {ltTICKET, key};
}
};
static ticket_t const ticket{};
/** A SignerList */
Keylet
signers(AccountID const& account) noexcept;
/** A Check */
/** @{ */
Keylet
check(AccountID const& id, UInt32or256 const& seq) noexcept;
inline Keylet
check(uint256 const& key) noexcept
{
return {ltCHECK, key};
}
/** @} */
/** A DepositPreauth */
/** @{ */
Keylet
depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept;
inline Keylet
depositPreauth(uint256 const& key) noexcept
{
return {ltDEPOSIT_PREAUTH, key};
}
/** @} */
//------------------------------------------------------------------------------
/** Any ledger entry */
Keylet
unchecked(uint256 const& key) noexcept;
/** The root page of an account's directory */
Keylet
ownerDir(AccountID const& id) noexcept;
/** A page in a directory */
/** @{ */
Keylet
page(uint256 const& root, std::uint64_t index = 0) noexcept;
inline Keylet
page(Keylet const& root, std::uint64_t index = 0) noexcept
{
assert(root.type == ltDIR_NODE);
return page(root.key, index);
}
/** @} */
/** An escrow entry */
Keylet
escrow(AccountID const& src, UInt32or256 const& seq) noexcept;
/** A PaymentChannel */
Keylet
payChan(
AccountID const& src,
AccountID const& dst,
UInt32or256 const& seq) noexcept;
/** NFT page keylets
Unlike objects whose ledger identifiers are produced by hashing data,
NFT page identifiers are composite identifiers, consisting of the owner's
160-bit AccountID, followed by a 96-bit value that determines which NFT
tokens are candidates for that page.
*/
/** @{ */
/** A keylet for the owner's first possible NFT page. */
Keylet
nftpage_min(AccountID const& owner);
/** A keylet for the owner's last possible NFT page. */
Keylet
nftpage_max(AccountID const& owner);
Keylet
nftpage(Keylet const& k, uint256 const& token);
/** @} */
/** An offer from an account to buy or sell an NFT */
Keylet
nftoffer(AccountID const& owner, UInt32or256 const& seq);
inline Keylet
nftoffer(uint256 const& offer)
{
return {ltNFTOKEN_OFFER, offer};
}
/** The directory of buy offers for the specified NFT */
Keylet
nft_buys(uint256 const& id) noexcept;
/** The directory of sell offers for the specified NFT */
Keylet
nft_sells(uint256 const& id) noexcept;
Keylet
import_vlseq(PublicKey const& key) noexcept;
Keylet
uritoken(AccountID const& issuer, Blob const& uri);
/** AMM entry */
Keylet
amm(Issue const& issue1, Issue const& issue2) noexcept;
Keylet
amm(uint256 const& amm) noexcept;
Keylet
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
Keylet
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq);
Keylet
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);
Keylet
did(AccountID const& account) noexcept;
Keylet
oracle(AccountID const& account, std::uint32_t const& documentID) noexcept;
} // namespace keylet
// Everything below is deprecated and should be removed in favor of keylets:
uint256
getBookBase(Book const& book);
uint256
getQualityNext(uint256 const& uBase);
// VFALCO This name could be better
std::uint64_t
getQuality(uint256 const& uBase);
uint256
getTicketIndex(AccountID const& account, std::uint32_t uSequence);
uint256
getTicketIndex(AccountID const& account, SeqProxy ticketSeq);
} // namespace ripple
#endif

View File

@@ -0,0 +1,47 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_INNER_OBJECT_FORMATS_H_INCLUDED
#define RIPPLE_PROTOCOL_INNER_OBJECT_FORMATS_H_INCLUDED
#include <ripple/protocol/KnownFormats.h>
namespace ripple {
/** Manages the list of known inner object formats.
*/
class InnerObjectFormats : public KnownFormats<int, InnerObjectFormats>
{
private:
/** Create the object.
This will load the object with all the known inner object formats.
*/
InnerObjectFormats();
public:
static InnerObjectFormats const&
getInstance();
SOTemplate const*
findSOTemplateBySField(SField const& sField) const;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,121 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_ISSUE_H_INCLUDED
#define RIPPLE_PROTOCOL_ISSUE_H_INCLUDED
#include <ripple/json/json_value.h>
#include <ripple/protocol/UintTypes.h>
#include <cassert>
#include <functional>
#include <type_traits>
namespace ripple {
/** A currency issued by an account.
@see Currency, AccountID, Issue, Book
*/
class Issue
{
public:
Currency currency{};
AccountID account{};
Issue()
{
}
Issue(Currency const& c, AccountID const& a) : currency(c), account(a)
{
}
std::string
getText() const;
};
bool
isConsistent(Issue const& ac);
std::string
to_string(Issue const& ac);
Json::Value
to_json(Issue const& is);
Issue
issueFromJson(Json::Value const& v);
std::ostream&
operator<<(std::ostream& os, Issue const& x);
template <class Hasher>
void
hash_append(Hasher& h, Issue const& r)
{
using beast::hash_append;
hash_append(h, r.currency, r.account);
}
/** Equality comparison. */
/** @{ */
[[nodiscard]] inline constexpr bool
operator==(Issue const& lhs, Issue const& rhs)
{
return (lhs.currency == rhs.currency) &&
(isXRP(lhs.currency) || lhs.account == rhs.account);
}
/** @} */
/** Strict weak ordering. */
/** @{ */
[[nodiscard]] inline constexpr std::weak_ordering
operator<=>(Issue const& lhs, Issue const& rhs)
{
if (auto const c{lhs.currency <=> rhs.currency}; c != 0)
return c;
if (isXRP(lhs.currency))
return std::weak_ordering::equivalent;
return (lhs.account <=> rhs.account);
}
/** @} */
//------------------------------------------------------------------------------
/** Returns an asset specifier that represents XRP. */
inline Issue const&
xrpIssue()
{
static Issue issue{xrpCurrency(), xrpAccount()};
return issue;
}
/** Returns an asset specifier that represents no account and currency. */
inline Issue const&
noIssue()
{
static Issue issue{noCurrency(), noAccount()};
return issue;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2015 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_PROTOCOL_KEYTYPE_H_INCLUDED
#define RIPPLE_PROTOCOL_KEYTYPE_H_INCLUDED
#include <optional>
#include <string>
namespace ripple {
enum class KeyType {
secp256k1 = 0,
ed25519 = 1,
};
inline std::optional<KeyType>
keyTypeFromString(std::string const& s)
{
if (s == "secp256k1")
return KeyType::secp256k1;
if (s == "ed25519")
return KeyType::ed25519;
return {};
}
inline char const*
to_string(KeyType type)
{
if (type == KeyType::secp256k1)
return "secp256k1";
if (type == KeyType::ed25519)
return "ed25519";
return "INVALID";
}
template <class Stream>
inline Stream&
operator<<(Stream& s, KeyType type)
{
return s << to_string(type);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_KEYLET_H_INCLUDED
#define RIPPLE_PROTOCOL_KEYLET_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/protocol/LedgerFormats.h>
namespace ripple {
class STLedgerEntry;
/** A pair of SHAMap key and LedgerEntryType.
A Keylet identifies both a key in the state map
and its ledger entry type.
@note Keylet is a portmanteau of the words key
and LET, an acronym for LedgerEntryType.
*/
struct Keylet
{
uint256 key;
LedgerEntryType type;
Keylet(LedgerEntryType type_, uint256 const& key_) : key(key_), type(type_)
{
}
/** Returns true if the SLE matches the type */
bool
check(STLedgerEntry const&) const;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,205 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_KNOWNFORMATS_H_INCLUDED
#define RIPPLE_PROTOCOL_KNOWNFORMATS_H_INCLUDED
#include <ripple/basics/contract.h>
#include <ripple/beast/type_name.h>
#include <ripple/protocol/SOTemplate.h>
#include <boost/container/flat_map.hpp>
#include <algorithm>
#include <forward_list>
namespace ripple {
/** Manages a list of known formats.
Each format has a name, an associated KeyType (typically an enumeration),
and a predefined @ref SOElement.
@tparam KeyType The type of key identifying the format.
*/
template <class KeyType, class Derived>
class KnownFormats
{
public:
/** A known format.
*/
class Item
{
public:
Item(
char const* name,
KeyType type,
std::initializer_list<SOElement> uniqueFields,
std::initializer_list<SOElement> commonFields)
: soTemplate_(uniqueFields, commonFields), name_(name), type_(type)
{
// Verify that KeyType is appropriate.
static_assert(
std::is_enum<KeyType>::value ||
std::is_integral<KeyType>::value,
"KnownFormats KeyType must be integral or enum.");
}
/** Retrieve the name of the format.
*/
std::string const&
getName() const
{
return name_;
}
/** Retrieve the transaction type this format represents.
*/
KeyType
getType() const
{
return type_;
}
SOTemplate const&
getSOTemplate() const
{
return soTemplate_;
}
private:
SOTemplate soTemplate_;
std::string const name_;
KeyType const type_;
};
/** Create the known formats object.
Derived classes will load the object with all the known formats.
*/
KnownFormats() : name_(beast::type_name<Derived>())
{
}
/** Destroy the known formats object.
The defined formats are deleted.
*/
virtual ~KnownFormats() = default;
KnownFormats(KnownFormats const&) = delete;
KnownFormats&
operator=(KnownFormats const&) = delete;
/** Retrieve the type for a format specified by name.
If the format name is unknown, an exception is thrown.
@param name The name of the type.
@return The type.
*/
KeyType
findTypeByName(std::string const& name) const
{
if (auto const result = findByName(name))
return result->getType();
Throw<std::runtime_error>(
name_ + ": Unknown format name '" +
name.substr(0, std::min(name.size(), std::size_t(32))) + "'");
}
/** Retrieve a format based on its type.
*/
Item const*
findByType(KeyType type) const
{
auto const itr = types_.find(type);
if (itr == types_.end())
return nullptr;
return itr->second;
}
// begin() and end() are provided for testing purposes.
typename std::forward_list<Item>::const_iterator
begin() const
{
return formats_.begin();
}
typename std::forward_list<Item>::const_iterator
end() const
{
return formats_.end();
}
protected:
/** Retrieve a format based on its name.
*/
Item const*
findByName(std::string const& name) const
{
auto const itr = names_.find(name);
if (itr == names_.end())
return nullptr;
return itr->second;
}
/** Add a new format.
@param name The name of this format.
@param type The type of this format.
@param uniqueFields An std::initializer_list of unique fields
@param commonFields An std::initializer_list of common fields
@return The created format.
*/
Item const&
add(char const* name,
KeyType type,
std::initializer_list<SOElement> uniqueFields,
std::initializer_list<SOElement> commonFields = {})
{
if (auto const item = findByType(type))
{
LogicError(
std::string("Duplicate key for item '") + name +
"': already maps to " + item->getName());
}
formats_.emplace_front(name, type, uniqueFields, commonFields);
Item const& item{formats_.front()};
names_[name] = &item;
types_[type] = &item;
return item;
}
private:
std::string name_;
// One of the situations where a std::forward_list is useful. We want to
// store each Item in a place where its address won't change. So a node-
// based container is appropriate. But we don't need searchability.
std::forward_list<Item> formats_;
boost::container::flat_map<std::string, Item const*> names_;
boost::container::flat_map<KeyType, Item const*> types_;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,383 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_LEDGERFORMATS_H_INCLUDED
#define RIPPLE_PROTOCOL_LEDGERFORMATS_H_INCLUDED
#include <ripple/protocol/KnownFormats.h>
namespace ripple {
/** Identifiers for on-ledger objects.
Each ledger object requires a unique type identifier, which is stored
within the object itself; this makes it possible to iterate the entire
ledger and determine each object's type and verify that the object you
retrieved from a given hash matches the expected type.
@warning Since these values are stored inside objects stored on the ledger
they are part of the protocol. **Changing them should be avoided
because without special handling, this will result in a hard
fork.**
@note Values outside this range may be used internally by the code for
various purposes, but attempting to use such values to identify
on-ledger objects will results in an invariant failure.
@note When retiring types, the specific values should not be removed but
should be marked as [[deprecated]]. This is to avoid accidental
reuse of identifiers.
@todo The C++ language does not enable checking for duplicate values
here. If it becomes possible then we should do this.
@ingroup protocol
*/
// clang-format off
enum LedgerEntryType : std::uint16_t
{
/** A ledger object which describes an account.
\sa keylet::account
*/
ltACCOUNT_ROOT = 0x0061,
/** A ledger object which contains a list of object identifiers.
\sa keylet::page, keylet::quality, keylet::book, keylet::next and
keylet::ownerDir
*/
ltDIR_NODE = 0x0064,
/** A ledger object which describes a bidirectional trust line.
@note Per Vinnie Falco this should be renamed to ltTRUST_LINE
\sa keylet::line
*/
ltRIPPLE_STATE = 0x0072,
/** A ledger object which describes a ticket.
\sa keylet::ticket
*/
ltTICKET = 0x0054,
/** A ledger object which contains a signer list for an account.
\sa keylet::signers
*/
ltSIGNER_LIST = 0x0053,
/** A ledger object which describes an offer on the DEX.
\sa keylet::offer
*/
ltOFFER = 0x006f,
/** The ledger object which lists details about sidechains.
\sa keylet::bridge
*/
ltBRIDGE = 0x0069,
/** A ledger object that contains a list of ledger hashes.
This type is used to store the ledger hashes which the protocol uses
to implement skip lists that allow for efficient backwards (and, in
theory, forward) forward iteration across large ledger ranges.
\sa keylet::skip
*/
ltLEDGER_HASHES = 0x0068,
/** The ledger object which lists details about amendments on the network.
\note This is a singleton: only one such object exists in the ledger.
\sa keylet::amendments
*/
ltAMENDMENTS = 0x0066,
/** A claim id for a cross chain transaction.
\sa keylet::xChainClaimID
*/
ltXCHAIN_OWNED_CLAIM_ID = 0x0071,
/** A claim id for a cross chain create account transaction.
\sa keylet::xChainCreateAccountClaimID
*/
ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID = 0x0074,
/** The ledger object which lists the network's fee settings.
\note This is a singleton: only one such object exists in the ledger.
\sa keylet::fees
*/
ltFEE_SETTINGS = 0x0073,
/** The ledger object which records the last (and largest) sequence for a validator list key
* as used in the Import amendment
*/
ltIMPORT_VLSEQ = 0x0049,
/** A ledger object describing a single escrow.
\sa keylet::escrow
*/
ltESCROW = 0x0075,
/** A ledger object describing a single unidirectional XRP payment channel.
\sa keylet::payChan
*/
ltPAYCHAN = 0x0078,
/** A ledger object which describes a check.
\sa keylet::check
*/
ltCHECK = 0x0043,
/** A ledger object which describes a deposit preauthorization.
\sa keylet::depositPreauth
*/
ltDEPOSIT_PREAUTH = 0x0070,
/** The ledger object which tracks the current negative UNL state.
\note This is a singleton: only one such object exists in the ledger.
\sa keylet::negativeUNL
*/
ltNEGATIVE_UNL = 0x004e,
/** A ledger object which contains a list of NFTs
\sa keylet::nftpage_min, keylet::nftpage_max, keylet::nftpage
*/
ltNFTOKEN_PAGE = 0x0050,
/** A ledger object which identifies an offer to buy or sell an NFT.
\sa keylet::nftoffer
*/
ltNFTOKEN_OFFER = 0x0037,
/** A unique ledger object which contains an up to 256 byte URI
\sa keylet::uritoken
*/
ltURI_TOKEN = 0x0055,
/** A ledger object that reports on the active dUNL validators
* that were validating for more than 240 of the last 256 ledgers
*
* \sa keylet::UNLReport
*/
ltUNL_REPORT = 0x0052,
/** The ledger object which tracks the AMM.
\sa keylet::amm
*/
ltAMM = 0x0079,
/** The ledger object which tracks the DID.
\sa keylet::did
*/
ltDID = 0x4449,
/** A ledger object which tracks Oracle
\sa keylet::oracle
*/
ltORACLE = 0x0080,
//---------------------------------------------------------------------------
/** A special type, matching any ledger entry type.
The value does not represent a concrete type, but rather is used in
contexts where the specific type of a ledger object is unimportant,
unknown or unavailable.
Objects with this special type cannot be created or stored on the
ledger.
\sa keylet::unchecked
*/
ltANY = 0,
/** A special type, matching any ledger type except directory nodes.
The value does not represent a concrete type, but rather is used in
contexts where the ledger object must not be a directory node but
its specific type is otherwise unimportant, unknown or unavailable.
Objects with this special type cannot be created or stored on the
ledger.
\sa keylet::child
*/
ltCHILD = 0x1CD2,
//---------------------------------------------------------------------------
/** A legacy, deprecated type.
\deprecated **This object type is not supported and should not be used.**
Support for this type of object was never implemented.
No objects of this type were ever created.
*/
ltNICKNAME [[deprecated("This object type is not supported and should not be used.")]] = 0x006e,
/** A legacy, deprecated type.
\deprecated **This object type is not supported and should not be used.**
Support for this type of object was never implemented.
No objects of this type were ever created.
*/
ltCONTRACT [[deprecated("This object type is not supported and should not be used.")]] = 0x0063,
/** A legacy, deprecated type.
\deprecated **This object type is not supported and should not be used.**
Support for this type of object was never implemented.
No objects of this type were ever created.
*/
ltGENERATOR_MAP [[deprecated("This object type is not supported and should not be used.")]] = 0x0067,
/** A ledger object which describes an installed hook on an account.
\sa keylet::hook
*/
ltHOOK ='H',
/** A ledger object which describes a stored value (from a k-v pair) for an installed hook.
\sa keylet::hookState
*/
ltHOOK_STATE ='v',
/** A reference-counted ledger object which stores the web assembly bytecode of a hook.
\sa keylet::hookDefinition
*/
ltHOOK_DEFINITION = 'D',
/** A ledger object containing a hook-emitted transaction from a previous hook execution.
\sa keylet::emitted
*/
ltEMITTED_TXN = 'E',
};
// clang-format off
/**
@ingroup protocol
*/
enum LedgerSpecificFlags {
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
lsfRequireDestTag =
0x00020000, // True, to require a DestinationTag for payments.
lsfRequireAuth =
0x00040000, // True, to require a authorization to hold IOUs.
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
lsfDisableMaster = 0x00100000, // True, force regular key
lsfNoFreeze = 0x00200000, // True, cannot freeze ripple states
lsfGlobalFreeze = 0x00400000, // True, all assets frozen
lsfDefaultRipple =
0x00800000, // True, trust lines allow rippling by default
lsfDepositAuth = 0x01000000, // True, all deposits require authorization
lsfTshCollect = 0x02000000, // True, allow TSH collect-calls to acc hooks
lsfDisallowIncomingNFTokenOffer =
0x04000000, // True, reject new incoming NFT offers
lsfDisallowIncomingCheck =
0x08000000, // True, reject new checks
lsfDisallowIncomingPayChan =
0x10000000, // True, reject new paychans
lsfDisallowIncomingTrustline =
0x20000000, // True, reject new trustlines (only if no issued assets)
lsfURITokenIssuer =
0x40000000, // True, has minted tokens in the past
lsfDisallowIncomingRemit = // True, no remits allowed to this account
0x80000000,
// 0x0004000 is available
lsfAllowTrustLineClawback =
0x00008000, // True, enable clawback
// ltOFFER
lsfPassive = 0x00010000,
lsfSell = 0x00020000, // True, offer was placed as a sell.
// ltRIPPLE_STATE
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000,
lsfLowNoRipple = 0x00100000,
lsfHighNoRipple = 0x00200000,
lsfLowFreeze = 0x00400000, // True, low side has set freeze flag
lsfHighFreeze = 0x00800000, // True, high side has set freeze flag
lsfAMMNode = 0x01000000, // True, trust line to AMM. Used by client
// apps to identify payments via AMM.
// ltSIGNER_LIST
lsfOneOwnerCount = 0x00010000, // True, uses only one OwnerCount
// ltDIR_NODE
lsfNFTokenBuyOffers = 0x00000001,
lsfNFTokenSellOffers = 0x00000002,
lsfEmittedDir = 0x00000004,
// ltNFTOKEN_OFFER
lsfSellNFToken = 0x00000001,
// ltURI_TOKEN
lsfBurnable = 0x00000001, // True, issuer can burn the token
// remarks
lsfImmutable = 1,
};
//------------------------------------------------------------------------------
/** Holds the list of known ledger entry formats.
*/
class LedgerFormats : public KnownFormats<LedgerEntryType, LedgerFormats>
{
private:
/** Create the object.
This will load the object with all the known ledger formats.
*/
LedgerFormats();
public:
static LedgerFormats const&
getInstance();
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_LEDGERHEADER_H_INCLUDED
#define RIPPLE_PROTOCOL_LEDGERHEADER_H_INCLUDED
#include <ripple/basics/Slice.h>
#include <ripple/basics/XRPAmount.h>
#include <ripple/basics/base_uint.h>
#include <ripple/basics/chrono.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/Serializer.h>
namespace ripple {
/** Information about the notional ledger backing the view. */
struct LedgerHeader
{
explicit LedgerHeader() = default;
//
// For all ledgers
//
LedgerIndex seq = 0;
NetClock::time_point parentCloseTime = {};
//
// For closed ledgers
//
// Closed means "tx set already determined"
uint256 hash = beast::zero;
uint256 txHash = beast::zero;
uint256 accountHash = beast::zero;
uint256 parentHash = beast::zero;
XRPAmount drops = beast::zero;
// If validated is false, it means "not yet validated."
// Once validated is true, it will never be set false at a later time.
// VFALCO TODO Make this not mutable
bool mutable validated = false;
bool accepted = false;
// flags indicating how this ledger close took place
int closeFlags = 0;
// the resolution for this ledger close time (2-120 seconds)
NetClock::duration closeTimeResolution = {};
// For closed ledgers, the time the ledger
// closed. For open ledgers, the time the ledger
// will close if there's no transactions.
//
NetClock::time_point closeTime = {};
};
// We call them "headers" in conversation
// but "info" in code. Unintuitive.
// This alias lets us give the "correct" name to the class
// without yet disturbing existing uses.
using LedgerInfo = LedgerHeader;
// ledger close flags
static std::uint32_t const sLCF_NoConsensusTime = 0x01;
inline bool
getCloseAgree(LedgerHeader const& info)
{
return (info.closeFlags & sLCF_NoConsensusTime) == 0;
}
void
addRaw(LedgerHeader const&, Serializer&, bool includeHash = false);
/** Deserialize a ledger header from a byte array. */
LedgerHeader
deserializeHeader(Slice data, bool hasHash = false);
/** Deserialize a ledger header (prefixed with 4 bytes) from a byte array. */
LedgerHeader
deserializePrefixedHeader(Slice data, bool hasHash = false);
} // namespace ripple
#endif

View File

@@ -0,0 +1,247 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_JSON_MULTIAPIJSON_H_INCLUDED
#define RIPPLE_JSON_MULTIAPIJSON_H_INCLUDED
#include <ripple/json/json_value.h>
#include <ripple/protocol/ApiVersion.h>
#include <array>
#include <cassert>
#include <concepts>
#include <cstdlib>
#include <functional>
#include <limits>
#include <type_traits>
#include <utility>
namespace ripple {
namespace detail {
template <typename T>
constexpr bool is_integral_constant = false;
template <typename I, auto A>
constexpr bool is_integral_constant<std::integral_constant<I, A>&> = true;
template <typename I, auto A>
constexpr bool is_integral_constant<std::integral_constant<I, A> const&> = true;
template <typename T>
concept some_integral_constant = detail::is_integral_constant<T&>;
// This class is designed to wrap a collection of _almost_ identical Json::Value
// objects, indexed by version (i.e. there is some mapping of version to object
// index). It is used e.g. when we need to publish JSON data to users supporting
// different API versions. We allow manipulation and inspection of all objects
// at once with `isMember` and `set`, and also individual inspection and updates
// of an object selected by the user by version, using `visitor_t` nested type.
template <unsigned MinVer, unsigned MaxVer>
struct MultiApiJson
{
static_assert(MinVer <= MaxVer);
static constexpr auto
valid(unsigned int v) noexcept -> bool
{
return v >= MinVer && v <= MaxVer;
}
static constexpr auto
index(unsigned int v) noexcept -> std::size_t
{
return (v < MinVer) ? 0 : static_cast<std::size_t>(v - MinVer);
}
constexpr static std::size_t size = MaxVer + 1 - MinVer;
std::array<Json::Value, size> val = {};
explicit MultiApiJson(Json::Value const& init = {})
{
if (init == Json::Value{})
return; // All elements are already default-initialized
for (auto& v : val)
v = init;
}
void
set(const char* key,
auto const&
v) requires std::constructible_from<Json::Value, decltype(v)>
{
for (auto& a : this->val)
a[key] = v;
}
// Intentionally not using class enum here, MultivarJson is scope enough
enum IsMemberResult : int { none = 0, some, all };
[[nodiscard]] IsMemberResult
isMember(const char* key) const
{
int count = 0;
for (auto& a : this->val)
if (a.isMember(key))
count += 1;
return (count == 0 ? none : (count < size ? some : all));
}
static constexpr struct visitor_t final
{
// integral_constant version, extra arguments
template <
typename Json,
unsigned int Version,
typename... Args,
typename Fn>
requires std::same_as<std::remove_cvref_t<Json>, MultiApiJson> auto
operator()(
Json& json,
std::integral_constant<unsigned int, Version> const version,
Fn fn,
Args&&... args) const
-> std::invoke_result_t<
Fn,
decltype(json.val[0]),
std::integral_constant<unsigned int, Version>,
Args&&...>
{
static_assert(
valid(Version) && index(Version) >= 0 && index(Version) < size);
return std::invoke(
fn,
json.val[index(Version)],
version,
std::forward<Args>(args)...);
}
// integral_constant version, Json only
template <typename Json, unsigned int Version, typename Fn>
requires std::same_as<std::remove_cvref_t<Json>, MultiApiJson> auto
operator()(
Json& json,
std::integral_constant<unsigned int, Version> const,
Fn fn) const -> std::invoke_result_t<Fn, decltype(json.val[0])>
{
static_assert(
valid(Version) && index(Version) >= 0 && index(Version) < size);
return std::invoke(fn, json.val[index(Version)]);
}
// unsigned int version, extra arguments
template <
typename Json,
typename Version,
typename... Args,
typename Fn>
requires(!some_integral_constant<Version>) &&
std::convertible_to<Version, unsigned>&& std::same_as<
std::remove_cvref_t<Json>,
MultiApiJson> auto
operator()(Json& json, Version version, Fn fn, Args&&... args) const
-> std::
invoke_result_t<Fn, decltype(json.val[0]), Version, Args&&...>
{
assert(
valid(version) && index(version) >= 0 && index(version) < size);
return std::invoke(
fn,
json.val[index(version)],
version,
std::forward<Args>(args)...);
}
// unsigned int version, Json only
template <typename Json, typename Version, typename Fn>
requires(!some_integral_constant<Version>) &&
std::convertible_to<Version, unsigned>&& std::
same_as<std::remove_cvref_t<Json>, MultiApiJson> auto
operator()(Json& json, Version version, Fn fn) const
-> std::invoke_result_t<Fn, decltype(json.val[0])>
{
assert(
valid(version) && index(version) >= 0 && index(version) < size);
return std::invoke(fn, json.val[index(version)]);
}
} visitor = {};
auto
visit()
{
return [self = this](auto... args) requires requires
{
visitor(
std::declval<MultiApiJson&>(),
std::declval<decltype(args)>()...);
}
{
return visitor(*self, std::forward<decltype(args)>(args)...);
};
}
auto
visit() const
{
return [self = this](auto... args) requires requires
{
visitor(
std::declval<MultiApiJson const&>(),
std::declval<decltype(args)>()...);
}
{
return visitor(*self, std::forward<decltype(args)>(args)...);
};
}
template <typename... Args>
auto
visit(Args... args)
-> std::invoke_result_t<visitor_t, MultiApiJson&, Args...> requires(
sizeof...(args) > 0) &&
requires
{
visitor(*this, std::forward<decltype(args)>(args)...);
}
{
return visitor(*this, std::forward<decltype(args)>(args)...);
}
template <typename... Args>
auto
visit(Args... args) const -> std::
invoke_result_t<visitor_t, MultiApiJson const&, Args...> requires(
sizeof...(args) > 0) &&
requires
{
visitor(*this, std::forward<decltype(args)>(args)...);
}
{
return visitor(*this, std::forward<decltype(args)>(args)...);
}
};
} // namespace detail
// Wrapper for Json for all supported API versions.
using MultiApiJson = detail::
MultiApiJson<RPC::apiMinimumSupportedVersion, RPC::apiMaximumValidVersion>;
} // namespace ripple
#endif

View File

@@ -0,0 +1,45 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_NFTSYNTHETICSERIALIZER_H_INCLUDED
#define RIPPLE_PROTOCOL_NFTSYNTHETICSERIALIZER_H_INCLUDED
#include <ripple/json/json_forwards.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TxMeta.h>
#include <memory>
namespace ripple {
/**
Adds common synthetic fields to transaction-related JSON responses
@{
*/
void
insertNFTSyntheticInJson(
Json::Value&,
std::shared_ptr<STTx const> const&,
TxMeta const&);
/** @} */
} // namespace ripple
#endif

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_NFTOKENID_H_INCLUDED
#define RIPPLE_PROTOCOL_NFTOKENID_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/json/json_forwards.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TxMeta.h>
#include <memory>
#include <optional>
#include <vector>
namespace ripple {
/**
Add a `nftoken_ids` field to the `meta` output parameter.
The field is only added to successful NFTokenMint, NFTokenAcceptOffer,
and NFTokenCancelOffer transactions.
Helper functions are not static because they can be used by Clio.
@{
*/
bool
canHaveNFTokenID(
std::shared_ptr<STTx const> const& serializedTx,
TxMeta const& transactionMeta);
std::optional<uint256>
getNFTokenIDFromPage(TxMeta const& transactionMeta);
std::vector<uint256>
getNFTokenIDFromDeletedOffer(TxMeta const& transactionMeta);
void
insertNFTokenID(
Json::Value& response,
std::shared_ptr<STTx const> const& transaction,
TxMeta const& transactionMeta);
/** @} */
} // namespace ripple
#endif

View File

@@ -0,0 +1,57 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_NFTOKENOFFERID_H_INCLUDED
#define RIPPLE_PROTOCOL_NFTOKENOFFERID_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/json/json_forwards.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TxMeta.h>
#include <memory>
#include <optional>
namespace ripple {
/**
Add an `offer_id` field to the `meta` output parameter.
The field is only added to successful NFTokenCreateOffer transactions.
Helper functions are not static because they can be used by Clio.
@{
*/
bool
canHaveNFTokenOfferID(
std::shared_ptr<STTx const> const& serializedTx,
TxMeta const& transactionMeta);
std::optional<uint256>
getOfferIDFromCreatedOffer(TxMeta const& transactionMeta);
void
insertNFTokenOfferID(
Json::Value& response,
std::shared_ptr<STTx const> const& transaction,
TxMeta const& transactionMeta);
/** @} */
} // namespace ripple
#endif

View File

@@ -0,0 +1,69 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_PAYCHAN_H_INCLUDED
#define RIPPLE_PROTOCOL_PAYCHAN_H_INCLUDED
#include <ripple/basics/XRPAmount.h>
#include <ripple/basics/base_uint.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/Serializer.h>
namespace ripple {
inline void
serializePayChanAuthorization(
Serializer& msg,
uint256 const& key,
XRPAmount const& amt)
{
msg.add32(HashPrefix::paymentChannelClaim);
msg.addBitString(key);
msg.add64(amt.drops());
}
inline void
serializePayChanAuthorization(
Serializer& msg,
uint256 const& key,
IOUAmount const& amt,
Currency const& cur,
AccountID const& iss)
{
msg.add32(HashPrefix::paymentChannelClaim);
msg.addBitString(key);
if (amt == beast::zero)
msg.add64(STAmount::cNotNative);
else if (amt.signum() == -1) // 512 = not native
msg.add64(
amt.mantissa() |
(static_cast<std::uint64_t>(amt.exponent() + 512 + 97)
<< (64 - 10)));
else // 256 = positive
msg.add64(
amt.mantissa() |
(static_cast<std::uint64_t>(amt.exponent() + 512 + 256 + 97)
<< (64 - 10)));
msg.addBitString(cur);
msg.addBitString(iss);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,139 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_PROTOCOL_H_INCLUDED
#define RIPPLE_PROTOCOL_PROTOCOL_H_INCLUDED
#include <ripple/basics/ByteUtilities.h>
#include <ripple/basics/base_uint.h>
#include <cstdint>
namespace ripple {
/** Protocol specific constants.
This information is, implicitly, part of the protocol.
@note Changing these values without adding code to the
server to detect "pre-change" and "post-change"
will result in a hard fork.
@ingroup protocol
*/
/** Smallest legal byte size of a transaction. */
std::size_t constexpr txMinSizeBytes = 10;
/** Largest legal byte size of a transaction. */
std::size_t constexpr txMaxSizeBytes = megabytes(1);
/** The maximum number of unfunded offers to delete at once */
std::size_t constexpr unfundedOfferRemoveLimit = 1000;
/** The maximum number of expired offers to delete at once */
std::size_t constexpr expiredOfferRemoveLimit = 256;
/** The maximum number of metadata entries allowed in one transaction */
std::size_t constexpr oversizeMetaDataCap = 5200;
/** The maximum number of entries per directory page */
std::size_t constexpr dirNodeMaxEntries = 32;
/** The maximum number of pages allowed in a directory */
std::uint64_t constexpr dirNodeMaxPages = 262144;
/** The maximum number of items in an NFT page */
std::size_t constexpr dirMaxTokensPerPage = 32;
/** The maximum number of owner directory entries for account to be deletable */
std::size_t constexpr maxDeletableDirEntries = 1000;
/** The maximum number of token offers that can be canceled at once */
std::size_t constexpr maxTokenOfferCancelCount = 500;
/** The maximum number of offers in an offer directory for NFT to be burnable */
std::size_t constexpr maxDeletableTokenOfferEntries = 500;
/** The maximum token transfer fee allowed.
Token transfer fees can range from 0% to 50% and are specified in tenths of
a basis point; that is a value of 1000 represents a transfer fee of 1% and
a value of 10000 represents a transfer fee of 10%.
Note that for extremely low transfer fees values, it is possible that the
calculated fee will be 0.
*/
std::uint16_t constexpr maxTransferFee = 50000;
/** The maximum length of a URI inside an NFT */
std::size_t constexpr maxTokenURILength = 256;
/** The maximum length of a Data element inside a DID */
std::size_t constexpr maxDIDDocumentLength = 256;
/** The maximum length of a URI inside a DID */
std::size_t constexpr maxDIDURILength = 256;
/** The maximum length of an Attestation inside a DID */
std::size_t constexpr maxDIDAttestationLength = 256;
/** The maximum length of a domain */
std::size_t constexpr maxDomainLength = 256;
/** A ledger index. */
using LedgerIndex = std::uint32_t;
/** A transaction identifier.
The value is computed as the hash of the
canonicalized, serialized transaction object.
*/
using TxID = uint256;
/** The maximum number of trustlines to delete as part of AMM account
* deletion cleanup.
*/
std::uint16_t constexpr maxDeletableAMMTrustLines = 512;
/** The maximum length of a URI inside an Oracle */
std::size_t constexpr maxOracleURI = 256;
/** The maximum length of a Provider inside an Oracle */
std::size_t constexpr maxOracleProvider = 256;
/** The maximum size of a data series array inside an Oracle */
std::size_t constexpr maxOracleDataSeries = 10;
/** The maximum length of a SymbolClass inside an Oracle */
std::size_t constexpr maxOracleSymbolClass = 16;
/** The maximum allowed time difference between lastUpdateTime and the time
of the last closed ledger
*/
std::size_t constexpr maxLastUpdateTimeDelta = 300;
/** The maximum price scaling factor
*/
std::size_t constexpr maxPriceScale = 20;
/** The maximum percentage of outliers to trim
*/
std::size_t constexpr maxTrim = 25;
} // namespace ripple
#endif

View File

@@ -0,0 +1,293 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_PUBLICKEY_H_INCLUDED
#define RIPPLE_PROTOCOL_PUBLICKEY_H_INCLUDED
#include <ripple/basics/Slice.h>
#include <ripple/protocol/KeyType.h>
#include <ripple/protocol/STExchange.h>
#include <ripple/protocol/UintTypes.h>
#include <ripple/protocol/json_get_or_throw.h>
#include <ripple/protocol/tokens.h>
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <optional>
#include <ostream>
#include <utility>
namespace ripple {
/** A public key.
Public keys are used in the public-key cryptography
system used to verify signatures attached to messages.
The format of the public key is Ripple specific,
information needed to determine the cryptosystem
parameters used is stored inside the key.
As of this writing two systems are supported:
secp256k1
ed25519
secp256k1 public keys consist of a 33 byte
compressed public key, with the lead byte equal
to 0x02 or 0x03.
The ed25519 public keys consist of a 1 byte
prefix constant 0xED, followed by 32 bytes of
public key data.
*/
class PublicKey
{
protected:
// All the constructed public keys are valid, non-empty and contain 33
// bytes of data.
static constexpr std::size_t size_ = 33;
std::uint8_t buf_[size_]; // should be large enough
public:
using const_iterator = std::uint8_t const*;
public:
PublicKey() = delete;
PublicKey(PublicKey const& other);
PublicKey&
operator=(PublicKey const& other);
/** Create a public key.
Preconditions:
publicKeyType(slice) != std::nullopt
*/
explicit PublicKey(Slice const& slice);
std::uint8_t const*
data() const noexcept
{
return buf_;
}
std::size_t
size() const noexcept
{
return size_;
}
const_iterator
begin() const noexcept
{
return buf_;
}
const_iterator
cbegin() const noexcept
{
return buf_;
}
const_iterator
end() const noexcept
{
return buf_ + size_;
}
const_iterator
cend() const noexcept
{
return buf_ + size_;
}
Slice
slice() const noexcept
{
return {buf_, size_};
}
operator Slice() const noexcept
{
return slice();
}
};
/** Print the public key to a stream.
*/
std::ostream&
operator<<(std::ostream& os, PublicKey const& pk);
inline bool
operator==(PublicKey const& lhs, PublicKey const& rhs)
{
return std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
}
inline bool
operator<(PublicKey const& lhs, PublicKey const& rhs)
{
return std::lexicographical_compare(
lhs.data(),
lhs.data() + lhs.size(),
rhs.data(),
rhs.data() + rhs.size());
}
template <class Hasher>
void
hash_append(Hasher& h, PublicKey const& pk)
{
h(pk.data(), pk.size());
}
template <>
struct STExchange<STBlob, PublicKey>
{
explicit STExchange() = default;
using value_type = PublicKey;
static void
get(std::optional<value_type>& t, STBlob const& u)
{
t.emplace(Slice(u.data(), u.size()));
}
static std::unique_ptr<STBlob>
set(SField const& f, PublicKey const& t)
{
return std::make_unique<STBlob>(f, t.data(), t.size());
}
};
//------------------------------------------------------------------------------
inline std::string
toBase58(TokenType type, PublicKey const& pk)
{
return encodeBase58Token(type, pk.data(), pk.size());
}
template <>
std::optional<PublicKey>
parseBase58(TokenType type, std::string const& s);
enum class ECDSACanonicality { canonical, fullyCanonical };
/** Determines the canonicality of a signature.
A canonical signature is in its most reduced form.
For example the R and S components do not contain
additional leading zeroes. However, even in
canonical form, (R,S) and (R,G-S) are both
valid signatures for message M.
Therefore, to prevent malleability attacks we
define a fully canonical signature as one where:
R < G - S
where G is the curve order.
This routine returns std::nullopt if the format
of the signature is invalid (for example, the
points are encoded incorrectly).
@return std::nullopt if the signature fails
validity checks.
@note Only the format of the signature is checked,
no verification cryptography is performed.
*/
std::optional<ECDSACanonicality>
ecdsaCanonicality(Slice const& sig);
/** Returns the type of public key.
@return std::nullopt If the public key does not
represent a known type.
*/
/** @{ */
[[nodiscard]] std::optional<KeyType>
publicKeyType(Slice const& slice);
[[nodiscard]] inline std::optional<KeyType>
publicKeyType(PublicKey const& publicKey)
{
return publicKeyType(publicKey.slice());
}
/** @} */
/** Verify a secp256k1 signature on the digest of a message. */
[[nodiscard]] bool
verifyDigest(
PublicKey const& publicKey,
uint256 const& digest,
Slice const& sig,
bool mustBeFullyCanonical = true) noexcept;
/** Verify a signature on a message.
With secp256k1 signatures, the data is first hashed with
SHA512-Half, and the resulting digest is signed.
*/
[[nodiscard]] bool
verify(
PublicKey const& publicKey,
Slice const& m,
Slice const& sig,
bool mustBeFullyCanonical = true) noexcept;
/** Calculate the 160-bit node ID from a node public key. */
NodeID
calcNodeID(PublicKey const&);
// VFALCO This belongs in AccountID.h but
// is here because of header issues
AccountID
calcAccountID(PublicKey const& pk);
} // namespace ripple
//------------------------------------------------------------------------------
namespace Json {
template <>
inline ripple::PublicKey
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
std::string const b58 = getOrThrow<std::string>(v, field);
if (auto pubKeyBlob = strUnHex(b58); publicKeyType(makeSlice(*pubKeyBlob)))
{
return PublicKey{makeSlice(*pubKeyBlob)};
}
for (auto const tokenType :
{TokenType::NodePublic, TokenType::AccountPublic})
{
if (auto const pk = parseBase58<PublicKey>(tokenType, b58))
return *pk;
}
Throw<JsonTypeMismatchError>(field.getJsonName(), "PublicKey");
}
} // namespace Json
#endif

View File

@@ -0,0 +1,417 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_QUALITY_H_INCLUDED
#define RIPPLE_PROTOCOL_QUALITY_H_INCLUDED
#include <ripple/basics/IOUAmount.h>
#include <ripple/basics/XRPAmount.h>
#include <ripple/protocol/AmountConversions.h>
#include <ripple/protocol/STAmount.h>
#include <algorithm>
#include <cstdint>
#include <ostream>
namespace ripple {
/** Represents a pair of input and output currencies.
The input currency can be converted to the output
currency by multiplying by the rate, represented by
Quality.
For offers, "in" is always TakerPays and "out" is
always TakerGets.
*/
template <class In, class Out>
struct TAmounts
{
TAmounts() = default;
TAmounts(beast::Zero, beast::Zero) : in(beast::zero), out(beast::zero)
{
}
TAmounts(In const& in_, Out const& out_) : in(in_), out(out_)
{
}
/** Returns `true` if either quantity is not positive. */
bool
empty() const noexcept
{
return in <= beast::zero || out <= beast::zero;
}
TAmounts&
operator+=(TAmounts const& rhs)
{
in += rhs.in;
out += rhs.out;
return *this;
}
TAmounts&
operator-=(TAmounts const& rhs)
{
in -= rhs.in;
out -= rhs.out;
return *this;
}
In in;
Out out;
};
using Amounts = TAmounts<STAmount, STAmount>;
template <class In, class Out>
bool
operator==(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
{
return lhs.in == rhs.in && lhs.out == rhs.out;
}
template <class In, class Out>
bool
operator!=(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
{
return !(lhs == rhs);
}
//------------------------------------------------------------------------------
// Ripple specific constant used for parsing qualities and other things
#define QUALITY_ONE 1'000'000'000
/** Represents the logical ratio of output currency to input currency.
Internally this is stored using a custom floating point representation,
as the inverse of the ratio, so that quality will be descending in
a sequence of actual values that represent qualities.
*/
class Quality
{
public:
// Type of the internal representation. Higher qualities
// have lower unsigned integer representations.
using value_type = std::uint64_t;
static const int minTickSize = 3;
static const int maxTickSize = 16;
private:
// This has the same representation as STAmount, see the comment on the
// STAmount. However, this class does not always use the canonical
// representation. In particular, the increment and decrement operators may
// cause a non-canonical representation.
value_type m_value;
public:
Quality() = default;
/** Create a quality from the integer encoding of an STAmount */
explicit Quality(std::uint64_t value);
/** Create a quality from the ratio of two amounts. */
explicit Quality(Amounts const& amount);
/** Create a quality from the ratio of two amounts. */
template <class In, class Out>
explicit Quality(TAmounts<In, Out> const& amount)
: Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out)))
{
}
/** Create a quality from the ratio of two amounts. */
template <class In, class Out>
Quality(Out const& out, In const& in)
: Quality(Amounts(toSTAmount(in), toSTAmount(out)))
{
}
/** Advances to the next higher quality level. */
/** @{ */
Quality&
operator++();
Quality
operator++(int);
/** @} */
/** Advances to the next lower quality level. */
/** @{ */
Quality&
operator--();
Quality
operator--(int);
/** @} */
/** Returns the quality as STAmount. */
STAmount
rate() const
{
return amountFromQuality(m_value);
}
/** Returns the quality rounded up to the specified number
of decimal digits.
*/
Quality
round(int tickSize) const;
/** Returns the scaled amount with in capped.
Math is avoided if the result is exact. The output is clamped
to prevent money creation.
*/
[[nodiscard]] Amounts
ceil_in(Amounts const& amount, STAmount const& limit) const;
template <class In, class Out>
[[nodiscard]] TAmounts<In, Out>
ceil_in(TAmounts<In, Out> const& amount, In const& limit) const;
// Some of the underlying rounding functions called by ceil_in() ignored
// low order bits that could influence rounding decisions. This "strict"
// method uses underlying functions that pay attention to all the bits.
[[nodiscard]] Amounts
ceil_in_strict(Amounts const& amount, STAmount const& limit, bool roundUp)
const;
template <class In, class Out>
[[nodiscard]] TAmounts<In, Out>
ceil_in_strict(
TAmounts<In, Out> const& amount,
In const& limit,
bool roundUp) const;
/** Returns the scaled amount with out capped.
Math is avoided if the result is exact. The input is clamped
to prevent money creation.
*/
[[nodiscard]] Amounts
ceil_out(Amounts const& amount, STAmount const& limit) const;
template <class In, class Out>
[[nodiscard]] TAmounts<In, Out>
ceil_out(TAmounts<In, Out> const& amount, Out const& limit) const;
// Some of the underlying rounding functions called by ceil_out() ignored
// low order bits that could influence rounding decisions. This "strict"
// method uses underlying functions that pay attention to all the bits.
[[nodiscard]] Amounts
ceil_out_strict(Amounts const& amount, STAmount const& limit, bool roundUp)
const;
template <class In, class Out>
[[nodiscard]] TAmounts<In, Out>
ceil_out_strict(
TAmounts<In, Out> const& amount,
Out const& limit,
bool roundUp) const;
private:
// The ceil_in and ceil_out methods that deal in TAmount all convert
// their arguments to STAoumout and convert the result back to TAmount.
// This helper function takes care of all the conversion operations.
template <
class In,
class Out,
class Lim,
typename FnPtr,
std::same_as<bool>... Round>
[[nodiscard]] TAmounts<In, Out>
ceil_TAmounts_helper(
TAmounts<In, Out> const& amount,
Lim const& limit,
Lim const& limit_cmp,
FnPtr ceil_function,
Round... round) const;
public:
/** Returns `true` if lhs is lower quality than `rhs`.
Lower quality means the taker receives a worse deal.
Higher quality is better for the taker.
*/
friend bool
operator<(Quality const& lhs, Quality const& rhs) noexcept
{
return lhs.m_value > rhs.m_value;
}
friend bool
operator>(Quality const& lhs, Quality const& rhs) noexcept
{
return lhs.m_value < rhs.m_value;
}
friend bool
operator<=(Quality const& lhs, Quality const& rhs) noexcept
{
return !(lhs > rhs);
}
friend bool
operator>=(Quality const& lhs, Quality const& rhs) noexcept
{
return !(lhs < rhs);
}
friend bool
operator==(Quality const& lhs, Quality const& rhs) noexcept
{
return lhs.m_value == rhs.m_value;
}
friend bool
operator!=(Quality const& lhs, Quality const& rhs) noexcept
{
return !(lhs == rhs);
}
friend std::ostream&
operator<<(std::ostream& os, Quality const& quality)
{
os << quality.m_value;
return os;
}
// return the relative distance (relative error) between two qualities. This
// is used for testing only. relative distance is abs(a-b)/min(a,b)
friend double
relativeDistance(Quality const& q1, Quality const& q2)
{
assert(q1.m_value > 0 && q2.m_value > 0);
if (q1.m_value == q2.m_value) // make expected common case fast
return 0;
auto const [minV, maxV] = std::minmax(q1.m_value, q2.m_value);
auto mantissa = [](std::uint64_t rate) {
return rate & ~(255ull << (64 - 8));
};
auto exponent = [](std::uint64_t rate) {
return static_cast<int>(rate >> (64 - 8)) - 100;
};
auto const minVMantissa = mantissa(minV);
auto const maxVMantissa = mantissa(maxV);
auto const expDiff = exponent(maxV) - exponent(minV);
double const minVD = static_cast<double>(minVMantissa);
double const maxVD = expDiff ? maxVMantissa * pow(10, expDiff)
: static_cast<double>(maxVMantissa);
// maxVD and minVD are scaled so they have the same exponents. Dividing
// cancels out the exponents, so we only need to deal with the (scaled)
// mantissas
return (maxVD - minVD) / minVD;
}
};
template <
class In,
class Out,
class Lim,
typename FnPtr,
std::same_as<bool>... Round>
TAmounts<In, Out>
Quality::ceil_TAmounts_helper(
TAmounts<In, Out> const& amount,
Lim const& limit,
Lim const& limit_cmp,
FnPtr ceil_function,
Round... roundUp) const
{
if (limit_cmp <= limit)
return amount;
// Use the existing STAmount implementation for now, but consider
// replacing with code specific to IOUAMount and XRPAmount
Amounts stAmt(toSTAmount(amount.in), toSTAmount(amount.out));
STAmount stLim(toSTAmount(limit));
Amounts const stRes = ((*this).*ceil_function)(stAmt, stLim, roundUp...);
return TAmounts<In, Out>(toAmount<In>(stRes.in), toAmount<Out>(stRes.out));
}
template <class In, class Out>
TAmounts<In, Out>
Quality::ceil_in(TAmounts<In, Out> const& amount, In const& limit) const
{
// Construct a function pointer to the function we want to call.
static constexpr Amounts (Quality::*ceil_in_fn_ptr)(
Amounts const&, STAmount const&) const = &Quality::ceil_in;
return ceil_TAmounts_helper(amount, limit, amount.in, ceil_in_fn_ptr);
}
template <class In, class Out>
TAmounts<In, Out>
Quality::ceil_in_strict(
TAmounts<In, Out> const& amount,
In const& limit,
bool roundUp) const
{
// Construct a function pointer to the function we want to call.
static constexpr Amounts (Quality::*ceil_in_fn_ptr)(
Amounts const&, STAmount const&, bool) const = &Quality::ceil_in_strict;
return ceil_TAmounts_helper(
amount, limit, amount.in, ceil_in_fn_ptr, roundUp);
}
template <class In, class Out>
TAmounts<In, Out>
Quality::ceil_out(TAmounts<In, Out> const& amount, Out const& limit) const
{
// Construct a function pointer to the function we want to call.
static constexpr Amounts (Quality::*ceil_out_fn_ptr)(
Amounts const&, STAmount const&) const = &Quality::ceil_out;
return ceil_TAmounts_helper(amount, limit, amount.out, ceil_out_fn_ptr);
}
template <class In, class Out>
TAmounts<In, Out>
Quality::ceil_out_strict(
TAmounts<In, Out> const& amount,
Out const& limit,
bool roundUp) const
{
// Construct a function pointer to the function we want to call.
static constexpr Amounts (Quality::*ceil_out_fn_ptr)(
Amounts const&, STAmount const&, bool) const =
&Quality::ceil_out_strict;
return ceil_TAmounts_helper(
amount, limit, amount.out, ceil_out_fn_ptr, roundUp);
}
/** Calculate the quality of a two-hop path given the two hops.
@param lhs The first leg of the path: input to intermediate.
@param rhs The second leg of the path: intermediate to output.
*/
Quality
composed_quality(Quality const& lhs, Quality const& rhs);
} // namespace ripple
#endif

View File

@@ -0,0 +1,107 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_QUALITYFUNCTION_H_INCLUDED
#define RIPPLE_PROTOCOL_QUALITYFUNCTION_H_INCLUDED
#include <ripple/basics/Number.h>
#include <ripple/protocol/AMMCore.h>
#include <ripple/protocol/Quality.h>
namespace ripple {
/** Average quality of a path as a function of `out`: q(out) = m * out + b,
* where m = -1 / poolGets, b = poolPays / poolGets. If CLOB offer then
* `m` is equal to 0 `b` is equal to the offer's quality. The function
* is derived by substituting `in` in q = out / in with the swap out formula
* for `in`:
* in = [(poolGets * poolPays) / (poolGets - out) - poolPays] / (1 - tfee)
* and combining the function for multiple steps. The function is used
* to limit required output amount when quality limit is provided in one
* path optimization.
*/
class QualityFunction
{
private:
// slope
Number m_;
// intercept
Number b_;
// seated if QF is for CLOB offer.
std::optional<Quality> quality_;
public:
struct AMMTag
{
};
// AMMOffer for multi-path is like CLOB, i.e. the offer size
// changes proportionally to its quality.
struct CLOBLikeTag
{
};
QualityFunction(Quality const& quality, CLOBLikeTag);
template <typename TIn, typename TOut>
QualityFunction(
TAmounts<TIn, TOut> const& amounts,
std::uint32_t tfee,
AMMTag);
/** Combines QF with the next step QF
*/
void
combine(QualityFunction const& qf);
/** Find output to produce the requested
* average quality.
* @param quality requested average quality (quality limit)
*/
std::optional<Number>
outFromAvgQ(Quality const& quality);
/** Return true if the quality function is constant
*/
bool
isConst() const
{
return quality_.has_value();
}
std::optional<Quality> const&
quality() const
{
return quality_;
}
};
template <typename TIn, typename TOut>
QualityFunction::QualityFunction(
TAmounts<TIn, TOut> const& amounts,
std::uint32_t tfee,
QualityFunction::AMMTag)
{
if (amounts.in <= beast::zero || amounts.out <= beast::zero)
Throw<std::runtime_error>("QualityFunction amounts are 0.");
Number const cfee = feeMult(tfee);
m_ = -cfee / amounts.in;
b_ = amounts.out * cfee / amounts.in;
}
} // namespace ripple
#endif // RIPPLE_PROTOCOL_QUALITYFUNCTION_H_INCLUDED

View File

@@ -0,0 +1,44 @@
# protocol
Classes and functions for handling data and
values associated with the XRP Ledger protocol.
## Serialized Objects
Objects transmitted over the network must be
serialized into a canonical format. The prefix "ST" refers
to classes that deal with the serialized format.
The term "Tx" or "tx" is an abbreviation for "Transaction",
a commonly occurring object type.
### Optional Fields
Our serialized fields have some "type magic" to make
optional fields easier to read:
- The operation `x[sfFoo]` means "return the value of 'Foo'
if it exists, or the default value if it doesn't."
- The operation `x[~sfFoo]` means "return the value of 'Foo'
if it exists, or nothing if it doesn't." This usage of the
tilde/bitwise NOT operator is not standard outside of the
`rippled` codebase.
- As a consequence of this, `x[~sfFoo] = y[~sfFoo]`
assigns the value of Foo from y to x, including omitting
Foo from x if it doesn't exist in y.
Typically, for things that are guaranteed to exist, you use
`x[sfFoo]` and avoid having to deal with a container that may
or may not hold a value. For things not guaranteed to exist,
you use `x[~sfFoo]` because you want such a container. It
avoids having to look something up twice, once just to see if
it exists and a second time to get/set its value.
([Real example](https://github.com/ripple/rippled/blob/35f4698aed5dce02f771b34cfbb690495cb5efcc/src/ripple/app/tx/impl/PayChan.cpp#L229-L236))
The source of this "type magic" is in
[SField.h](./SField.h#L296-L302).
### Related Resources
- [ripple-binary-codec SField enums](https://github.com/XRPLF/xrpl.js/tree/main/packages/ripple-binary-codec/src/enums)
- [SFCode Registry Tables](https://github.com/XRPLF/sFieldRegistry)

View File

@@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
/*
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_NET_RPCERR_H_INCLUDED
#define RIPPLE_NET_RPCERR_H_INCLUDED
#include <ripple/json/json_value.h>
namespace ripple {
// VFALCO NOTE these are deprecated
bool
isRpcError(Json::Value jvResult);
Json::Value
rpcError(int iError, std::string msg = "");
} // namespace ripple
#endif

View File

@@ -0,0 +1,105 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2015 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_PROTOCOL_RATE_H_INCLUDED
#define RIPPLE_PROTOCOL_RATE_H_INCLUDED
#include <ripple/protocol/STAmount.h>
#include <boost/operators.hpp>
#include <cassert>
#include <cstdint>
#include <ostream>
namespace ripple {
/** Represents a transfer rate
Transfer rates are specified as fractions of 1 billion.
For example, a transfer rate of 1% is represented as
1,010,000,000.
*/
struct Rate : private boost::totally_ordered<Rate>
{
std::uint32_t value;
Rate() = delete;
explicit Rate(std::uint32_t rate) : value(rate)
{
}
};
inline bool
operator==(Rate const& lhs, Rate const& rhs) noexcept
{
return lhs.value == rhs.value;
}
inline bool
operator<(Rate const& lhs, Rate const& rhs) noexcept
{
return lhs.value < rhs.value;
}
inline std::ostream&
operator<<(std::ostream& os, Rate const& rate)
{
os << rate.value;
return os;
}
STAmount
multiply(STAmount const& amount, Rate const& rate);
STAmount
multiplyRound(STAmount const& amount, Rate const& rate, bool roundUp);
STAmount
multiplyRound(
STAmount const& amount,
Rate const& rate,
Issue const& issue,
bool roundUp);
STAmount
divide(STAmount const& amount, Rate const& rate);
STAmount
divideRound(STAmount const& amount, Rate const& rate, bool roundUp);
STAmount
divideRound(
STAmount const& amount,
Rate const& rate,
Issue const& issue,
bool roundUp);
namespace nft {
/** Given a transfer fee (in basis points) convert it to a transfer rate. */
Rate
transferFeeAsRate(std::uint16_t fee);
} // namespace nft
/** A transfer rate signifying a 1:1 exchange */
extern Rate const parityRate;
} // namespace ripple
#endif

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_RIPPLELEDGERHASH_H_INCLUDED
#define RIPPLE_PROTOCOL_RIPPLELEDGERHASH_H_INCLUDED
#include <ripple/basics/base_uint.h>
namespace ripple {
using LedgerHash = uint256;
}
#endif

View File

@@ -0,0 +1,132 @@
//------------------------------------------------------------------------------
/*
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_LEDGER_RULES_H_INCLUDED
#define RIPPLE_LEDGER_RULES_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/beast/hash/uhash.h>
#include <ripple/protocol/STVector256.h>
#include <unordered_set>
namespace ripple {
class DigestAwareReadView;
/** Rules controlling protocol behavior. */
class Rules
{
private:
class Impl;
// Carrying impl by shared_ptr makes Rules comparatively cheap to pass
// by value.
std::shared_ptr<Impl const> impl_;
public:
Rules(Rules const&) = default;
Rules(Rules&&) = default;
Rules&
operator=(Rules const&) = default;
Rules&
operator=(Rules&&) = default;
Rules() = delete;
/** Construct an empty rule set.
These are the rules reflected by
the genesis ledger.
*/
explicit Rules(std::unordered_set<uint256, beast::uhash<>> const& presets);
private:
// Allow a friend function to construct Rules.
friend Rules
makeRulesGivenLedger(
DigestAwareReadView const& ledger,
Rules const& current);
friend Rules
makeRulesGivenLedger(
DigestAwareReadView const& ledger,
std::unordered_set<uint256, beast::uhash<>> const& presets);
public:
Rules(
std::unordered_set<uint256, beast::uhash<>> const& presets,
std::optional<uint256> const& digest,
STVector256 const& amendments);
std::unordered_set<uint256, beast::uhash<>> const&
presets() const;
public:
/** Returns `true` if a feature is enabled. */
bool
enabled(uint256 const& feature) const;
/** Returns `true` if two rule sets are identical.
@note This is for diagnostics.
*/
bool
operator==(Rules const&) const;
bool
operator!=(Rules const& other) const;
};
std::optional<Rules> const&
getCurrentTransactionRules();
void
setCurrentTransactionRules(std::optional<Rules> r);
/** RAII class to set and restore the current transaction rules
*/
class CurrentTransactionRulesGuard
{
public:
explicit CurrentTransactionRulesGuard(Rules r)
: saved_(getCurrentTransactionRules())
{
setCurrentTransactionRules(std::move(r));
}
~CurrentTransactionRulesGuard()
{
setCurrentTransactionRules(saved_);
}
CurrentTransactionRulesGuard() = delete;
CurrentTransactionRulesGuard(CurrentTransactionRulesGuard const&) = delete;
CurrentTransactionRulesGuard&
operator=(CurrentTransactionRulesGuard const&) = delete;
private:
std::optional<Rules> saved_;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,721 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SFIELD_H_INCLUDED
#define RIPPLE_PROTOCOL_SFIELD_H_INCLUDED
#include <ripple/basics/safe_cast.h>
#include <ripple/json/json_value.h>
#include <cstdint>
#include <map>
#include <utility>
namespace ripple {
/*
Some fields have a different meaning for their
default value versus not present.
Example:
QualityIn on a TrustLine
*/
//------------------------------------------------------------------------------
// Forwards
class STAccount;
class STAmount;
class STIssue;
class STBlob;
template <int>
class STBitString;
template <class>
class STInteger;
class STXChainBridge;
class STVector256;
class STCurrency;
class Definitions;
#pragma push_macro("XMACRO")
#undef XMACRO
#define XMACRO(STYPE) \
/* special types */ \
STYPE(STI_UNKNOWN, -2) \
STYPE(STI_NOTPRESENT, 0) \
STYPE(STI_UINT16, 1) \
\
/* types (common) */ \
STYPE(STI_UINT32, 2) \
STYPE(STI_UINT64, 3) \
STYPE(STI_UINT128, 4) \
STYPE(STI_UINT256, 5) \
STYPE(STI_AMOUNT, 6) \
STYPE(STI_VL, 7) \
STYPE(STI_ACCOUNT, 8) \
\
/* 9-13 are reserved */ \
STYPE(STI_OBJECT, 14) \
STYPE(STI_ARRAY, 15) \
\
/* types (uncommon) */ \
STYPE(STI_UINT8, 16) \
STYPE(STI_UINT160, 17) \
STYPE(STI_PATHSET, 18) \
STYPE(STI_VECTOR256, 19) \
STYPE(STI_UINT96, 20) \
STYPE(STI_UINT192, 21) \
STYPE(STI_UINT384, 22) \
STYPE(STI_UINT512, 23) \
STYPE(STI_ISSUE, 24) \
STYPE(STI_XCHAIN_BRIDGE, 25) \
STYPE(STI_CURRENCY, 26) \
\
/* high-level types */ \
/* cannot be serialized inside other types */ \
STYPE(STI_TRANSACTION, 10001) \
STYPE(STI_LEDGERENTRY, 10002) \
STYPE(STI_VALIDATION, 10003) \
STYPE(STI_METADATA, 10004)
#pragma push_macro("TO_ENUM")
#undef TO_ENUM
#pragma push_macro("TO_MAP")
#undef TO_MAP
#define TO_ENUM(name, value) name = value,
#define TO_MAP(name, value) {#name, value},
enum SerializedTypeID { XMACRO(TO_ENUM) };
static std::map<std::string, int> const sTypeMap = {XMACRO(TO_MAP)};
#undef XMACRO
#undef TO_ENUM
#pragma pop_macro("XMACRO")
#pragma pop_macro("TO_ENUM")
#pragma pop_macro("TO_MAP")
// constexpr
inline int
field_code(SerializedTypeID id, int index)
{
return (safe_cast<int>(id) << 16) | index;
}
// constexpr
inline int
field_code(int id, int index)
{
return (id << 16) | index;
}
/** Identifies fields.
Fields are necessary to tag data in signed transactions so that
the binary format of the transaction can be canonicalized. All
SFields are created at compile time.
Each SField, once constructed, lives until program termination, and there
is only one instance per fieldType/fieldValue pair which serves the entire
application.
*/
class SField
{
public:
enum {
sMD_Never = 0x00,
sMD_ChangeOrig = 0x01, // original value when it changes
sMD_ChangeNew = 0x02, // new value when it changes
sMD_DeleteFinal = 0x04, // final value when it is deleted
sMD_Create = 0x08, // value when it's created
sMD_Always = 0x10, // value when node containing it is affected at all
sMD_Default =
sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create
};
enum class IsSigning : unsigned char { no, yes };
static IsSigning const notSigning = IsSigning::no;
int const fieldCode; // (type<<16)|index
SerializedTypeID const fieldType; // STI_*
int const fieldValue; // Code number for protocol
std::string const fieldName;
int const fieldMeta;
int const fieldNum;
IsSigning const signingField;
Json::StaticString const jsonName;
SField(SField const&) = delete;
SField&
operator=(SField const&) = delete;
SField(SField&&) = delete;
SField&
operator=(SField&&) = delete;
public:
struct private_access_tag_t; // public, but still an implementation detail
// These constructors can only be called from SField.cpp
SField(
private_access_tag_t,
SerializedTypeID tid,
int fv,
const char* fn,
int meta = sMD_Default,
IsSigning signing = IsSigning::yes);
explicit SField(private_access_tag_t, int fc);
static const SField&
getField(int fieldCode);
static const SField&
getField(std::string const& fieldName);
static const SField&
getField(int type, int value)
{
return getField(field_code(type, value));
}
static const SField&
getField(SerializedTypeID type, int value)
{
return getField(field_code(type, value));
}
std::string const&
getName() const
{
return fieldName;
}
bool
hasName() const
{
return fieldCode > 0;
}
Json::StaticString const&
getJsonName() const
{
return jsonName;
}
bool
isInvalid() const
{
return fieldCode == -1;
}
bool
isUseful() const
{
return fieldCode > 0;
}
bool
isBinary() const
{
return fieldValue < 256;
}
// A discardable field is one that cannot be serialized, and
// should be discarded during serialization,like 'hash'.
// You cannot serialize an object's hash inside that object,
// but you can have it in the JSON representation.
bool
isDiscardable() const
{
return fieldValue > 256;
}
int
getCode() const
{
return fieldCode;
}
int
getNum() const
{
return fieldNum;
}
static int
getNumFields()
{
return num;
}
bool
shouldMeta(int c) const
{
return (fieldMeta & c) != 0;
}
bool
shouldInclude(bool withSigningField) const
{
return (fieldValue < 256) &&
(withSigningField || (signingField == IsSigning::yes));
}
bool
operator==(const SField& f) const
{
return fieldCode == f.fieldCode;
}
bool
operator!=(const SField& f) const
{
return fieldCode != f.fieldCode;
}
static int
compare(const SField& f1, const SField& f2);
static std::map<int, SField const*> knownCodeToField;
private:
static int num;
};
/** A field with a type known at compile time. */
template <class T>
struct TypedField : SField
{
using type = T;
template <class... Args>
explicit TypedField(private_access_tag_t pat, Args&&... args);
};
/** Indicate std::optional field semantics. */
template <class T>
struct OptionaledField
{
TypedField<T> const* f;
explicit OptionaledField(TypedField<T> const& f_) : f(&f_)
{
}
};
template <class T>
inline OptionaledField<T>
operator~(TypedField<T> const& f)
{
return OptionaledField<T>(f);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using SF_UINT8 = TypedField<STInteger<std::uint8_t>>;
using SF_UINT16 = TypedField<STInteger<std::uint16_t>>;
using SF_UINT32 = TypedField<STInteger<std::uint32_t>>;
using SF_UINT64 = TypedField<STInteger<std::uint64_t>>;
using SF_UINT96 = TypedField<STBitString<96>>;
using SF_UINT128 = TypedField<STBitString<128>>;
using SF_UINT160 = TypedField<STBitString<160>>;
using SF_UINT192 = TypedField<STBitString<192>>;
using SF_UINT256 = TypedField<STBitString<256>>;
using SF_UINT384 = TypedField<STBitString<384>>;
using SF_UINT512 = TypedField<STBitString<512>>;
using SF_ACCOUNT = TypedField<STAccount>;
using SF_AMOUNT = TypedField<STAmount>;
using SF_ISSUE = TypedField<STIssue>;
using SF_CURRENCY = TypedField<STCurrency>;
using SF_VL = TypedField<STBlob>;
using SF_VECTOR256 = TypedField<STVector256>;
using SF_XCHAIN_BRIDGE = TypedField<STXChainBridge>;
//------------------------------------------------------------------------------
extern SField const sfInvalid;
extern SField const sfGeneric;
extern SField const sfLedgerEntry;
extern SField const sfTransaction;
extern SField const sfValidation;
extern SField const sfMetadata;
// 8-bit integers (common)
extern SF_UINT8 const sfCloseResolution;
extern SF_UINT8 const sfMethod;
extern SF_UINT8 const sfTransactionResult;
extern SF_UINT8 const sfWasLockingChainSend;
extern SF_UINT8 const sfScale;
// 8-bit integers (uncommon)
extern SF_UINT8 const sfTickSize;
extern SF_UINT8 const sfUNLModifyDisabling;
extern SF_UINT8 const sfHookResult;
// 16-bit integers (common)
extern SF_UINT16 const sfLedgerEntryType;
extern SF_UINT16 const sfTransactionType;
extern SF_UINT16 const sfSignerWeight;
extern SF_UINT16 const sfTransferFee;
extern SF_UINT16 const sfTradingFee;
// 16-bit integers (uncommon)
extern SF_UINT16 const sfVersion;
extern SF_UINT16 const sfHookStateChangeCount;
extern SF_UINT16 const sfHookEmitCount;
extern SF_UINT16 const sfHookExecutionIndex;
extern SF_UINT16 const sfHookApiVersion;
extern SF_UINT16 const sfDiscountedFee;
// 32-bit integers (common)
extern SF_UINT32 const sfNetworkID;
extern SF_UINT32 const sfFlags;
extern SF_UINT32 const sfSourceTag;
extern SF_UINT32 const sfSequence;
extern SF_UINT32 const sfPreviousTxnLgrSeq;
extern SF_UINT32 const sfLedgerSequence;
extern SF_UINT32 const sfCloseTime;
extern SF_UINT32 const sfParentCloseTime;
extern SF_UINT32 const sfSigningTime;
extern SF_UINT32 const sfExpiration;
extern SF_UINT32 const sfTransferRate;
extern SF_UINT32 const sfWalletSize;
extern SF_UINT32 const sfOwnerCount;
extern SF_UINT32 const sfDestinationTag;
extern SF_UINT32 const sfLastUpdateTime;
// 32-bit integers (uncommon)
extern SF_UINT32 const sfHighQualityIn;
extern SF_UINT32 const sfHighQualityOut;
extern SF_UINT32 const sfLowQualityIn;
extern SF_UINT32 const sfLowQualityOut;
extern SF_UINT32 const sfQualityIn;
extern SF_UINT32 const sfQualityOut;
extern SF_UINT32 const sfStampEscrow;
extern SF_UINT32 const sfBondAmount;
extern SF_UINT32 const sfLoadFee;
extern SF_UINT32 const sfOfferSequence;
extern SF_UINT32 const sfFirstLedgerSequence;
extern SF_UINT32 const sfLastLedgerSequence;
extern SF_UINT32 const sfTransactionIndex;
extern SF_UINT32 const sfOperationLimit;
extern SF_UINT32 const sfReferenceFeeUnits;
extern SF_UINT32 const sfReserveBase;
extern SF_UINT32 const sfReserveIncrement;
extern SF_UINT32 const sfSetFlag;
extern SF_UINT32 const sfClearFlag;
extern SF_UINT32 const sfSignerQuorum;
extern SF_UINT32 const sfCancelAfter;
extern SF_UINT32 const sfFinishAfter;
extern SF_UINT32 const sfSignerListID;
extern SF_UINT32 const sfSettleDelay;
extern SF_UINT32 const sfTicketCount;
extern SF_UINT32 const sfTicketSequence;
extern SF_UINT32 const sfNFTokenTaxon;
extern SF_UINT32 const sfMintedNFTokens;
extern SF_UINT32 const sfBurnedNFTokens;
extern SF_UINT32 const sfHookStateCount;
extern SF_UINT32 const sfEmitGeneration;
extern SF_UINT32 const sfVoteWeight;
extern SF_UINT32 const sfLockCount;
extern SF_UINT32 const sfRewardTime;
extern SF_UINT32 const sfRewardLgrFirst;
extern SF_UINT32 const sfRewardLgrLast;
extern SF_UINT32 const sfFirstNFTokenSequence;
extern SF_UINT32 const sfImportSequence;
extern SF_UINT32 const sfXahauActivationLgrSeq;
extern SF_UINT32 const sfOracleDocumentID;
// 64-bit integers (common)
extern SF_UINT64 const sfIndexNext;
extern SF_UINT64 const sfIndexPrevious;
extern SF_UINT64 const sfBookNode;
extern SF_UINT64 const sfOwnerNode;
extern SF_UINT64 const sfBaseFee;
extern SF_UINT64 const sfExchangeRate;
extern SF_UINT64 const sfLowNode;
extern SF_UINT64 const sfHighNode;
extern SF_UINT64 const sfDestinationNode;
extern SF_UINT64 const sfCookie;
extern SF_UINT64 const sfServerVersion;
extern SF_UINT64 const sfEmitBurden;
extern SF_UINT64 const sfNFTokenOfferNode;
// 64-bit integers (uncommon)
extern SF_UINT64 const sfHookInstructionCount;
extern SF_UINT64 const sfHookReturnCode;
extern SF_UINT64 const sfReferenceCount;
extern SF_UINT64 const sfRewardAccumulator;
extern SF_UINT64 const sfAccountCount;
extern SF_UINT64 const sfAccountIndex;
extern SF_UINT64 const sfTouchCount;
extern SF_UINT64 const sfXChainClaimID;
extern SF_UINT64 const sfXChainAccountCreateCount;
extern SF_UINT64 const sfXChainAccountClaimCount;
extern SF_UINT64 const sfAssetPrice;
// 128-bit
extern SF_UINT128 const sfEmailHash;
// 160-bit (common)
extern SF_UINT160 const sfTakerPaysCurrency;
extern SF_UINT160 const sfTakerPaysIssuer;
extern SF_UINT160 const sfTakerGetsCurrency;
extern SF_UINT160 const sfTakerGetsIssuer;
// 256-bit (common)
extern SF_UINT256 const sfLedgerHash;
extern SF_UINT256 const sfParentHash;
extern SF_UINT256 const sfTransactionHash;
extern SF_UINT256 const sfAccountHash;
extern SF_UINT256 const sfHookOn;
extern SF_UINT256 const sfHookCanEmit;
extern SF_UINT256 const sfPreviousTxnID;
extern SF_UINT256 const sfLedgerIndex;
extern SF_UINT256 const sfWalletLocator;
extern SF_UINT256 const sfRootIndex;
extern SF_UINT256 const sfAccountTxnID;
extern SF_UINT256 const sfNFTokenID;
extern SF_UINT256 const sfEmitParentTxnID;
extern SF_UINT256 const sfEmitNonce;
extern SF_UINT256 const sfEmitHookHash;
extern SF_UINT256 const sfObjectID;
extern SF_UINT256 const sfAMMID;
// 256-bit (uncommon)
extern SF_UINT256 const sfBookDirectory;
extern SF_UINT256 const sfInvoiceID;
extern SF_UINT256 const sfNickname;
extern SF_UINT256 const sfAmendment;
extern SF_UINT256 const sfDigest;
extern SF_UINT256 const sfChannel;
extern SF_UINT256 const sfConsensusHash;
extern SF_UINT256 const sfCheckID;
extern SF_UINT256 const sfValidatedHash;
extern SF_UINT256 const sfPreviousPageMin;
extern SF_UINT256 const sfNextPageMin;
extern SF_UINT256 const sfNFTokenBuyOffer;
extern SF_UINT256 const sfNFTokenSellOffer;
extern SF_UINT256 const sfHookStateKey;
extern SF_UINT256 const sfHookHash;
extern SF_UINT256 const sfHookNamespace;
extern SF_UINT256 const sfHookSetTxnID;
extern SF_UINT256 const sfOfferID;
extern SF_UINT256 const sfEscrowID;
extern SF_UINT256 const sfURITokenID;
extern SF_UINT256 const sfGovernanceFlags;
extern SF_UINT256 const sfGovernanceMarks;
extern SF_UINT256 const sfEmittedTxnID;
// currency amount (common)
extern SF_AMOUNT const sfAmount;
extern SF_AMOUNT const sfBalance;
extern SF_AMOUNT const sfLimitAmount;
extern SF_AMOUNT const sfTakerPays;
extern SF_AMOUNT const sfTakerGets;
extern SF_AMOUNT const sfLowLimit;
extern SF_AMOUNT const sfHighLimit;
extern SF_AMOUNT const sfFee;
extern SF_AMOUNT const sfSendMax;
extern SF_AMOUNT const sfDeliverMin;
extern SF_AMOUNT const sfLockedBalance;
extern SF_AMOUNT const sfAmount2;
extern SF_AMOUNT const sfEPrice;
extern SF_AMOUNT const sfBidMin;
extern SF_AMOUNT const sfBidMax;
extern SF_AMOUNT const sfPrice;
extern SF_AMOUNT const sfLPTokenBalance;
// currency amount (uncommon)
extern SF_AMOUNT const sfMinimumOffer;
extern SF_AMOUNT const sfRippleEscrow;
extern SF_AMOUNT const sfDeliveredAmount;
extern SF_AMOUNT const sfNFTokenBrokerFee;
extern SF_AMOUNT const sfHookCallbackFee;
extern SF_AMOUNT const sfLPTokenOut;
extern SF_AMOUNT const sfLPTokenIn;
// currency amount (fees)
extern SF_AMOUNT const sfBaseFeeDrops;
extern SF_AMOUNT const sfReserveBaseDrops;
extern SF_AMOUNT const sfReserveIncrementDrops;
extern SF_AMOUNT const sfSignatureReward;
extern SF_AMOUNT const sfMinAccountCreateAmount;
// variable length (common)
extern SF_VL const sfPublicKey;
extern SF_VL const sfMessageKey;
extern SF_VL const sfSigningPubKey;
extern SF_VL const sfTxnSignature;
extern SF_VL const sfURI;
extern SF_VL const sfSignature;
extern SF_VL const sfDomain;
extern SF_VL const sfFundCode;
extern SF_VL const sfRemoveCode;
extern SF_VL const sfExpireCode;
extern SF_VL const sfCreateCode;
extern SF_VL const sfMemoType;
extern SF_VL const sfMemoData;
extern SF_VL const sfMemoFormat;
extern SF_VL const sfDIDDocument;
extern SF_VL const sfData;
extern SF_VL const sfAssetClass;
extern SF_VL const sfProvider;
// variable length (uncommon)
extern SF_VL const sfFulfillment;
extern SF_VL const sfCondition;
extern SF_VL const sfMasterSignature;
extern SF_VL const sfUNLModifyValidator;
extern SF_VL const sfValidatorToDisable;
extern SF_VL const sfValidatorToReEnable;
extern SF_VL const sfHookStateData;
extern SF_VL const sfHookReturnString;
extern SF_VL const sfHookParameterName;
extern SF_VL const sfHookParameterValue;
extern SF_VL const sfBlob;
extern SF_VL const sfRemarkName;
extern SF_VL const sfRemarkValue;
// account
extern SF_ACCOUNT const sfAccount;
extern SF_ACCOUNT const sfOwner;
extern SF_ACCOUNT const sfDestination;
extern SF_ACCOUNT const sfIssuer;
extern SF_ACCOUNT const sfAuthorize;
extern SF_ACCOUNT const sfUnauthorize;
extern SF_ACCOUNT const sfRegularKey;
extern SF_ACCOUNT const sfNFTokenMinter;
extern SF_ACCOUNT const sfEmitCallback;
// account (uncommon)
extern SF_ACCOUNT const sfHookAccount;
extern SF_ACCOUNT const sfNFTokenMinter;
extern SF_ACCOUNT const sfInform;
extern SF_ACCOUNT const sfOtherChainSource;
extern SF_ACCOUNT const sfOtherChainDestination;
extern SF_ACCOUNT const sfAttestationSignerAccount;
extern SF_ACCOUNT const sfAttestationRewardAccount;
extern SF_ACCOUNT const sfLockingChainDoor;
extern SF_ACCOUNT const sfIssuingChainDoor;
// path set
extern SField const sfPaths;
// currency
extern SF_CURRENCY const sfBaseAsset;
extern SF_CURRENCY const sfQuoteAsset;
// issue
extern SF_ISSUE const sfAsset;
extern SF_ISSUE const sfAsset2;
extern SF_ISSUE const sfLockingChainIssue;
extern SF_ISSUE const sfIssuingChainIssue;
// bridge
extern SF_XCHAIN_BRIDGE const sfXChainBridge;
// vector of 256-bit
extern SF_VECTOR256 const sfIndexes;
extern SF_VECTOR256 const sfHashes;
extern SF_VECTOR256 const sfAmendments;
extern SF_VECTOR256 const sfNFTokenOffers;
extern SF_VECTOR256 const sfHookNamespaces;
extern SF_VECTOR256 const sfURITokenIDs;
// inner object
// OBJECT/1 is reserved for end of object
extern SField const sfTransactionMetaData;
extern SField const sfCreatedNode;
extern SField const sfDeletedNode;
extern SField const sfModifiedNode;
extern SField const sfPreviousFields;
extern SField const sfFinalFields;
extern SField const sfNewFields;
extern SField const sfTemplateEntry;
extern SField const sfMemo;
extern SField const sfSignerEntry;
extern SField const sfNFToken;
extern SField const sfEmitDetails;
extern SField const sfHook;
extern SField const sfVoteEntry;
extern SField const sfAuctionSlot;
extern SField const sfAuthAccount;
extern SField const sfPriceData;
extern SField const sfSigner;
extern SField const sfMajority;
extern SField const sfDisabledValidator;
extern SField const sfEmittedTxn;
extern SField const sfHookExecution;
extern SField const sfHookDefinition;
extern SField const sfHookParameter;
extern SField const sfHookGrant;
extern SField const sfActiveValidator;
extern SField const sfImportVLKey;
extern SField const sfHookEmission;
extern SField const sfMintURIToken;
extern SField const sfAmountEntry;
extern SField const sfRemark;
extern SField const sfXChainClaimProofSig;
extern SField const sfXChainCreateAccountProofSig;
extern SField const sfXChainClaimAttestationCollectionElement;
extern SField const sfXChainCreateAccountAttestationCollectionElement;
// array of objects (common)
// ARRAY/1 is reserved for end of array
// extern SField const sfSigningAccounts; // Never been used.
extern SField const sfSigners;
extern SField const sfSignerEntries;
extern SField const sfTemplate;
extern SField const sfNecessary;
extern SField const sfSufficient;
extern SField const sfAffectedNodes;
extern SField const sfMemos;
extern SField const sfNFTokens;
extern SField const sfHooks;
extern SField const sfGenesisMint;
extern SField const sfVoteSlots;
extern SField const sfAuthAccounts;
extern SField const sfPriceDataSeries;
// array of objects (uncommon)
extern SField const sfMajorities;
extern SField const sfDisabledValidators;
extern SField const sfHookExecutions;
extern SField const sfHookExecution;
extern SField const sfHookParameters;
extern SField const sfHooks;
extern SField const sfHookGrants;
extern SField const sfGenesisMints;
extern SField const sfActiveValidators;
extern SField const sfImportVLKeys;
extern SField const sfHookEmissions;
extern SField const sfAmounts;
extern SField const sfRemarks;
extern SField const sfXChainClaimAttestations;
extern SField const sfXChainCreateAccountAttestations;
//------------------------------------------------------------------------------
} // namespace ripple
#endif

View File

@@ -0,0 +1,150 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SOTEMPLATE_H_INCLUDED
#define RIPPLE_PROTOCOL_SOTEMPLATE_H_INCLUDED
#include <ripple/basics/contract.h>
#include <ripple/protocol/SField.h>
#include <functional>
#include <initializer_list>
#include <memory>
#include <stdexcept>
namespace ripple {
/** Kind of element in each entry of an SOTemplate. */
enum SOEStyle {
soeINVALID = -1,
soeREQUIRED = 0, // required
soeOPTIONAL = 1, // optional, may be present with default value
soeDEFAULT = 2, // optional, if present, must not have default value
// inner object with the default fields has to be
// constructed with STObject::makeInnerObject()
};
//------------------------------------------------------------------------------
/** An element in a SOTemplate. */
class SOElement
{
// Use std::reference_wrapper so SOElement can be stored in a std::vector.
std::reference_wrapper<SField const> sField_;
SOEStyle style_;
public:
SOElement(SField const& fieldName, SOEStyle style)
: sField_(fieldName), style_(style)
{
if (!sField_.get().isUseful())
{
auto nm = std::to_string(fieldName.getCode());
if (fieldName.hasName())
nm += ": '" + fieldName.getName() + "'";
Throw<std::runtime_error>(
"SField (" + nm + ") in SOElement must be useful.");
}
}
SField const&
sField() const
{
return sField_.get();
}
SOEStyle
style() const
{
return style_;
}
};
//------------------------------------------------------------------------------
/** Defines the fields and their attributes within a STObject.
Each subclass of SerializedObject will provide its own template
describing the available fields and their metadata attributes.
*/
class SOTemplate
{
public:
// Copying vectors is expensive. Make this a move-only type until
// there is motivation to change that.
SOTemplate(SOTemplate&& other) = default;
SOTemplate&
operator=(SOTemplate&& other) = default;
/** Create a template populated with all fields.
After creating the template fields cannot be
added, modified, or removed.
*/
SOTemplate(
std::initializer_list<SOElement> uniqueFields,
std::initializer_list<SOElement> commonFields = {});
/* Provide for the enumeration of fields */
std::vector<SOElement>::const_iterator
begin() const
{
return elements_.cbegin();
}
std::vector<SOElement>::const_iterator
cbegin() const
{
return begin();
}
std::vector<SOElement>::const_iterator
end() const
{
return elements_.cend();
}
std::vector<SOElement>::const_iterator
cend() const
{
return end();
}
/** The number of entries in this template */
std::size_t
size() const
{
return elements_.size();
}
/** Retrieve the position of a named field. */
int
getIndex(SField const&) const;
SOEStyle
style(SField const& sf) const
{
return elements_[indices_[sf.getNum()]].style();
}
private:
std::vector<SOElement> elements_;
std::vector<int> indices_; // field num -> index
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STACCOUNT_H_INCLUDED
#define RIPPLE_PROTOCOL_STACCOUNT_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/AccountID.h>
#include <ripple/protocol/STBase.h>
#include <string>
namespace ripple {
class STAccount final : public STBase, public CountedObject<STAccount>
{
private:
// The original implementation of STAccount kept the value in an STBlob.
// But an STAccount is always 160 bits, so we can store it with less
// overhead in a ripple::uint160. However, so the serialized format of the
// STAccount stays unchanged, we serialize and deserialize like an STBlob.
AccountID value_;
bool default_;
public:
using value_type = AccountID;
STAccount();
STAccount(SField const& n);
STAccount(SField const& n, Buffer&& v);
STAccount(SerialIter& sit, SField const& name);
STAccount(SField const& n, AccountID const& v);
SerializedTypeID
getSType() const override;
std::string
getText() const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
STAccount&
operator=(AccountID const& value);
AccountID const&
value() const noexcept;
void
setValue(AccountID const& v);
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
inline STAccount&
STAccount::operator=(AccountID const& value)
{
setValue(value);
return *this;
}
inline AccountID const&
STAccount::value() const noexcept
{
return value_;
}
inline void
STAccount::setValue(AccountID const& v)
{
value_ = v;
default_ = false;
}
inline bool
operator==(STAccount const& lhs, STAccount const& rhs)
{
return lhs.value() == rhs.value();
}
inline auto
operator<(STAccount const& lhs, STAccount const& rhs)
{
return lhs.value() < rhs.value();
}
inline bool
operator==(STAccount const& lhs, AccountID const& rhs)
{
return lhs.value() == rhs;
}
inline auto
operator<(STAccount const& lhs, AccountID const& rhs)
{
return lhs.value() < rhs;
}
inline auto
operator<(AccountID const& lhs, STAccount const& rhs)
{
return lhs < rhs.value();
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,653 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STAMOUNT_H_INCLUDED
#define RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/IOUAmount.h>
#include <ripple/basics/LocalValue.h>
#include <ripple/basics/Number.h>
#include <ripple/basics/XRPAmount.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/json_get_or_throw.h>
namespace ripple {
// Internal form:
// 1: If amount is zero, then value is zero and offset is -100
// 2: Otherwise:
// legal offset range is -96 to +80 inclusive
// value range is 10^15 to (10^16 - 1) inclusive
// amount = value * [10 ^ offset]
// Wire form:
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
class STAmount final : public STBase, public CountedObject<STAmount>
{
public:
using mantissa_type = std::uint64_t;
using exponent_type = int;
using rep = std::pair<mantissa_type, exponent_type>;
private:
Issue mIssue;
mantissa_type mValue;
exponent_type mOffset;
bool mIsNative; // A shorthand for isXRP(mIssue).
bool mIsNegative;
public:
using value_type = STAmount;
static const int cMinOffset = -96;
static const int cMaxOffset = 80;
// Maximum native value supported by the code
static const std::uint64_t cMinValue = 1000000000000000ull;
static const std::uint64_t cMaxValue = 9999999999999999ull;
static const std::uint64_t cMaxNative = 9000000000000000000ull;
// Max native value on network.
static const std::uint64_t cMaxNativeN = 100000000000000000ull;
static const std::uint64_t cNotNative = 0x8000000000000000ull;
static const std::uint64_t cPosNative = 0x4000000000000000ull;
static std::uint64_t const uRateOne;
//--------------------------------------------------------------------------
STAmount(SerialIter& sit, SField const& name);
struct unchecked
{
explicit unchecked() = default;
};
// Do not call canonicalize
STAmount(
SField const& name,
Issue const& issue,
mantissa_type mantissa,
exponent_type exponent,
bool native,
bool negative,
unchecked);
STAmount(
Issue const& issue,
mantissa_type mantissa,
exponent_type exponent,
bool native,
bool negative,
unchecked);
// Call canonicalize
STAmount(
SField const& name,
Issue const& issue,
mantissa_type mantissa,
exponent_type exponent,
bool native,
bool negative);
STAmount(SField const& name, std::int64_t mantissa);
STAmount(
SField const& name,
std::uint64_t mantissa = 0,
bool negative = false);
STAmount(
SField const& name,
Issue const& issue,
std::uint64_t mantissa = 0,
int exponent = 0,
bool negative = false);
explicit STAmount(std::uint64_t mantissa = 0, bool negative = false);
explicit STAmount(SField const& name, STAmount const& amt);
STAmount(
Issue const& issue,
std::uint64_t mantissa = 0,
int exponent = 0,
bool negative = false);
// VFALCO Is this needed when we have the previous signature?
STAmount(
Issue const& issue,
std::uint32_t mantissa,
int exponent = 0,
bool negative = false);
STAmount(Issue const& issue, std::int64_t mantissa, int exponent = 0);
STAmount(Issue const& issue, int mantissa, int exponent = 0);
// Legacy support for new-style amounts
STAmount(IOUAmount const& amount, Issue const& issue);
STAmount(XRPAmount const& amount);
operator Number() const;
//--------------------------------------------------------------------------
//
// Observers
//
//--------------------------------------------------------------------------
int
exponent() const noexcept;
bool
native() const noexcept;
bool
negative() const noexcept;
std::uint64_t
mantissa() const noexcept;
Issue const&
issue() const;
// These three are deprecated
Currency const&
getCurrency() const;
AccountID const&
getIssuer() const;
int
signum() const noexcept;
/** Returns a zero value with the same issuer and currency. */
STAmount
zeroed() const;
void
setJson(Json::Value&) const;
STAmount const&
value() const noexcept;
//--------------------------------------------------------------------------
//
// Operators
//
//--------------------------------------------------------------------------
explicit operator bool() const noexcept;
STAmount&
operator+=(STAmount const&);
STAmount&
operator-=(STAmount const&);
STAmount& operator=(beast::Zero);
STAmount&
operator=(XRPAmount const& amount);
//--------------------------------------------------------------------------
//
// Modification
//
//--------------------------------------------------------------------------
void
negate();
void
clear();
// Zero while copying currency and issuer.
void
clear(STAmount const& saTmpl);
void
clear(Issue const& issue);
void
setIssuer(AccountID const& uIssuer);
/** Set the Issue for this amount and update mIsNative. */
void
setIssue(Issue const& issue);
//--------------------------------------------------------------------------
//
// STBase
//
//--------------------------------------------------------------------------
SerializedTypeID
getSType() const override;
std::string
getFullText() const override;
std::string
getText() const override;
Json::Value getJson(JsonOptions) const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
XRPAmount
xrp() const;
IOUAmount
iou() const;
private:
static std::unique_ptr<STAmount>
construct(SerialIter&, SField const& name);
void
set(std::int64_t v);
void
canonicalize();
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
STAmount&
operator=(IOUAmount const& iou);
friend class detail::STVar;
friend STAmount
operator+(STAmount const& v1, STAmount const& v2);
};
//------------------------------------------------------------------------------
//
// Creation
//
//------------------------------------------------------------------------------
// VFALCO TODO The parameter type should be Quality not uint64_t
STAmount
amountFromQuality(std::uint64_t rate);
STAmount
amountFromString(Issue const& issue, std::string const& amount);
STAmount
amountFromJson(SField const& name, Json::Value const& v);
bool
amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource);
// IOUAmount and XRPAmount define toSTAmount, defining this
// trivial conversion here makes writing generic code easier
inline STAmount const&
toSTAmount(STAmount const& a)
{
return a;
}
//------------------------------------------------------------------------------
//
// Observers
//
//------------------------------------------------------------------------------
inline int
STAmount::exponent() const noexcept
{
return mOffset;
}
inline bool
STAmount::native() const noexcept
{
return mIsNative;
}
inline bool
STAmount::negative() const noexcept
{
return mIsNegative;
}
inline std::uint64_t
STAmount::mantissa() const noexcept
{
return mValue;
}
inline Issue const&
STAmount::issue() const
{
return mIssue;
}
inline Currency const&
STAmount::getCurrency() const
{
return mIssue.currency;
}
inline AccountID const&
STAmount::getIssuer() const
{
return mIssue.account;
}
inline int
STAmount::signum() const noexcept
{
return mValue ? (mIsNegative ? -1 : 1) : 0;
}
inline STAmount
STAmount::zeroed() const
{
return STAmount(mIssue);
}
inline STAmount::operator bool() const noexcept
{
return *this != beast::zero;
}
inline STAmount::operator Number() const
{
if (mIsNative)
return xrp();
return iou();
}
inline STAmount& STAmount::operator=(beast::Zero)
{
clear();
return *this;
}
inline STAmount&
STAmount::operator=(XRPAmount const& amount)
{
*this = STAmount(amount);
return *this;
}
inline void
STAmount::negate()
{
if (*this != beast::zero)
mIsNegative = !mIsNegative;
}
inline void
STAmount::clear()
{
// The -100 is used to allow 0 to sort less than a small positive values
// which have a negative exponent.
mOffset = mIsNative ? 0 : -100;
mValue = 0;
mIsNegative = false;
}
// Zero while copying currency and issuer.
inline void
STAmount::clear(STAmount const& saTmpl)
{
clear(saTmpl.mIssue);
}
inline void
STAmount::clear(Issue const& issue)
{
setIssue(issue);
clear();
}
inline void
STAmount::setIssuer(AccountID const& uIssuer)
{
mIssue.account = uIssuer;
setIssue(mIssue);
}
inline STAmount const&
STAmount::value() const noexcept
{
return *this;
}
inline bool
isLegalNet(STAmount const& value)
{
return !value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
}
//------------------------------------------------------------------------------
//
// Operators
//
//------------------------------------------------------------------------------
bool
operator==(STAmount const& lhs, STAmount const& rhs);
bool
operator<(STAmount const& lhs, STAmount const& rhs);
inline bool
operator!=(STAmount const& lhs, STAmount const& rhs)
{
return !(lhs == rhs);
}
inline bool
operator>(STAmount const& lhs, STAmount const& rhs)
{
return rhs < lhs;
}
inline bool
operator<=(STAmount const& lhs, STAmount const& rhs)
{
return !(rhs < lhs);
}
inline bool
operator>=(STAmount const& lhs, STAmount const& rhs)
{
return !(lhs < rhs);
}
STAmount
operator-(STAmount const& value);
//------------------------------------------------------------------------------
//
// Arithmetic
//
//------------------------------------------------------------------------------
STAmount
operator+(STAmount const& v1, STAmount const& v2);
STAmount
operator-(STAmount const& v1, STAmount const& v2);
STAmount
divide(STAmount const& v1, STAmount const& v2, Issue const& issue);
STAmount
multiply(STAmount const& v1, STAmount const& v2, Issue const& issue);
// multiply rounding result in specified direction
STAmount
mulRound(
STAmount const& v1,
STAmount const& v2,
Issue const& issue,
bool roundUp);
// multiply following the rounding directions more precisely.
STAmount
mulRoundStrict(
STAmount const& v1,
STAmount const& v2,
Issue const& issue,
bool roundUp);
// divide rounding result in specified direction
STAmount
divRound(
STAmount const& v1,
STAmount const& v2,
Issue const& issue,
bool roundUp);
// divide following the rounding directions more precisely.
STAmount
divRoundStrict(
STAmount const& v1,
STAmount const& v2,
Issue const& issue,
bool roundUp);
// Someone is offering X for Y, what is the rate?
// Rate: smaller is better, the taker wants the most out: in/out
// VFALCO TODO Return a Quality object
std::uint64_t
getRate(STAmount const& offerOut, STAmount const& offerIn);
//------------------------------------------------------------------------------
inline bool
isXRP(STAmount const& amount)
{
return isXRP(amount.issue().currency);
}
inline bool
isBadCurrency(STAmount const& amount)
{
if (amount.native())
return false;
return isBadCurrency(amount.issue().currency);
}
/** returns true iff adding or subtracting results in less than or equal to
* 0.01% precision loss **/
inline bool
isAddable(STAmount const& amt1, STAmount const& amt2)
{
// special case: adding anything to zero is always fine
if (amt1 == beast::zero || amt2 == beast::zero)
return true;
// special case: adding two xrp amounts together.
// this is just an overflow check
if (isXRP(amt1) && isXRP(amt2))
{
XRPAmount A = (amt1.signum() == -1 ? -(amt1.xrp()) : amt1.xrp());
XRPAmount B = (amt2.signum() == -1 ? -(amt2.xrp()) : amt2.xrp());
XRPAmount finalAmt = A + B;
return (finalAmt >= A && finalAmt >= B);
}
static const STAmount one{IOUAmount{1, 0}, noIssue()};
static const STAmount maxLoss{IOUAmount{1, -4}, noIssue()};
STAmount A = amt1;
STAmount B = amt2;
if (isXRP(A))
A = STAmount{IOUAmount{A.xrp().drops(), -6}, noIssue()};
if (isXRP(B))
B = STAmount{IOUAmount{B.xrp().drops(), -6}, noIssue()};
A.setIssue(noIssue());
B.setIssue(noIssue());
STAmount lhs = divide((A - B) + B, A, noIssue()) - one;
STAmount rhs = divide((B - A) + A, B, noIssue()) - one;
return ((rhs.negative() ? -rhs : rhs) + (lhs.negative() ? -lhs : lhs)) <=
maxLoss;
}
// Since `canonicalize` does not have access to a ledger, this is needed to put
// the low-level routine stAmountCanonicalize on an amendment switch. Only
// transactions need to use this switchover. Outside of a transaction it's safe
// to unconditionally use the new behavior.
bool
getSTAmountCanonicalizeSwitchover();
void
setSTAmountCanonicalizeSwitchover(bool v);
/** RAII class to set and restore the STAmount canonicalize switchover.
*/
class STAmountSO
{
public:
explicit STAmountSO(bool v) : saved_(getSTAmountCanonicalizeSwitchover())
{
setSTAmountCanonicalizeSwitchover(v);
}
~STAmountSO()
{
setSTAmountCanonicalizeSwitchover(saved_);
}
private:
bool saved_;
};
} // namespace ripple
//------------------------------------------------------------------------------
namespace Json {
template <>
inline ripple::STAmount
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
Json::StaticString const& key = field.getJsonName();
if (!v.isMember(key))
Throw<JsonMissingKeyError>(key);
Json::Value const& inner = v[key];
return amountFromJson(field, inner);
}
} // namespace Json
#endif

View File

@@ -0,0 +1,318 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STARRAY_H_INCLUDED
#define RIPPLE_PROTOCOL_STARRAY_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STObject.h>
namespace ripple {
class STArray final : public STBase, public CountedObject<STArray>
{
private:
using list_type = std::vector<STObject>;
list_type v_;
public:
using value_type = STObject;
using size_type = list_type::size_type;
using iterator = list_type::iterator;
using const_iterator = list_type::const_iterator;
// RH NOTE: please don't delete this constructor
STArray(std::vector<STObject> const& v, SField const& f);
STArray() = default;
STArray(STArray const&) = default;
template <
class Iter,
class = std::enable_if_t<std::is_convertible_v<
typename std::iterator_traits<Iter>::reference,
STObject>>>
explicit STArray(Iter first, Iter last);
template <
class Iter,
class = std::enable_if_t<std::is_convertible_v<
typename std::iterator_traits<Iter>::reference,
STObject>>>
STArray(SField const& f, Iter first, Iter last);
STArray&
operator=(STArray const&) = default;
STArray(STArray&&);
STArray&
operator=(STArray&&);
STArray(SField const& f, std::size_t n);
STArray(SerialIter& sit, SField const& f, int depth = 0);
explicit STArray(int n);
explicit STArray(SField const& f);
STObject&
operator[](std::size_t j);
STObject const&
operator[](std::size_t j) const;
STObject&
back();
STObject const&
back() const;
template <class... Args>
void
emplace_back(Args&&... args);
void
push_back(STObject const& object);
void
push_back(STObject&& object);
iterator
begin();
iterator
end();
const_iterator
begin() const;
const_iterator
end() const;
size_type
size() const;
bool
empty() const;
void
clear();
void
reserve(std::size_t n);
void
swap(STArray& a) noexcept;
std::string
getFullText() const override;
std::string
getText() const override;
Json::Value
getJson(JsonOptions index) const override;
void
add(Serializer& s) const override;
void
sort(bool (*compare)(const STObject& o1, const STObject& o2));
bool
operator==(const STArray& s) const;
bool
operator!=(const STArray& s) const;
iterator
erase(iterator pos);
iterator
erase(const_iterator pos);
iterator
erase(iterator first, iterator last);
iterator
erase(const_iterator first, const_iterator last);
SerializedTypeID
getSType() const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
template <class Iter, class>
STArray::STArray(Iter first, Iter last) : v_(first, last)
{
}
template <class Iter, class>
STArray::STArray(SField const& f, Iter first, Iter last)
: STBase(f), v_(first, last)
{
}
inline STObject&
STArray::operator[](std::size_t j)
{
return v_[j];
}
inline STObject const&
STArray::operator[](std::size_t j) const
{
return v_[j];
}
inline STObject&
STArray::back()
{
return v_.back();
}
inline STObject const&
STArray::back() const
{
return v_.back();
}
template <class... Args>
inline void
STArray::emplace_back(Args&&... args)
{
v_.emplace_back(std::forward<Args>(args)...);
}
inline void
STArray::push_back(STObject const& object)
{
v_.push_back(object);
}
inline void
STArray::push_back(STObject&& object)
{
v_.push_back(std::move(object));
}
inline STArray::iterator
STArray::begin()
{
return v_.begin();
}
inline STArray::iterator
STArray::end()
{
return v_.end();
}
inline STArray::const_iterator
STArray::begin() const
{
return v_.begin();
}
inline STArray::const_iterator
STArray::end() const
{
return v_.end();
}
inline STArray::size_type
STArray::size() const
{
return v_.size();
}
inline bool
STArray::empty() const
{
return v_.empty();
}
inline void
STArray::clear()
{
v_.clear();
}
inline void
STArray::reserve(std::size_t n)
{
v_.reserve(n);
}
inline void
STArray::swap(STArray& a) noexcept
{
v_.swap(a.v_);
}
inline bool
STArray::operator==(const STArray& s) const
{
return v_ == s.v_;
}
inline bool
STArray::operator!=(const STArray& s) const
{
return v_ != s.v_;
}
inline STArray::iterator
STArray::erase(iterator pos)
{
return v_.erase(pos);
}
inline STArray::iterator
STArray::erase(const_iterator pos)
{
return v_.erase(pos);
}
inline STArray::iterator
STArray::erase(iterator first, iterator last)
{
return v_.erase(first, last);
}
inline STArray::iterator
STArray::erase(const_iterator first, const_iterator last)
{
return v_.erase(first, last);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,230 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STBASE_H_INCLUDED
#define RIPPLE_PROTOCOL_STBASE_H_INCLUDED
#include <ripple/basics/contract.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/Serializer.h>
#include <memory>
#include <ostream>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
namespace ripple {
/// Note, should be treated as flags that can be | and &
struct JsonOptions
{
using underlying_t = unsigned int;
underlying_t value;
enum values : underlying_t {
// clang-format off
none = 0b0000'0000,
include_date = 0b0000'0001,
disable_API_prior_V2 = 0b0000'0010,
// IMPORTANT `_all` must be union of all of the above; see also operator~
_all = 0b0000'0011
// clang-format on
};
constexpr JsonOptions(underlying_t v) noexcept : value(v)
{
}
[[nodiscard]] constexpr explicit operator underlying_t() const noexcept
{
return value;
}
[[nodiscard]] constexpr explicit operator bool() const noexcept
{
return value != 0u;
}
[[nodiscard]] constexpr auto friend
operator==(JsonOptions lh, JsonOptions rh) noexcept -> bool = default;
[[nodiscard]] constexpr auto friend
operator!=(JsonOptions lh, JsonOptions rh) noexcept -> bool = default;
/// Returns JsonOptions union of lh and rh
[[nodiscard]] constexpr JsonOptions friend
operator|(JsonOptions lh, JsonOptions rh) noexcept
{
return {lh.value | rh.value};
}
/// Returns JsonOptions intersection of lh and rh
[[nodiscard]] constexpr JsonOptions friend
operator&(JsonOptions lh, JsonOptions rh) noexcept
{
return {lh.value & rh.value};
}
/// Returns JsonOptions binary negation, can be used with & (above) for set
/// difference e.g. `(options & ~JsonOptions::include_date)`
[[nodiscard]] constexpr JsonOptions friend
operator~(JsonOptions v) noexcept
{
return {~v.value & static_cast<underlying_t>(_all)};
}
};
namespace detail {
class STVar;
}
// VFALCO TODO fix this restriction on copy assignment.
//
// CAUTION: Do not create a vector (or similar container) of any object derived
// from STBase. Use Boost ptr_* containers. The copy assignment operator
// of STBase has semantics that will cause contained types to change
// their names when an object is deleted because copy assignment is used to
// "slide down" the remaining types and this will not copy the field
// name. Changing the copy assignment operator to copy the field name breaks the
// use of copy assignment just to copy values, which is used in the transaction
// engine code.
//------------------------------------------------------------------------------
/** A type which can be exported to a well known binary format.
A STBase:
- Always a field
- Can always go inside an eligible enclosing STBase
(such as STArray)
- Has a field name
Like JSON, a SerializedObject is a basket which has rules
on what it can hold.
@note "ST" stands for "Serialized Type."
*/
class STBase
{
SField const* fName;
public:
virtual ~STBase() = default;
STBase();
STBase(const STBase&) = default;
STBase&
operator=(const STBase& t);
explicit STBase(SField const& n);
bool
operator==(const STBase& t) const;
bool
operator!=(const STBase& t) const;
template <class D>
D&
downcast();
template <class D>
D const&
downcast() const;
virtual SerializedTypeID
getSType() const;
virtual std::string
getFullText() const;
virtual std::string
getText() const;
virtual Json::Value getJson(JsonOptions /*options*/) const;
virtual void
add(Serializer& s) const;
virtual bool
isEquivalent(STBase const& t) const;
virtual bool
isDefault() const;
/** A STBase is a field.
This sets the name.
*/
void
setFName(SField const& n);
SField const&
getFName() const;
void
addFieldID(Serializer& s) const;
protected:
template <class T>
static STBase*
emplace(std::size_t n, void* buf, T&& val);
private:
virtual STBase*
copy(std::size_t n, void* buf) const;
virtual STBase*
move(std::size_t n, void* buf);
friend class detail::STVar;
};
//------------------------------------------------------------------------------
std::ostream&
operator<<(std::ostream& out, const STBase& t);
template <class D>
D&
STBase::downcast()
{
D* ptr = dynamic_cast<D*>(this);
if (ptr == nullptr)
Throw<std::bad_cast>();
return *ptr;
}
template <class D>
D const&
STBase::downcast() const
{
D const* ptr = dynamic_cast<D const*>(this);
if (ptr == nullptr)
Throw<std::bad_cast>();
return *ptr;
}
template <class T>
STBase*
STBase::emplace(std::size_t n, void* buf, T&& val)
{
using U = std::decay_t<T>;
if (sizeof(U) > n)
return new U(std::forward<T>(val));
return new (buf) U(std::forward<T>(val));
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,200 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STBITSTRING_H_INCLUDED
#define RIPPLE_PROTOCOL_STBITSTRING_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/beast/utility/Zero.h>
#include <ripple/protocol/STBase.h>
namespace ripple {
// The template parameter could be an unsigned type, however there's a bug in
// gdb (last checked in gdb 12.1) that prevents gdb from finding the RTTI
// information of a template parameterized by an unsigned type. This RTTI
// information is needed to write gdb pretty printers.
template <int Bits>
class STBitString final : public STBase, public CountedObject<STBitString<Bits>>
{
static_assert(Bits > 0, "Number of bits must be positive");
public:
using value_type = base_uint<Bits>;
private:
value_type value_;
public:
STBitString() = default;
STBitString(SField const& n);
STBitString(const value_type& v);
STBitString(SField const& n, const value_type& v);
STBitString(SerialIter& sit, SField const& name);
SerializedTypeID
getSType() const override;
std::string
getText() const override;
bool
isEquivalent(const STBase& t) const override;
void
add(Serializer& s) const override;
bool
isDefault() const override;
template <typename Tag>
void
setValue(base_uint<Bits, Tag> const& v);
value_type const&
value() const;
operator value_type() const;
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
using STUInt128 = STBitString<128>;
using STUInt160 = STBitString<160>;
using STUInt256 = STBitString<256>;
template <int Bits>
inline STBitString<Bits>::STBitString(SField const& n) : STBase(n)
{
}
template <int Bits>
inline STBitString<Bits>::STBitString(const value_type& v) : value_(v)
{
}
template <int Bits>
inline STBitString<Bits>::STBitString(SField const& n, const value_type& v)
: STBase(n), value_(v)
{
}
template <int Bits>
inline STBitString<Bits>::STBitString(SerialIter& sit, SField const& name)
: STBitString(name, sit.getBitString<Bits>())
{
}
template <int Bits>
STBase*
STBitString<Bits>::copy(std::size_t n, void* buf) const
{
return emplace(n, buf, *this);
}
template <int Bits>
STBase*
STBitString<Bits>::move(std::size_t n, void* buf)
{
return emplace(n, buf, std::move(*this));
}
template <>
inline SerializedTypeID
STUInt128::getSType() const
{
return STI_UINT128;
}
template <>
inline SerializedTypeID
STUInt160::getSType() const
{
return STI_UINT160;
}
template <>
inline SerializedTypeID
STUInt256::getSType() const
{
return STI_UINT256;
}
template <int Bits>
std::string
STBitString<Bits>::getText() const
{
return to_string(value_);
}
template <int Bits>
bool
STBitString<Bits>::isEquivalent(const STBase& t) const
{
const STBitString* v = dynamic_cast<const STBitString*>(&t);
return v && (value_ == v->value_);
}
template <int Bits>
void
STBitString<Bits>::add(Serializer& s) const
{
assert(getFName().isBinary());
assert(getFName().fieldType == getSType());
s.addBitString<Bits>(value_);
}
template <int Bits>
template <typename Tag>
void
STBitString<Bits>::setValue(base_uint<Bits, Tag> const& v)
{
value_ = v;
}
template <int Bits>
typename STBitString<Bits>::value_type const&
STBitString<Bits>::value() const
{
return value_;
}
template <int Bits>
STBitString<Bits>::operator value_type() const
{
return value_;
}
template <int Bits>
bool
STBitString<Bits>::isDefault() const
{
return value_ == beast::zero;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,151 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STBLOB_H_INCLUDED
#define RIPPLE_PROTOCOL_STBLOB_H_INCLUDED
#include <ripple/basics/Buffer.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/Slice.h>
#include <ripple/protocol/STBase.h>
#include <cassert>
#include <cstring>
#include <memory>
namespace ripple {
// variable length byte string
class STBlob : public STBase, public CountedObject<STBlob>
{
Buffer value_;
public:
using value_type = Slice;
STBlob() = default;
STBlob(STBlob const& rhs);
STBlob(SField const& f, void const* data, std::size_t size);
STBlob(SField const& f, Buffer&& b);
STBlob(SField const& n);
STBlob(SerialIter&, SField const& name = sfGeneric);
std::size_t
size() const;
std::uint8_t const*
data() const;
SerializedTypeID
getSType() const override;
std::string
getText() const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
STBlob&
operator=(Slice const& slice);
value_type
value() const noexcept;
STBlob&
operator=(Buffer&& buffer);
void
setValue(Buffer&& b);
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
inline STBlob::STBlob(STBlob const& rhs)
: STBase(rhs), CountedObject<STBlob>(rhs), value_(rhs.data(), rhs.size())
{
}
inline STBlob::STBlob(SField const& f, void const* data, std::size_t size)
: STBase(f), value_(data, size)
{
}
inline STBlob::STBlob(SField const& f, Buffer&& b)
: STBase(f), value_(std::move(b))
{
}
inline STBlob::STBlob(SField const& n) : STBase(n)
{
}
inline std::size_t
STBlob::size() const
{
return value_.size();
}
inline std::uint8_t const*
STBlob::data() const
{
return reinterpret_cast<std::uint8_t const*>(value_.data());
}
inline STBlob&
STBlob::operator=(Slice const& slice)
{
value_ = Buffer(slice.data(), slice.size());
return *this;
}
inline STBlob::value_type
STBlob::value() const noexcept
{
return value_;
}
inline STBlob&
STBlob::operator=(Buffer&& buffer)
{
value_ = std::move(buffer);
return *this;
}
inline void
STBlob::setValue(Buffer&& b)
{
value_ = std::move(b);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,138 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_STCURRENCY_H_INCLUDED
#define RIPPLE_PROTOCOL_STCURRENCY_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/UintTypes.h>
namespace ripple {
class STCurrency final : public STBase
{
private:
Currency currency_{};
public:
using value_type = Currency;
STCurrency() = default;
explicit STCurrency(SerialIter& sit, SField const& name);
explicit STCurrency(SField const& name, Currency const& currency);
explicit STCurrency(SField const& name);
Currency const&
currency() const;
Currency const&
value() const noexcept;
void
setCurrency(Currency const& currency);
SerializedTypeID
getSType() const override;
std::string
getText() const override;
Json::Value getJson(JsonOptions) const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
private:
static std::unique_ptr<STCurrency>
construct(SerialIter&, SField const& name);
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
STCurrency
currencyFromJson(SField const& name, Json::Value const& v);
inline Currency const&
STCurrency::currency() const
{
return currency_;
}
inline Currency const&
STCurrency::value() const noexcept
{
return currency_;
}
inline void
STCurrency::setCurrency(Currency const& currency)
{
currency_ = currency;
}
inline bool
operator==(STCurrency const& lhs, STCurrency const& rhs)
{
return lhs.currency() == rhs.currency();
}
inline bool
operator!=(STCurrency const& lhs, STCurrency const& rhs)
{
return !operator==(lhs, rhs);
}
inline bool
operator<(STCurrency const& lhs, STCurrency const& rhs)
{
return lhs.currency() < rhs.currency();
}
inline bool
operator==(STCurrency const& lhs, Currency const& rhs)
{
return lhs.currency() == rhs;
}
inline bool
operator<(STCurrency const& lhs, Currency const& rhs)
{
return lhs.currency() < rhs;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,178 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STEXCHANGE_H_INCLUDED
#define RIPPLE_PROTOCOL_STEXCHANGE_H_INCLUDED
#include <ripple/basics/Blob.h>
#include <ripple/basics/Buffer.h>
#include <ripple/basics/Slice.h>
#include <ripple/basics/contract.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBlob.h>
#include <ripple/protocol/STInteger.h>
#include <ripple/protocol/STObject.h>
#include <memory>
#include <optional>
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace ripple {
/** Convert between serialized type U and C++ type T. */
template <class U, class T>
struct STExchange;
template <class U, class T>
struct STExchange<STInteger<U>, T>
{
explicit STExchange() = default;
using value_type = U;
static void
get(std::optional<T>& t, STInteger<U> const& u)
{
t = u.value();
}
static std::unique_ptr<STInteger<U>>
set(SField const& f, T const& t)
{
return std::make_unique<STInteger<U>>(f, t);
}
};
template <>
struct STExchange<STBlob, Slice>
{
explicit STExchange() = default;
using value_type = Slice;
static void
get(std::optional<value_type>& t, STBlob const& u)
{
t.emplace(u.data(), u.size());
}
static std::unique_ptr<STBlob>
set(TypedField<STBlob> const& f, Slice const& t)
{
return std::make_unique<STBlob>(f, t.data(), t.size());
}
};
template <>
struct STExchange<STBlob, Buffer>
{
explicit STExchange() = default;
using value_type = Buffer;
static void
get(std::optional<Buffer>& t, STBlob const& u)
{
t.emplace(u.data(), u.size());
}
static std::unique_ptr<STBlob>
set(TypedField<STBlob> const& f, Buffer const& t)
{
return std::make_unique<STBlob>(f, t.data(), t.size());
}
static std::unique_ptr<STBlob>
set(TypedField<STBlob> const& f, Buffer&& t)
{
return std::make_unique<STBlob>(f, std::move(t));
}
};
//------------------------------------------------------------------------------
/** Return the value of a field in an STObject as a given type. */
/** @{ */
template <class T, class U>
std::optional<T>
get(STObject const& st, TypedField<U> const& f)
{
std::optional<T> t;
STBase const* const b = st.peekAtPField(f);
if (!b)
return t;
auto const id = b->getSType();
if (id == STI_NOTPRESENT)
return t;
auto const u = dynamic_cast<U const*>(b);
// This should never happen
if (!u)
Throw<std::runtime_error>("Wrong field type");
STExchange<U, T>::get(t, *u);
return t;
}
template <class U>
std::optional<typename STExchange<U, typename U::value_type>::value_type>
get(STObject const& st, TypedField<U> const& f)
{
return get<typename U::value_type>(st, f);
}
/** @} */
/** Set a field value in an STObject. */
template <class U, class T>
void
set(STObject& st, TypedField<U> const& f, T&& t)
{
st.set(STExchange<U, typename std::decay<T>::type>::set(
f, std::forward<T>(t)));
}
/** Set a blob field using an init function. */
template <class Init>
void
set(STObject& st, TypedField<STBlob> const& f, std::size_t size, Init&& init)
{
st.set(std::make_unique<STBlob>(f, size, init));
}
/** Set a blob field from data. */
template <class = void>
void
set(STObject& st,
TypedField<STBlob> const& f,
void const* data,
std::size_t size)
{
st.set(std::make_unique<STBlob>(f, data, size));
}
/** Remove a field in an STObject. */
template <class U>
void
erase(STObject& st, TypedField<U> const& f)
{
st.makeFieldAbsent(f);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,163 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STINTEGER_H_INCLUDED
#define RIPPLE_PROTOCOL_STINTEGER_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STBase.h>
namespace ripple {
template <typename Integer>
class STInteger : public STBase, public CountedObject<STInteger<Integer>>
{
public:
using value_type = Integer;
private:
Integer value_;
public:
explicit STInteger(Integer v);
STInteger(SField const& n, Integer v = 0);
STInteger(SerialIter& sit, SField const& name);
SerializedTypeID
getSType() const override;
Json::Value getJson(JsonOptions) const override;
std::string
getText() const override;
void
add(Serializer& s) const override;
bool
isDefault() const override;
bool
isEquivalent(const STBase& t) const override;
STInteger&
operator=(value_type const& v);
value_type
value() const noexcept;
void
setValue(Integer v);
operator Integer() const;
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class ripple::detail::STVar;
};
using STUInt8 = STInteger<unsigned char>;
using STUInt16 = STInteger<std::uint16_t>;
using STUInt32 = STInteger<std::uint32_t>;
using STUInt64 = STInteger<std::uint64_t>;
template <typename Integer>
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
{
}
template <typename Integer>
inline STInteger<Integer>::STInteger(SField const& n, Integer v)
: STBase(n), value_(v)
{
}
template <typename Integer>
inline STBase*
STInteger<Integer>::copy(std::size_t n, void* buf) const
{
return emplace(n, buf, *this);
}
template <typename Integer>
inline STBase*
STInteger<Integer>::move(std::size_t n, void* buf)
{
return emplace(n, buf, std::move(*this));
}
template <typename Integer>
inline void
STInteger<Integer>::add(Serializer& s) const
{
assert(getFName().isBinary());
assert(getFName().fieldType == getSType());
s.addInteger(value_);
}
template <typename Integer>
inline bool
STInteger<Integer>::isDefault() const
{
return value_ == 0;
}
template <typename Integer>
inline bool
STInteger<Integer>::isEquivalent(const STBase& t) const
{
const STInteger* v = dynamic_cast<const STInteger*>(&t);
return v && (value_ == v->value_);
}
template <typename Integer>
inline STInteger<Integer>&
STInteger<Integer>::operator=(value_type const& v)
{
value_ = v;
return *this;
}
template <typename Integer>
inline typename STInteger<Integer>::value_type
STInteger<Integer>::value() const noexcept
{
return value_;
}
template <typename Integer>
inline void
STInteger<Integer>::setValue(Integer v)
{
value_ = v;
}
template <typename Integer>
inline STInteger<Integer>::operator Integer() const
{
return value_;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_STISSUE_H_INCLUDED
#define RIPPLE_PROTOCOL_STISSUE_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/Serializer.h>
namespace ripple {
class STIssue final : public STBase, CountedObject<STIssue>
{
private:
Issue issue_{xrpIssue()};
public:
using value_type = Issue;
STIssue() = default;
explicit STIssue(SerialIter& sit, SField const& name);
explicit STIssue(SField const& name, Issue const& issue);
explicit STIssue(SField const& name);
Issue const&
issue() const;
Issue const&
value() const noexcept;
void
setIssue(Issue const& issue);
SerializedTypeID
getSType() const override;
Json::Value getJson(JsonOptions) const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
STIssue
issueFromJson(SField const& name, Json::Value const& v);
inline Issue const&
STIssue::issue() const
{
return issue_;
}
inline Issue const&
STIssue::value() const noexcept
{
return issue_;
}
inline void
STIssue::setIssue(Issue const& issue)
{
if (isXRP(issue_.currency) != isXRP(issue_.account))
Throw<std::runtime_error>(
"invalid issue: currency and account native mismatch");
issue_ = issue;
}
inline bool
operator==(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() == rhs.issue();
}
inline bool
operator!=(STIssue const& lhs, STIssue const& rhs)
{
return !operator==(lhs, rhs);
}
inline bool
operator<(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() < rhs.issue();
}
inline bool
operator==(STIssue const& lhs, Issue const& rhs)
{
return lhs.issue() == rhs;
}
inline bool
operator<(STIssue const& lhs, Issue const& rhs)
{
return lhs.issue() < rhs;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,127 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STLEDGERENTRY_H_INCLUDED
#define RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/STObject.h>
namespace ripple {
class Rules;
class Invariants_test;
class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
{
uint256 key_;
LedgerEntryType type_;
public:
using pointer = std::shared_ptr<STLedgerEntry>;
using ref = const std::shared_ptr<STLedgerEntry>&;
/** Create an empty object with the given key and type. */
explicit STLedgerEntry(Keylet const& k);
STLedgerEntry(LedgerEntryType type, uint256 const& key);
STLedgerEntry(SerialIter& sit, uint256 const& index);
STLedgerEntry(SerialIter&& sit, uint256 const& index);
STLedgerEntry(STObject const& object, uint256 const& index);
SerializedTypeID
getSType() const override;
std::string
getFullText() const override;
std::string
getText() const override;
Json::Value
getJson(JsonOptions options) const override;
/** Returns the 'key' (or 'index') of this item.
The key identifies this entry's position in
the SHAMap associative container.
*/
uint256 const&
key() const;
LedgerEntryType
getType() const;
// is this a ledger entry that can be threaded
bool
isThreadedType(Rules const& rules) const;
bool
thread(
uint256 const& txID,
std::uint32_t ledgerSeq,
uint256& prevTxID,
std::uint32_t& prevLedgerID);
private:
/* Make STObject comply with the template for this SLE type
Can throw
*/
void
setSLEType();
friend Invariants_test; // this test wants access to the private type_
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
using SLE = STLedgerEntry;
inline STLedgerEntry::STLedgerEntry(LedgerEntryType type, uint256 const& key)
: STLedgerEntry(Keylet(type, key))
{
}
inline STLedgerEntry::STLedgerEntry(SerialIter&& sit, uint256 const& index)
: STLedgerEntry(sit, index)
{
}
/** Returns the 'key' (or 'index') of this item.
The key identifies this entry's position in
the SHAMap associative container.
*/
inline uint256 const&
STLedgerEntry::key() const
{
return key_;
}
inline LedgerEntryType
STLedgerEntry::getType() const
{
return type_;
}
} // namespace ripple
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_PROTOCOL_STPARSEDJSON_H_INCLUDED
#define RIPPLE_PROTOCOL_STPARSEDJSON_H_INCLUDED
#include <ripple/protocol/STArray.h>
#include <optional>
namespace ripple {
/** Holds the serialized result of parsing an input JSON object.
This does validation and checking on the provided JSON.
*/
class STParsedJSONObject
{
public:
/** Parses and creates an STParsedJSON object.
The result of the parsing is stored in object and error.
Exceptions:
Does not throw.
@param name The name of the JSON field, used in diagnostics.
@param json The JSON-RPC to parse.
*/
STParsedJSONObject(std::string const& name, Json::Value const& json);
STParsedJSONObject() = delete;
STParsedJSONObject(STParsedJSONObject const&) = delete;
STParsedJSONObject&
operator=(STParsedJSONObject const&) = delete;
~STParsedJSONObject() = default;
/** The STObject if the parse was successful. */
std::optional<STObject> object;
/** On failure, an appropriate set of error values. */
Json::Value error;
};
/** Holds the serialized result of parsing an input JSON array.
This does validation and checking on the provided JSON.
*/
class STParsedJSONArray
{
public:
/** Parses and creates an STParsedJSON array.
The result of the parsing is stored in array and error.
Exceptions:
Does not throw.
@param name The name of the JSON field, used in diagnostics.
@param json The JSON-RPC to parse.
*/
STParsedJSONArray(std::string const& name, Json::Value const& json);
STParsedJSONArray() = delete;
STParsedJSONArray(STParsedJSONArray const&) = delete;
STParsedJSONArray&
operator=(STParsedJSONArray const&) = delete;
~STParsedJSONArray() = default;
/** The STArray if the parse was successful. */
std::optional<STArray> array;
/** On failure, an appropriate set of error values. */
Json::Value error;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,523 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STPATHSET_H_INCLUDED
#define RIPPLE_PROTOCOL_STPATHSET_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/UintTypes.h>
#include <cassert>
#include <cstddef>
#include <optional>
namespace ripple {
class STPathElement final : public CountedObject<STPathElement>
{
unsigned int mType;
AccountID mAccountID;
Currency mCurrencyID;
AccountID mIssuerID;
bool is_offer_;
std::size_t hash_value_;
public:
enum Type {
typeNone = 0x00,
typeAccount =
0x01, // Rippling through an account (vs taking an offer).
typeCurrency = 0x10, // Currency follows.
typeIssuer = 0x20, // Issuer follows.
typeBoundary = 0xFF, // Boundary between alternate paths.
typeAll = typeAccount | typeCurrency | typeIssuer,
// Combination of all types.
};
STPathElement();
STPathElement(STPathElement const&) = default;
STPathElement&
operator=(STPathElement const&) = default;
STPathElement(
std::optional<AccountID> const& account,
std::optional<Currency> const& currency,
std::optional<AccountID> const& issuer);
STPathElement(
AccountID const& account,
Currency const& currency,
AccountID const& issuer,
bool forceCurrency = false);
STPathElement(
unsigned int uType,
AccountID const& account,
Currency const& currency,
AccountID const& issuer);
auto
getNodeType() const;
bool
isOffer() const;
bool
isAccount() const;
bool
hasIssuer() const;
bool
hasCurrency() const;
bool
isNone() const;
// Nodes are either an account ID or a offer prefix. Offer prefixs denote a
// class of offers.
AccountID const&
getAccountID() const;
Currency const&
getCurrency() const;
AccountID const&
getIssuerID() const;
bool
operator==(const STPathElement& t) const;
bool
operator!=(const STPathElement& t) const;
private:
static std::size_t
get_hash(STPathElement const& element);
};
class STPath final : public CountedObject<STPath>
{
std::vector<STPathElement> mPath;
public:
STPath() = default;
STPath(std::vector<STPathElement> p);
std::vector<STPathElement>::size_type
size() const;
bool
empty() const;
void
push_back(STPathElement const& e);
template <typename... Args>
void
emplace_back(Args&&... args);
bool
hasSeen(
AccountID const& account,
Currency const& currency,
AccountID const& issuer) const;
Json::Value getJson(JsonOptions) const;
std::vector<STPathElement>::const_iterator
begin() const;
std::vector<STPathElement>::const_iterator
end() const;
bool
operator==(STPath const& t) const;
std::vector<STPathElement>::const_reference
back() const;
std::vector<STPathElement>::const_reference
front() const;
STPathElement&
operator[](int i);
const STPathElement&
operator[](int i) const;
void
reserve(size_t s);
};
//------------------------------------------------------------------------------
// A set of zero or more payment paths
class STPathSet final : public STBase, public CountedObject<STPathSet>
{
std::vector<STPath> value;
public:
STPathSet() = default;
STPathSet(SField const& n);
STPathSet(SerialIter& sit, SField const& name);
void
add(Serializer& s) const override;
Json::Value getJson(JsonOptions) const override;
SerializedTypeID
getSType() const override;
bool
assembleAdd(STPath const& base, STPathElement const& tail);
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
// std::vector like interface:
std::vector<STPath>::const_reference
operator[](std::vector<STPath>::size_type n) const;
std::vector<STPath>::reference
operator[](std::vector<STPath>::size_type n);
std::vector<STPath>::const_iterator
begin() const;
std::vector<STPath>::const_iterator
end() const;
std::vector<STPath>::size_type
size() const;
bool
empty() const;
void
push_back(STPath const& e);
template <typename... Args>
void
emplace_back(Args&&... args);
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
// ------------ STPathElement ------------
inline STPathElement::STPathElement() : mType(typeNone), is_offer_(true)
{
hash_value_ = get_hash(*this);
}
inline STPathElement::STPathElement(
std::optional<AccountID> const& account,
std::optional<Currency> const& currency,
std::optional<AccountID> const& issuer)
: mType(typeNone)
{
if (!account)
{
is_offer_ = true;
}
else
{
is_offer_ = false;
mAccountID = *account;
mType |= typeAccount;
assert(mAccountID != noAccount());
}
if (currency)
{
mCurrencyID = *currency;
mType |= typeCurrency;
}
if (issuer)
{
mIssuerID = *issuer;
mType |= typeIssuer;
assert(mIssuerID != noAccount());
}
hash_value_ = get_hash(*this);
}
inline STPathElement::STPathElement(
AccountID const& account,
Currency const& currency,
AccountID const& issuer,
bool forceCurrency)
: mType(typeNone)
, mAccountID(account)
, mCurrencyID(currency)
, mIssuerID(issuer)
, is_offer_(isXRP(mAccountID))
{
if (!is_offer_)
mType |= typeAccount;
if (forceCurrency || !isXRP(currency))
mType |= typeCurrency;
if (!isXRP(issuer))
mType |= typeIssuer;
hash_value_ = get_hash(*this);
}
inline STPathElement::STPathElement(
unsigned int uType,
AccountID const& account,
Currency const& currency,
AccountID const& issuer)
: mType(uType)
, mAccountID(account)
, mCurrencyID(currency)
, mIssuerID(issuer)
, is_offer_(isXRP(mAccountID))
{
hash_value_ = get_hash(*this);
}
inline auto
STPathElement::getNodeType() const
{
return mType;
}
inline bool
STPathElement::isOffer() const
{
return is_offer_;
}
inline bool
STPathElement::isAccount() const
{
return !isOffer();
}
inline bool
STPathElement::hasIssuer() const
{
return getNodeType() & STPathElement::typeIssuer;
}
inline bool
STPathElement::hasCurrency() const
{
return getNodeType() & STPathElement::typeCurrency;
}
inline bool
STPathElement::isNone() const
{
return getNodeType() == STPathElement::typeNone;
}
// Nodes are either an account ID or a offer prefix. Offer prefixs denote a
// class of offers.
inline AccountID const&
STPathElement::getAccountID() const
{
return mAccountID;
}
inline Currency const&
STPathElement::getCurrency() const
{
return mCurrencyID;
}
inline AccountID const&
STPathElement::getIssuerID() const
{
return mIssuerID;
}
inline bool
STPathElement::operator==(const STPathElement& t) const
{
return (mType & typeAccount) == (t.mType & typeAccount) &&
hash_value_ == t.hash_value_ && mAccountID == t.mAccountID &&
mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID;
}
inline bool
STPathElement::operator!=(const STPathElement& t) const
{
return !operator==(t);
}
// ------------ STPath ------------
inline STPath::STPath(std::vector<STPathElement> p) : mPath(std::move(p))
{
}
inline std::vector<STPathElement>::size_type
STPath::size() const
{
return mPath.size();
}
inline bool
STPath::empty() const
{
return mPath.empty();
}
inline void
STPath::push_back(STPathElement const& e)
{
mPath.push_back(e);
}
template <typename... Args>
inline void
STPath::emplace_back(Args&&... args)
{
mPath.emplace_back(std::forward<Args>(args)...);
}
inline std::vector<STPathElement>::const_iterator
STPath::begin() const
{
return mPath.begin();
}
inline std::vector<STPathElement>::const_iterator
STPath::end() const
{
return mPath.end();
}
inline bool
STPath::operator==(STPath const& t) const
{
return mPath == t.mPath;
}
inline std::vector<STPathElement>::const_reference
STPath::back() const
{
return mPath.back();
}
inline std::vector<STPathElement>::const_reference
STPath::front() const
{
return mPath.front();
}
inline STPathElement&
STPath::operator[](int i)
{
return mPath[i];
}
inline const STPathElement&
STPath::operator[](int i) const
{
return mPath[i];
}
inline void
STPath::reserve(size_t s)
{
mPath.reserve(s);
}
// ------------ STPathSet ------------
inline STPathSet::STPathSet(SField const& n) : STBase(n)
{
}
// std::vector like interface:
inline std::vector<STPath>::const_reference
STPathSet::operator[](std::vector<STPath>::size_type n) const
{
return value[n];
}
inline std::vector<STPath>::reference
STPathSet::operator[](std::vector<STPath>::size_type n)
{
return value[n];
}
inline std::vector<STPath>::const_iterator
STPathSet::begin() const
{
return value.begin();
}
inline std::vector<STPath>::const_iterator
STPathSet::end() const
{
return value.end();
}
inline std::vector<STPath>::size_type
STPathSet::size() const
{
return value.size();
}
inline bool
STPathSet::empty() const
{
return value.empty();
}
inline void
STPathSet::push_back(STPath const& e)
{
value.push_back(e);
}
template <typename... Args>
inline void
STPathSet::emplace_back(Args&&... args)
{
value.emplace_back(std::forward<Args>(args)...);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,200 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STTX_H_INCLUDED
#define RIPPLE_PROTOCOL_STTX_H_INCLUDED
#include <ripple/basics/Expected.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/Rules.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/SeqProxy.h>
#include <ripple/protocol/TxFormats.h>
#include <boost/container/flat_set.hpp>
#include <functional>
namespace ripple {
enum TxnSql : char {
txnSqlNew = 'N',
txnSqlConflict = 'C',
txnSqlHeld = 'H',
txnSqlValidated = 'V',
txnSqlIncluded = 'I',
txnSqlUnknown = 'U'
};
class STTx final : public STObject, public CountedObject<STTx>
{
uint256 tid_;
TxType tx_type_;
public:
static std::size_t const minMultiSigners = 1;
// if rules are not supplied then the largest possible value is returned
static std::size_t
maxMultiSigners(Rules const* rules = 0)
{
if (rules && !rules->enabled(featureExpandedSignerList))
return 8;
return 32;
}
STTx() = delete;
STTx(STTx const& other) = default;
STTx&
operator=(STTx const& other) = delete;
explicit STTx(SerialIter& sit);
explicit STTx(SerialIter&& sit);
explicit STTx(STObject&& object);
/** Constructs a transaction.
The returned transaction will have the specified type and
any fields that the callback function adds to the object
that's passed in.
*/
STTx(TxType type, std::function<void(STObject&)> assembler);
// STObject functions.
SerializedTypeID
getSType() const override;
std::string
getFullText() const override;
// Outer transaction functions / signature functions.
Blob
getSignature() const;
uint256
getSigningHash() const;
TxType
getTxnType() const;
Blob
getSigningPubKey() const;
SeqProxy
getSeqProxy() const;
boost::container::flat_set<AccountID>
getMentionedAccounts() const;
uint256
getTransactionID() const;
Json::Value
getJson(JsonOptions options) const override;
Json::Value
getJson(JsonOptions options, bool binary) const;
void
sign(PublicKey const& publicKey, SecretKey const& secretKey);
/** Check the signature.
@return `true` if valid signature. If invalid, the error message string.
*/
enum class RequireFullyCanonicalSig : bool { no, yes };
Expected<void, std::string>
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
const;
// SQL Functions with metadata.
static std::string const&
getMetaSQLInsertReplaceHeader();
std::string
getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData)
const;
std::string
getMetaSQL(
Serializer rawTxn,
std::uint32_t inLedger,
char status,
std::string const& escapedMetaData) const;
private:
Expected<void, std::string>
checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const;
Expected<void, std::string>
checkMultiSign(
RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules) const;
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
bool
passesLocalChecks(STObject const& st, std::string&);
/** Sterilize a transaction.
The transaction is serialized and then deserialized,
ensuring that all equivalent transactions are in canonical
form. This also ensures that program metadata such as
the transaction's digest, are all computed.
*/
std::shared_ptr<STTx const>
sterilize(STTx const& stx);
/** Check whether a transaction is a pseudo-transaction */
bool
isPseudoTx(STObject const& tx);
inline STTx::STTx(SerialIter&& sit) : STTx(sit)
{
}
inline TxType
STTx::getTxnType() const
{
return tx_type_;
}
inline Blob
STTx::getSigningPubKey() const
{
return getFieldVL(sfSigningPubKey);
}
inline uint256
STTx::getTransactionID() const
{
return tid_;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,270 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STVALIDATION_H_INCLUDED
#define RIPPLE_PROTOCOL_STVALIDATION_H_INCLUDED
#include <ripple/basics/FeeUnits.h>
#include <ripple/basics/Log.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/SecretKey.h>
#include <cassert>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
namespace ripple {
// Validation flags
// This is a full (as opposed to a partial) validation
constexpr std::uint32_t vfFullValidation = 0x00000001;
// The signature is fully canonical
constexpr std::uint32_t vfFullyCanonicalSig = 0x80000000;
class STValidation final : public STObject, public CountedObject<STValidation>
{
bool mTrusted = false;
// Determines the validity of the signature in this validation; unseated
// optional if we haven't yet checked it, a boolean otherwise.
mutable std::optional<bool> valid_;
// The public key associated with the key used to sign this validation
PublicKey const signingPubKey_;
// The ID of the validator that issued this validation. For validators
// that use manifests this will be derived from the master public key.
NodeID const nodeID_;
NetClock::time_point seenTime_ = {};
public:
/** Construct a STValidation from a peer from serialized data.
@param sit Iterator over serialized data
@param lookupNodeID Invocable with signature
NodeID(PublicKey const&)
used to find the Node ID based on the public key
that signed the validation. For manifest based
validators, this should be the NodeID of the master
public key.
@param checkSignature Whether to verify the data was signed properly
@note Throws if the object is not valid
*/
template <class LookupNodeID>
STValidation(
SerialIter& sit,
LookupNodeID&& lookupNodeID,
bool checkSignature);
/** Construct, sign and trust a new STValidation issued by this node.
@param signTime When the validation is signed
@param publicKey The current signing public key
@param secretKey The current signing secret key
@param nodeID ID corresponding to node's public master key
@param f callback function to "fill" the validation with necessary data
*/
template <typename F>
STValidation(
NetClock::time_point signTime,
PublicKey const& pk,
SecretKey const& sk,
NodeID const& nodeID,
F&& f);
// Hash of the validated ledger
uint256
getLedgerHash() const;
// Hash of consensus transaction set used to generate ledger
uint256
getConsensusHash() const;
NetClock::time_point
getSignTime() const;
NetClock::time_point
getSeenTime() const noexcept;
PublicKey const&
getSignerPublic() const noexcept;
NodeID const&
getNodeID() const noexcept;
bool
isValid() const noexcept;
bool
isFull() const noexcept;
bool
isTrusted() const noexcept;
uint256
getSigningHash() const;
void
setTrusted();
void
setUntrusted();
void
setSeen(NetClock::time_point s);
Blob
getSerialized() const;
Blob
getSignature() const;
private:
static SOTemplate const&
validationFormat();
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
template <class LookupNodeID>
STValidation::STValidation(
SerialIter& sit,
LookupNodeID&& lookupNodeID,
bool checkSignature)
: STObject(validationFormat(), sit, sfValidation)
, signingPubKey_([this]() {
auto const spk = getFieldVL(sfSigningPubKey);
if (publicKeyType(makeSlice(spk)) != KeyType::secp256k1)
Throw<std::runtime_error>("Invalid public key in validation");
return PublicKey{makeSlice(spk)};
}())
, nodeID_(lookupNodeID(signingPubKey_))
{
if (checkSignature && !isValid())
{
JLOG(debugLog().error()) << "Invalid signature in validation: "
<< getJson(JsonOptions::none);
Throw<std::runtime_error>("Invalid signature in validation");
}
assert(nodeID_.isNonZero());
}
/** Construct, sign and trust a new STValidation issued by this node.
@param signTime When the validation is signed
@param publicKey The current signing public key
@param secretKey The current signing secret key
@param nodeID ID corresponding to node's public master key
@param f callback function to "fill" the validation with necessary data
*/
template <typename F>
STValidation::STValidation(
NetClock::time_point signTime,
PublicKey const& pk,
SecretKey const& sk,
NodeID const& nodeID,
F&& f)
: STObject(validationFormat(), sfValidation)
, signingPubKey_(pk)
, nodeID_(nodeID)
, seenTime_(signTime)
{
assert(nodeID_.isNonZero());
// First, set our own public key:
if (publicKeyType(pk) != KeyType::secp256k1)
LogicError("We can only use secp256k1 keys for signing validations");
setFieldVL(sfSigningPubKey, pk.slice());
setFieldU32(sfSigningTime, signTime.time_since_epoch().count());
// Perform additional initialization
f(*this);
// Finally, sign the validation and mark it as trusted:
setFlag(vfFullyCanonicalSig);
setFieldVL(sfSignature, signDigest(pk, sk, getSigningHash()));
setTrusted();
// Check to ensure that all required fields are present.
for (auto const& e : validationFormat())
{
if (e.style() == soeREQUIRED && !isFieldPresent(e.sField()))
LogicError(
"Required field '" + e.sField().getName() +
"' missing from validation.");
}
// We just signed this, so it should be valid.
valid_ = true;
}
inline PublicKey const&
STValidation::getSignerPublic() const noexcept
{
return signingPubKey_;
}
inline NodeID const&
STValidation::getNodeID() const noexcept
{
return nodeID_;
}
inline bool
STValidation::isTrusted() const noexcept
{
return mTrusted;
}
inline void
STValidation::setTrusted()
{
mTrusted = true;
}
inline void
STValidation::setUntrusted()
{
mTrusted = false;
}
inline void
STValidation::setSeen(NetClock::time_point s)
{
seenTime_ = s;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,260 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STVECTOR256_H_INCLUDED
#define RIPPLE_PROTOCOL_STVECTOR256_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STBitString.h>
#include <ripple/protocol/STInteger.h>
namespace ripple {
class STVector256 : public STBase, public CountedObject<STVector256>
{
std::vector<uint256> mValue;
public:
using value_type = std::vector<uint256> const&;
STVector256() = default;
explicit STVector256(SField const& n);
explicit STVector256(std::vector<uint256> const& vector);
STVector256(SField const& n, std::vector<uint256> const& vector);
STVector256(SerialIter& sit, SField const& name);
SerializedTypeID
getSType() const override;
void
add(Serializer& s) const override;
Json::Value getJson(JsonOptions) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
STVector256&
operator=(std::vector<uint256> const& v);
STVector256&
operator=(std::vector<uint256>&& v);
void
setValue(const STVector256& v);
/** Retrieve a copy of the vector we contain */
explicit operator std::vector<uint256>() const;
std::size_t
size() const;
void
resize(std::size_t n);
bool
empty() const;
std::vector<uint256>::reference
operator[](std::vector<uint256>::size_type n);
std::vector<uint256>::const_reference
operator[](std::vector<uint256>::size_type n) const;
std::vector<uint256> const&
value() const;
std::vector<uint256>::iterator
insert(std::vector<uint256>::const_iterator pos, uint256 const& value);
std::vector<uint256>::iterator
insert(std::vector<uint256>::const_iterator pos, uint256&& value);
void
push_back(uint256 const& v);
std::vector<uint256>::iterator
begin();
std::vector<uint256>::const_iterator
begin() const;
std::vector<uint256>::iterator
end();
std::vector<uint256>::const_iterator
end() const;
std::vector<uint256>::iterator
erase(std::vector<uint256>::iterator position);
void
clear() noexcept;
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
};
inline STVector256::STVector256(SField const& n) : STBase(n)
{
}
inline STVector256::STVector256(std::vector<uint256> const& vector)
: mValue(vector)
{
}
inline STVector256::STVector256(
SField const& n,
std::vector<uint256> const& vector)
: STBase(n), mValue(vector)
{
}
inline STVector256&
STVector256::operator=(std::vector<uint256> const& v)
{
mValue = v;
return *this;
}
inline STVector256&
STVector256::operator=(std::vector<uint256>&& v)
{
mValue = std::move(v);
return *this;
}
inline void
STVector256::setValue(const STVector256& v)
{
mValue = v.mValue;
}
/** Retrieve a copy of the vector we contain */
inline STVector256::operator std::vector<uint256>() const
{
return mValue;
}
inline std::size_t
STVector256::size() const
{
return mValue.size();
}
inline void
STVector256::resize(std::size_t n)
{
return mValue.resize(n);
}
inline bool
STVector256::empty() const
{
return mValue.empty();
}
inline std::vector<uint256>::reference
STVector256::operator[](std::vector<uint256>::size_type n)
{
return mValue[n];
}
inline std::vector<uint256>::const_reference
STVector256::operator[](std::vector<uint256>::size_type n) const
{
return mValue[n];
}
inline std::vector<uint256> const&
STVector256::value() const
{
return mValue;
}
inline std::vector<uint256>::iterator
STVector256::insert(
std::vector<uint256>::const_iterator pos,
uint256 const& value)
{
return mValue.insert(pos, value);
}
inline std::vector<uint256>::iterator
STVector256::insert(std::vector<uint256>::const_iterator pos, uint256&& value)
{
return mValue.insert(pos, std::move(value));
}
inline void
STVector256::push_back(uint256 const& v)
{
mValue.push_back(v);
}
inline std::vector<uint256>::iterator
STVector256::begin()
{
return mValue.begin();
}
inline std::vector<uint256>::const_iterator
STVector256::begin() const
{
return mValue.begin();
}
inline std::vector<uint256>::iterator
STVector256::end()
{
return mValue.end();
}
inline std::vector<uint256>::const_iterator
STVector256::end() const
{
return mValue.end();
}
inline std::vector<uint256>::iterator
STVector256::erase(std::vector<uint256>::iterator position)
{
return mValue.erase(position);
}
inline void
STVector256::clear() noexcept
{
return mValue.clear();
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,236 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2022 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_PROTOCOL_STXCHAINBRIDGE_H_INCLUDED
#define RIPPLE_PROTOCOL_STXCHAINBRIDGE_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STAccount.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STIssue.h>
namespace ripple {
class Serializer;
class STObject;
class STXChainBridge final : public STBase, public CountedObject<STXChainBridge>
{
STAccount lockingChainDoor_{sfLockingChainDoor};
STIssue lockingChainIssue_{sfLockingChainIssue};
STAccount issuingChainDoor_{sfIssuingChainDoor};
STIssue issuingChainIssue_{sfIssuingChainIssue};
public:
using value_type = STXChainBridge;
enum class ChainType { locking, issuing };
static ChainType
otherChain(ChainType ct);
static ChainType
srcChain(bool wasLockingChainSend);
static ChainType
dstChain(bool wasLockingChainSend);
STXChainBridge();
explicit STXChainBridge(SField const& name);
STXChainBridge(STXChainBridge const& rhs) = default;
STXChainBridge(STObject const& o);
STXChainBridge(
AccountID const& srcChainDoor,
Issue const& srcChainIssue,
AccountID const& dstChainDoor,
Issue const& dstChainIssue);
explicit STXChainBridge(Json::Value const& v);
explicit STXChainBridge(SField const& name, Json::Value const& v);
explicit STXChainBridge(SerialIter& sit, SField const& name);
STXChainBridge&
operator=(STXChainBridge const& rhs) = default;
std::string
getText() const override;
STObject
toSTObject() const;
AccountID const&
lockingChainDoor() const;
Issue const&
lockingChainIssue() const;
AccountID const&
issuingChainDoor() const;
Issue const&
issuingChainIssue() const;
AccountID const&
door(ChainType ct) const;
Issue const&
issue(ChainType ct) const;
SerializedTypeID
getSType() const override;
Json::Value getJson(JsonOptions) const override;
void
add(Serializer& s) const override;
bool
isEquivalent(const STBase& t) const override;
bool
isDefault() const override;
value_type const&
value() const noexcept;
private:
static std::unique_ptr<STXChainBridge>
construct(SerialIter&, SField const& name);
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend bool
operator==(STXChainBridge const& lhs, STXChainBridge const& rhs);
friend bool
operator<(STXChainBridge const& lhs, STXChainBridge const& rhs);
};
inline bool
operator==(STXChainBridge const& lhs, STXChainBridge const& rhs)
{
return std::tie(
lhs.lockingChainDoor_,
lhs.lockingChainIssue_,
lhs.issuingChainDoor_,
lhs.issuingChainIssue_) ==
std::tie(
rhs.lockingChainDoor_,
rhs.lockingChainIssue_,
rhs.issuingChainDoor_,
rhs.issuingChainIssue_);
}
inline bool
operator<(STXChainBridge const& lhs, STXChainBridge const& rhs)
{
return std::tie(
lhs.lockingChainDoor_,
lhs.lockingChainIssue_,
lhs.issuingChainDoor_,
lhs.issuingChainIssue_) <
std::tie(
rhs.lockingChainDoor_,
rhs.lockingChainIssue_,
rhs.issuingChainDoor_,
rhs.issuingChainIssue_);
}
inline AccountID const&
STXChainBridge::lockingChainDoor() const
{
return lockingChainDoor_.value();
};
inline Issue const&
STXChainBridge::lockingChainIssue() const
{
return lockingChainIssue_.value();
};
inline AccountID const&
STXChainBridge::issuingChainDoor() const
{
return issuingChainDoor_.value();
};
inline Issue const&
STXChainBridge::issuingChainIssue() const
{
return issuingChainIssue_.value();
};
inline STXChainBridge::value_type const&
STXChainBridge::value() const noexcept
{
return *this;
}
inline AccountID const&
STXChainBridge::door(ChainType ct) const
{
if (ct == ChainType::locking)
return lockingChainDoor();
return issuingChainDoor();
}
inline Issue const&
STXChainBridge::issue(ChainType ct) const
{
if (ct == ChainType::locking)
return lockingChainIssue();
return issuingChainIssue();
}
inline STXChainBridge::ChainType
STXChainBridge::otherChain(ChainType ct)
{
if (ct == ChainType::locking)
return ChainType::issuing;
return ChainType::locking;
}
inline STXChainBridge::ChainType
STXChainBridge::srcChain(bool wasLockingChainSend)
{
if (wasLockingChainSend)
return ChainType::locking;
return ChainType::issuing;
}
inline STXChainBridge::ChainType
STXChainBridge::dstChain(bool wasLockingChainSend)
{
if (wasLockingChainSend)
return ChainType::issuing;
return ChainType::locking;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,185 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SECRETKEY_H_INCLUDED
#define RIPPLE_PROTOCOL_SECRETKEY_H_INCLUDED
#include <ripple/basics/Buffer.h>
#include <ripple/basics/Slice.h>
#include <ripple/protocol/KeyType.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/Seed.h>
#include <ripple/protocol/tokens.h>
#include <array>
#include <cstring>
#include <string>
namespace ripple {
/** A secret key. */
class SecretKey
{
private:
std::uint8_t buf_[32];
public:
using const_iterator = std::uint8_t const*;
SecretKey() = delete;
SecretKey(SecretKey const&) = default;
SecretKey&
operator=(SecretKey const&) = default;
~SecretKey();
SecretKey(std::array<std::uint8_t, 32> const& data);
SecretKey(Slice const& slice);
std::uint8_t const*
data() const
{
return buf_;
}
std::size_t
size() const
{
return sizeof(buf_);
}
/** Convert the secret key to a hexadecimal string.
@note The operator<< function is deliberately omitted
to avoid accidental exposure of secret key material.
*/
std::string
to_string() const;
const_iterator
begin() const noexcept
{
return buf_;
}
const_iterator
cbegin() const noexcept
{
return buf_;
}
const_iterator
end() const noexcept
{
return buf_ + sizeof(buf_);
}
const_iterator
cend() const noexcept
{
return buf_ + sizeof(buf_);
}
};
inline bool
operator==(SecretKey const& lhs, SecretKey const& rhs)
{
return lhs.size() == rhs.size() &&
std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
}
inline bool
operator!=(SecretKey const& lhs, SecretKey const& rhs)
{
return !(lhs == rhs);
}
//------------------------------------------------------------------------------
/** Parse a secret key */
template <>
std::optional<SecretKey>
parseBase58(TokenType type, std::string const& s);
inline std::string
toBase58(TokenType type, SecretKey const& sk)
{
return encodeBase58Token(type, sk.data(), sk.size());
}
/** Create a secret key using secure random numbers. */
SecretKey
randomSecretKey();
/** Generate a new secret key deterministically. */
SecretKey
generateSecretKey(KeyType type, Seed const& seed);
/** Derive the public key from a secret key. */
PublicKey
derivePublicKey(KeyType type, SecretKey const& sk);
/** Generate a key pair deterministically.
This algorithm is specific to Ripple:
For secp256k1 key pairs, the seed is converted
to a Generator and used to compute the key pair
corresponding to ordinal 0 for the generator.
*/
std::pair<PublicKey, SecretKey>
generateKeyPair(KeyType type, Seed const& seed);
/** Create a key pair using secure random numbers. */
std::pair<PublicKey, SecretKey>
randomKeyPair(KeyType type);
/** Generate a signature for a message digest.
This can only be used with secp256k1 since Ed25519's
security properties come, in part, from how the message
is hashed.
*/
/** @{ */
Buffer
signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest);
inline Buffer
signDigest(KeyType type, SecretKey const& sk, uint256 const& digest)
{
return signDigest(derivePublicKey(type, sk), sk, digest);
}
/** @} */
/** Generate a signature for a message.
With secp256k1 signatures, the data is first hashed with
SHA512-Half, and the resulting digest is signed.
*/
/** @{ */
Buffer
sign(PublicKey const& pk, SecretKey const& sk, Slice const& message);
inline Buffer
sign(KeyType type, SecretKey const& sk, Slice const& message)
{
return sign(derivePublicKey(type, sk), sk, message);
}
/** @} */
} // namespace ripple
#endif

View File

@@ -0,0 +1,140 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SEED_H_INCLUDED
#define RIPPLE_PROTOCOL_SEED_H_INCLUDED
#include <ripple/basics/Slice.h>
#include <ripple/basics/base_uint.h>
#include <ripple/protocol/tokens.h>
#include <array>
#include <optional>
namespace ripple {
/** Seeds are used to generate deterministic secret keys. */
class Seed
{
private:
std::array<uint8_t, 16> buf_;
public:
using const_iterator = std::array<uint8_t, 16>::const_iterator;
Seed() = delete;
Seed(Seed const&) = default;
Seed&
operator=(Seed const&) = default;
/** Destroy the seed.
The buffer will first be securely erased.
*/
~Seed();
/** Construct a seed */
/** @{ */
explicit Seed(Slice const& slice);
explicit Seed(uint128 const& seed);
/** @} */
std::uint8_t const*
data() const
{
return buf_.data();
}
std::size_t
size() const
{
return buf_.size();
}
const_iterator
begin() const noexcept
{
return buf_.begin();
}
const_iterator
cbegin() const noexcept
{
return buf_.cbegin();
}
const_iterator
end() const noexcept
{
return buf_.end();
}
const_iterator
cend() const noexcept
{
return buf_.cend();
}
};
//------------------------------------------------------------------------------
/** Create a seed using secure random numbers. */
Seed
randomSeed();
/** Generate a seed deterministically.
The algorithm is specific to Ripple:
The seed is calculated as the first 128 bits
of the SHA512-Half of the string text excluding
any terminating null.
@note This will not attempt to determine the format of
the string (e.g. hex or base58).
*/
Seed
generateSeed(std::string const& passPhrase);
/** Parse a Base58 encoded string into a seed */
template <>
std::optional<Seed>
parseBase58(std::string const& s);
/** Attempt to parse a string as a seed.
@param str the string to parse
@param rfc1751 true if we should attempt RFC1751 style parsing (deprecated)
* */
std::optional<Seed>
parseGenericSeed(std::string const& str, bool rfc1751 = true);
/** Encode a Seed in RFC1751 format */
std::string
seedAs1751(Seed const& seed);
/** Format a seed as a Base58 string */
inline std::string
toBase58(Seed const& seed)
{
return encodeBase58Token(TokenType::FamilySeed, seed.data(), seed.size());
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,170 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2018 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_PROTOCOL_SEQ_PROXY_H_INCLUDED
#define RIPPLE_PROTOCOL_SEQ_PROXY_H_INCLUDED
#include <cstdint>
#include <ostream>
namespace ripple {
/** A type that represents either a sequence value or a ticket value.
We use the value() of a SeqProxy in places where a sequence was used
before. An example of this is the sequence of an Offer stored in the
ledger. We do the same thing with the in-ledger identifier of a
Check, Payment Channel, and Escrow.
Why is this safe? If we use the SeqProxy::value(), how do we know that
each ledger entry will be unique?
There are two components that make this safe:
1. A "TicketCreate" transaction carefully avoids creating a ticket
that corresponds with an already used Sequence or Ticket value.
The transactor does this by referring to the account root's
sequence number. Creating the ticket advances the account root's
sequence number so the same ticket (or sequence) value cannot be
used again.
2. When a "TicketCreate" transaction creates a batch of tickets it advances
the account root sequence to one past the largest created ticket.
Therefore all tickets in a batch other than the first may never have
the same value as a sequence on that same account. And since a ticket
may only be used once there will never be any duplicates within this
account.
*/
class SeqProxy
{
public:
enum Type : std::uint8_t { seq = 0, ticket };
private:
std::uint32_t value_;
Type type_;
public:
constexpr explicit SeqProxy(Type t, std::uint32_t v) : value_{v}, type_{t}
{
}
SeqProxy(SeqProxy const& other) = default;
SeqProxy&
operator=(SeqProxy const& other) = default;
/** Factory function to return a sequence-based SeqProxy */
static constexpr SeqProxy
sequence(std::uint32_t v)
{
return SeqProxy{Type::seq, v};
}
constexpr std::uint32_t
value() const
{
return value_;
}
constexpr bool
isSeq() const
{
return type_ == seq;
}
constexpr bool
isTicket() const
{
return type_ == ticket;
}
// Occasionally it is convenient to be able to increase the value_
// of a SeqProxy. But it's unusual. So, rather than putting in an
// addition operator, you must invoke the method by name. That makes
// if more difficult to invoke accidentally.
SeqProxy&
advanceBy(std::uint32_t amount)
{
value_ += amount;
return *this;
}
// Comparison
//
// The comparison is designed specifically so _all_ Sequence
// representations sort in front of Ticket representations. This
// is true even if the Ticket value() is less that the Sequence
// value().
//
// This somewhat surprising sort order has benefits for transaction
// processing. It guarantees that transactions creating Tickets are
// sorted in from of transactions that consume Tickets.
friend constexpr bool
operator==(SeqProxy lhs, SeqProxy rhs)
{
if (lhs.type_ != rhs.type_)
return false;
return (lhs.value() == rhs.value());
}
friend constexpr bool
operator!=(SeqProxy lhs, SeqProxy rhs)
{
return !(lhs == rhs);
}
friend constexpr bool
operator<(SeqProxy lhs, SeqProxy rhs)
{
if (lhs.type_ != rhs.type_)
return lhs.type_ < rhs.type_;
return lhs.value() < rhs.value();
}
friend constexpr bool
operator>(SeqProxy lhs, SeqProxy rhs)
{
return rhs < lhs;
}
friend constexpr bool
operator>=(SeqProxy lhs, SeqProxy rhs)
{
return !(lhs < rhs);
}
friend constexpr bool
operator<=(SeqProxy lhs, SeqProxy rhs)
{
return !(lhs > rhs);
}
friend std::ostream&
operator<<(std::ostream& os, SeqProxy seqProx)
{
os << (seqProx.isSeq() ? "sequence " : "ticket ");
os << seqProx.value();
return os;
}
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,433 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SERIALIZER_H_INCLUDED
#define RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED
#include <ripple/basics/Blob.h>
#include <ripple/basics/Buffer.h>
#include <ripple/basics/Slice.h>
#include <ripple/basics/base_uint.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/safe_cast.h>
#include <ripple/basics/strHex.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/SField.h>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <type_traits>
namespace ripple {
class Serializer
{
private:
// DEPRECATED
Blob mData;
public:
explicit Serializer(int n = 256)
{
mData.reserve(n);
}
Serializer(void const* data, std::size_t size)
{
mData.resize(size);
if (size)
{
assert(data != nullptr);
std::memcpy(mData.data(), data, size);
}
}
Slice
slice() const noexcept
{
return Slice(mData.data(), mData.size());
}
std::size_t
size() const noexcept
{
return mData.size();
}
void const*
data() const noexcept
{
return mData.data();
}
// assemble functions
int
add8(unsigned char i);
int
add16(std::uint16_t i);
int
add32(std::uint32_t i); // ledger indexes, account sequence, timestamps
int
add32(HashPrefix p);
int
add64(std::uint64_t i); // native currency amounts
template <typename Integer>
int addInteger(Integer);
template <std::size_t Bits, class Tag>
int
addBitString(base_uint<Bits, Tag> const& v)
{
return addRaw(v.data(), v.size());
}
int
addRaw(Blob const& vector);
int
addRaw(Slice slice);
int
addRaw(const void* ptr, int len);
int
addRaw(const Serializer& s);
int
addVL(Blob const& vector);
int
addVL(Slice const& slice);
template <class Iter>
int
addVL(Iter begin, Iter end, int len);
int
addVL(const void* ptr, int len);
// disassemble functions
bool
get8(int&, int offset) const;
template <typename Integer>
bool
getInteger(Integer& number, int offset)
{
static const auto bytes = sizeof(Integer);
if ((offset + bytes) > mData.size())
return false;
number = 0;
auto ptr = &mData[offset];
for (auto i = 0; i < bytes; ++i)
{
if (i)
number <<= 8;
number |= *ptr++;
}
return true;
}
template <std::size_t Bits, typename Tag = void>
bool
getBitString(base_uint<Bits, Tag>& data, int offset) const
{
auto success = (offset + (Bits / 8)) <= mData.size();
if (success)
memcpy(data.begin(), &(mData.front()) + offset, (Bits / 8));
return success;
}
int
addFieldID(int type, int name);
int
addFieldID(SerializedTypeID type, int name)
{
return addFieldID(safe_cast<int>(type), name);
}
// DEPRECATED
uint256
getSHA512Half() const;
// totality functions
Blob const&
peekData() const
{
return mData;
}
Blob
getData() const
{
return mData;
}
Blob&
modData()
{
return mData;
}
int
getDataLength() const
{
return mData.size();
}
const void*
getDataPtr() const
{
return mData.data();
}
void*
getDataPtr()
{
return mData.data();
}
int
getLength() const
{
return mData.size();
}
std::string
getString() const
{
return std::string(static_cast<const char*>(getDataPtr()), size());
}
void
erase()
{
mData.clear();
}
bool
chop(int num);
// vector-like functions
Blob ::iterator
begin()
{
return mData.begin();
}
Blob ::iterator
end()
{
return mData.end();
}
Blob ::const_iterator
begin() const
{
return mData.begin();
}
Blob ::const_iterator
end() const
{
return mData.end();
}
void
reserve(size_t n)
{
mData.reserve(n);
}
void
resize(size_t n)
{
mData.resize(n);
}
size_t
capacity() const
{
return mData.capacity();
}
bool
operator==(Blob const& v) const
{
return v == mData;
}
bool
operator!=(Blob const& v) const
{
return v != mData;
}
bool
operator==(const Serializer& v) const
{
return v.mData == mData;
}
bool
operator!=(const Serializer& v) const
{
return v.mData != mData;
}
static int
decodeLengthLength(int b1);
static int
decodeVLLength(int b1);
static int
decodeVLLength(int b1, int b2);
static int
decodeVLLength(int b1, int b2, int b3);
private:
static int
encodeLengthLength(int length); // length to encode length
int
addEncoded(int length);
};
template <class Iter>
int
Serializer::addVL(Iter begin, Iter end, int len)
{
int ret = addEncoded(len);
for (; begin != end; ++begin)
{
addRaw(begin->data(), begin->size());
#ifndef NDEBUG
len -= begin->size();
#endif
}
assert(len == 0);
return ret;
}
//------------------------------------------------------------------------------
// DEPRECATED
// Transitional adapter to new serialization interfaces
class SerialIter
{
private:
std::uint8_t const* p_;
std::size_t remain_;
std::size_t used_ = 0;
public:
SerialIter(void const* data, std::size_t size) noexcept;
SerialIter(Slice const& slice) : SerialIter(slice.data(), slice.size())
{
}
// Infer the size of the data based on the size of the passed array.
template <int N>
explicit SerialIter(std::uint8_t const (&data)[N]) : SerialIter(&data[0], N)
{
static_assert(N > 0, "");
}
std::size_t
empty() const noexcept
{
return remain_ == 0;
}
void
reset() noexcept;
int
getBytesLeft() const noexcept
{
return static_cast<int>(remain_);
}
// get functions throw on error
unsigned char
get8();
std::uint16_t
get16();
std::uint32_t
get32();
std::uint64_t
get64();
template <std::size_t Bits, class Tag = void>
base_uint<Bits, Tag>
getBitString();
uint128
get128()
{
return getBitString<128>();
}
uint160
get160()
{
return getBitString<160>();
}
uint256
get256()
{
return getBitString<256>();
}
void
getFieldID(int& type, int& name);
// Returns the size of the VL if the
// next object is a VL. Advances the iterator
// to the beginning of the VL.
int
getVLDataLength();
Slice
getSlice(std::size_t bytes);
// VFALCO DEPRECATED Returns a copy
Blob
getRaw(int size);
// VFALCO DEPRECATED Returns a copy
Blob
getVL();
void
skip(int num);
Buffer
getVLBuffer();
template <class T>
T
getRawHelper(int size);
};
template <std::size_t Bits, class Tag>
base_uint<Bits, Tag>
SerialIter::getBitString()
{
auto const n = Bits / 8;
if (remain_ < n)
Throw<std::runtime_error>("invalid SerialIter getBitString");
auto const x = p_;
p_ += n;
used_ += n;
remain_ -= n;
return base_uint<Bits, Tag>::fromVoid(x);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SIGN_H_INCLUDED
#define RIPPLE_PROTOCOL_SIGN_H_INCLUDED
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/SecretKey.h>
#include <utility>
namespace ripple {
/** Sign an STObject
@param st Object to sign
@param prefix Prefix to insert before serialized object when hashing
@param type Signing key type used to derive public key
@param sk Signing secret key
@param sigField Field in which to store the signature on the object.
If not specified the value defaults to `sfSignature`.
@note If a signature already exists, it is overwritten.
*/
void
sign(
STObject& st,
HashPrefix const& prefix,
KeyType type,
SecretKey const& sk,
SF_VL const& sigField = sfSignature);
/** Returns `true` if STObject contains valid signature
@param st Signed object
@param prefix Prefix inserted before serialized object when hashing
@param pk Public key for verifying signature
@param sigField Object's field containing the signature.
If not specified the value defaults to `sfSignature`.
*/
bool
verify(
STObject const& st,
HashPrefix const& prefix,
PublicKey const& pk,
SF_VL const& sigField = sfSignature);
/** Return a Serializer suitable for computing a multisigning TxnSignature. */
Serializer
buildMultiSigningData(STObject const& obj, AccountID const& signingID);
/** Break the multi-signing hash computation into 2 parts for optimization.
We can optimize verifying multiple multisignatures by splitting the
data building into two parts;
o A large part that is shared by all of the computations.
o A small part that is unique to each signer in the multisignature.
The following methods support that optimization:
1. startMultiSigningData provides the large part which can be shared.
2. finishMuiltiSigningData caps the passed in serializer with each
signer's unique data.
*/
Serializer
startMultiSigningData(STObject const& obj);
inline void
finishMultiSigningData(AccountID const& signingID, Serializer& s)
{
s.addBitString(signingID);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SYSTEMPARAMETERS_H_INCLUDED
#define RIPPLE_PROTOCOL_SYSTEMPARAMETERS_H_INCLUDED
#include <ripple/basics/XRPAmount.h>
#include <ripple/basics/chrono.h>
#include <cstdint>
#include <string>
namespace ripple {
// Various protocol and system specific constant globals.
/* The name of the system. */
static inline std::string const&
systemName()
{
static std::string const name = "xahau";
return name;
}
/** Configure the native currency. */
/** Number of drops in the genesis account. */
constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP};
/** Returns true if the amount does not exceed the initial XRP in existence. */
inline bool
isLegalAmount(XRPAmount const& amount)
{
return amount <= INITIAL_XRP;
}
/** Returns true if the absolute value of the amount does not exceed the initial
* XRP in existence. */
inline bool
isLegalAmountSigned(XRPAmount const& amount)
{
return amount >= -INITIAL_XRP && amount <= INITIAL_XRP;
}
/* The currency code for the native currency. */
static inline std::string const&
systemCurrencyCode()
{
static std::string const code = "XAH";
return code;
}
/** The XRP ledger network's earliest allowed sequence */
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{1U};
/** The number of ledgers in a shard */
static constexpr std::uint32_t DEFAULT_LEDGERS_PER_SHARD{16384u};
/** The minimum amount of support an amendment should have.
@note This value is used by legacy code and will become obsolete
once the fixAmendmentMajorityCalc amendment activates.
*/
constexpr std::ratio<204, 256> preFixAmendmentMajorityCalcThreshold;
constexpr std::ratio<80, 100> postFixAmendmentMajorityCalcThreshold;
/** The minimum amount of time an amendment must hold a majority */
constexpr std::chrono::seconds const defaultAmendmentMajorityTime =
std::chrono::days{5};
} // namespace ripple
/** Default peer port (IANA registered) */
inline std::uint16_t constexpr DEFAULT_PEER_PORT{21337};
#endif

699
include/xrpl/protocol/TER.h Normal file
View File

@@ -0,0 +1,699 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012 - 2019 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_PROTOCOL_TER_H_INCLUDED
#define RIPPLE_PROTOCOL_TER_H_INCLUDED
#include <ripple/basics/safe_cast.h>
#include <ripple/json/json_value.h>
#include <optional>
#include <ostream>
#include <string>
#include <unordered_map>
namespace ripple {
// See https://xrpl.org/transaction-results.html
//
// "Transaction Engine Result"
// or Transaction ERror.
//
using TERUnderlyingType = int;
//------------------------------------------------------------------------------
enum TELcodes : TERUnderlyingType {
// Note: Range is stable.
// Exact numbers are used in ripple-binary-codec:
// https://github.com/ripple/ripple-binary-codec/blob/master/src/enums/definitions.json
// Use tokens.
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local
// limit) Only valid during non-consensus processing. Implications:
// - Not forwarded
// - No fee check
telLOCAL_ERROR = -399,
telBAD_DOMAIN,
telBAD_PATH_COUNT,
telBAD_PUBLIC_KEY,
telFAILED_PROCESSING,
telINSUF_FEE_P,
telNO_DST_PARTIAL,
telCAN_NOT_QUEUE,
telCAN_NOT_QUEUE_BALANCE,
telCAN_NOT_QUEUE_BLOCKS,
telCAN_NOT_QUEUE_BLOCKED,
telCAN_NOT_QUEUE_FEE,
telCAN_NOT_QUEUE_FULL,
telWRONG_NETWORK,
telREQUIRES_NETWORK_ID,
telNETWORK_ID_MAKES_TX_NON_CANONICAL,
telNON_LOCAL_EMITTED_TXN,
telIMPORT_VL_KEY_NOT_RECOGNISED,
telCAN_NOT_QUEUE_IMPORT,
telENV_RPC_FAILED,
};
//------------------------------------------------------------------------------
enum TEMcodes : TERUnderlyingType {
// Note: Range is stable.
// Exact numbers are used in ripple-binary-codec:
// https://github.com/ripple/ripple-binary-codec/blob/master/src/enums/definitions.json
// Use tokens.
// -299 .. -200: M Malformed (bad signature)
// Causes:
// - Transaction corrupt.
// Implications:
// - Not applied
// - Not forwarded
// - Reject
// - Cannot succeed in any imagined ledger.
temMALFORMED = -299,
temBAD_AMOUNT,
temBAD_CURRENCY,
temBAD_EXPIRATION,
temBAD_FEE,
temBAD_ISSUER,
temBAD_LIMIT,
temBAD_OFFER,
temBAD_PATH,
temBAD_PATH_LOOP,
temBAD_REGKEY,
temBAD_SEND_NATIVE_LIMIT,
temBAD_SEND_NATIVE_MAX,
temBAD_SEND_NATIVE_NO_DIRECT,
temBAD_SEND_NATIVE_PARTIAL,
temBAD_SEND_NATIVE_PATHS,
temBAD_SEQUENCE,
temBAD_SIGNATURE,
temBAD_SRC_ACCOUNT,
temBAD_TRANSFER_RATE,
temDST_IS_SRC,
temDST_NEEDED,
temINVALID,
temINVALID_FLAG,
temREDUNDANT,
temRIPPLE_EMPTY,
temDISABLED,
temBAD_SIGNER,
temBAD_QUORUM,
temBAD_WEIGHT,
temBAD_TICK_SIZE,
temINVALID_ACCOUNT_ID,
temCANNOT_PREAUTH_SELF,
temINVALID_COUNT,
temUNCERTAIN, // An internal intermediate result; should never be returned.
temUNKNOWN, // An internal intermediate result; should never be returned.
temSEQ_AND_TICKET,
temBAD_NFTOKEN_TRANSFER_FEE,
temBAD_AMM_TOKENS,
temXCHAIN_EQUAL_DOOR_ACCOUNTS,
temXCHAIN_BAD_PROOF,
temXCHAIN_BRIDGE_BAD_ISSUES,
temXCHAIN_BRIDGE_NONDOOR_OWNER,
temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT,
temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT,
temHOOK_DATA_TOO_LARGE,
temEMPTY_DID,
temARRAY_EMPTY,
temARRAY_TOO_LARGE,
};
//------------------------------------------------------------------------------
enum TEFcodes : TERUnderlyingType {
// Note: Range is stable.
// Exact numbers are used in ripple-binary-codec:
// https://github.com/ripple/ripple-binary-codec/blob/master/src/enums/definitions.json
// Use tokens.
// -199 .. -100: F
// Failure (sequence number previously used)
//
// Causes:
// - Transaction cannot succeed because of ledger state.
// - Unexpected ledger state.
// - C++ exception.
//
// Implications:
// - Not applied
// - Not forwarded
// - Could succeed in an imagined ledger.
tefFAILURE = -199,
tefALREADY,
tefBAD_ADD_AUTH,
tefBAD_AUTH,
tefBAD_LEDGER,
tefCREATED,
tefEXCEPTION,
tefINTERNAL,
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
tefPAST_SEQ,
tefWRONG_PRIOR,
tefMASTER_DISABLED,
tefMAX_LEDGER,
tefBAD_SIGNATURE,
tefBAD_QUORUM,
tefNOT_MULTI_SIGNING,
tefBAD_AUTH_MASTER,
tefINVARIANT_FAILED,
tefTOO_BIG,
tefNO_TICKET,
tefNFTOKEN_IS_NOT_TRANSFERABLE,
tefPAST_IMPORT_SEQ,
tefPAST_IMPORT_VL_SEQ,
tefNONDIR_EMIT,
tefIMPORT_BLACKHOLED,
};
//------------------------------------------------------------------------------
enum TERcodes : TERUnderlyingType {
// Note: Range is stable.
// Exact numbers are used in ripple-binary-codec:
// https://github.com/ripple/ripple-binary-codec/blob/master/src/enums/definitions.json
// Use tokens.
// -99 .. -1: R Retry
// sequence too high, no funds for txn fee, originating -account
// non-existent
//
// Cause:
// Prior application of another, possibly non-existent, transaction could
// allow this transaction to succeed.
//
// Implications:
// - Not applied
// - May be forwarded
// - Results indicating the txn was forwarded: terQUEUED
// - All others are not forwarded.
// - Might succeed later
// - Hold
// - Makes hole in sequence which jams transactions.
terRETRY = -99,
terFUNDS_SPENT, // DEPRECATED.
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
terNO_AUTH, // Not authorized to hold IOUs.
terNO_LINE, // Internal flag.
terOWNERS, // Can't succeed with non-zero owner count.
terPRE_SEQ, // Can't pay fee, no point in forwarding, so don't
// burden network.
terLAST, // DEPRECATED.
terNO_RIPPLE, // Rippling not allowed
terQUEUED, // Transaction is being held in TxQ until fee drops
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
terNO_AMM, // AMM doesn't exist for the asset pair
terNO_HOOK // Transaction requires a non-existent hook definition
// (referenced by sfHookHash)
};
//------------------------------------------------------------------------------
enum TEScodes : TERUnderlyingType {
// Note: Exact number must stay stable. This code is stored by value
// in metadata for historic transactions.
// 0: S Success (success)
// Causes:
// - Success.
// Implications:
// - Applied
// - Forwarded
tesSUCCESS = 0,
tesPARTIAL = 1,
};
//------------------------------------------------------------------------------
enum TECcodes : TERUnderlyingType {
// Note: Exact numbers must stay stable. These codes are stored by
// value in metadata for historic transactions.
// 100 .. 255 C
// Claim fee only (ripple transaction with no good paths, pay to
// non-existent account, no path)
//
// Causes:
// - Success, but does not achieve optimal result.
// - Invalid transaction or no effect, but claim fee to use the sequence
// number.
//
// Implications:
// - Applied
// - Forwarded
//
// Only allowed as a return code of appliedTransaction when !tapRETRY.
// Otherwise, treated as terRETRY.
//
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
tecCLAIM = 100,
tecPATH_PARTIAL = 101,
tecUNFUNDED_ADD = 102, // Unused legacy code
tecUNFUNDED_OFFER = 103,
tecUNFUNDED_PAYMENT = 104,
tecFAILED_PROCESSING = 105,
tecDIR_FULL = 121,
tecINSUF_RESERVE_LINE = 122,
tecINSUF_RESERVE_OFFER = 123,
tecNO_DST = 124,
tecNO_DST_INSUF_NATIVE = 125,
tecNO_LINE_INSUF_RESERVE = 126,
tecNO_LINE_REDUNDANT = 127,
tecPATH_DRY = 128,
tecUNFUNDED = 129,
tecNO_ALTERNATIVE_KEY = 130,
tecNO_REGULAR_KEY = 131,
tecOWNERS = 132,
tecNO_ISSUER = 133,
tecNO_AUTH = 134,
tecNO_LINE = 135,
tecINSUFF_FEE = 136,
tecFROZEN = 137,
tecNO_TARGET = 138,
tecNO_PERMISSION = 139,
tecNO_ENTRY = 140,
tecINSUFFICIENT_RESERVE = 141,
tecNEED_MASTER_KEY = 142,
tecDST_TAG_NEEDED = 143,
tecINTERNAL = 144,
tecOVERSIZE = 145,
tecCRYPTOCONDITION_ERROR = 146,
tecINVARIANT_FAILED = 147,
tecEXPIRED = 148,
tecDUPLICATE = 149,
tecKILLED = 150,
tecHAS_OBLIGATIONS = 151,
tecTOO_SOON = 152,
tecHOOK_REJECTED = 153,
tecMAX_SEQUENCE_REACHED = 154,
tecNO_SUITABLE_NFTOKEN_PAGE = 155,
tecNFTOKEN_BUY_SELL_MISMATCH = 156,
tecNFTOKEN_OFFER_TYPE_MISMATCH = 157,
tecCANT_ACCEPT_OWN_NFTOKEN_OFFER = 158,
tecINSUFFICIENT_FUNDS = 159,
tecOBJECT_NOT_FOUND = 160,
tecINSUFFICIENT_PAYMENT = 161,
tecUNFUNDED_AMM = 162,
tecAMM_BALANCE = 163,
tecAMM_FAILED = 164,
tecAMM_INVALID_TOKENS = 165,
tecAMM_EMPTY = 166,
tecAMM_NOT_EMPTY = 167,
tecAMM_ACCOUNT = 168,
tecREQUIRES_FLAG = 169,
tecPRECISION_LOSS = 170,
tecXCHAIN_BAD_TRANSFER_ISSUE = 171,
tecXCHAIN_NO_CLAIM_ID = 172,
tecXCHAIN_BAD_CLAIM_ID = 173,
tecXCHAIN_CLAIM_NO_QUORUM = 174,
tecXCHAIN_PROOF_UNKNOWN_KEY = 175,
tecXCHAIN_CREATE_ACCOUNT_NONXRP_ISSUE = 176,
tecXCHAIN_WRONG_CHAIN = 177,
tecXCHAIN_REWARD_MISMATCH = 178,
tecXCHAIN_NO_SIGNERS_LIST = 179,
tecXCHAIN_SENDING_ACCOUNT_MISMATCH = 180,
tecXCHAIN_INSUFF_CREATE_AMOUNT = 181,
tecXCHAIN_ACCOUNT_CREATE_PAST = 182,
tecXCHAIN_ACCOUNT_CREATE_TOO_MANY = 183,
tecXCHAIN_PAYMENT_FAILED = 184,
tecXCHAIN_SELF_COMMIT = 185,
tecXCHAIN_CREATE_ACCOUNT_DISABLED = 186,
tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR = 191,
tecINSUF_RESERVE_SELLER = 187,
tecIMMUTABLE = 188,
tecTOO_MANY_REMARKS = 189,
tecINCOMPLETE = 190,
// 191: tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR
tecEMPTY_DID = 192,
tecINVALID_UPDATE_TIME = 193,
tecTOKEN_PAIR_NOT_FOUND = 194,
tecARRAY_EMPTY = 195,
tecARRAY_TOO_LARGE = 196,
tecLAST_POSSIBLE_ENTRY = 255,
};
//------------------------------------------------------------------------------
// For generic purposes, a free function that returns the value of a TE*codes.
constexpr TERUnderlyingType
TERtoInt(TELcodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
constexpr TERUnderlyingType
TERtoInt(TEMcodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
constexpr TERUnderlyingType
TERtoInt(TEFcodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
constexpr TERUnderlyingType
TERtoInt(TERcodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
constexpr TERUnderlyingType
TERtoInt(TEScodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
constexpr TERUnderlyingType
TERtoInt(TECcodes v)
{
return safe_cast<TERUnderlyingType>(v);
}
//------------------------------------------------------------------------------
// Template class that is specific to selected ranges of error codes. The
// Trait tells std::enable_if which ranges are allowed.
template <template <typename> class Trait>
class TERSubset
{
public:
TERUnderlyingType code_;
// Constructors
constexpr TERSubset() : code_(tesSUCCESS)
{
}
constexpr TERSubset(TERSubset const& rhs) = default;
constexpr TERSubset(TERSubset&& rhs) = default;
private:
constexpr explicit TERSubset(int rhs) : code_(rhs)
{
}
public:
static constexpr TERSubset
fromInt(int from)
{
return TERSubset(from);
}
// Trait tells enable_if which types are allowed for construction.
template <
typename T,
typename = std::enable_if_t<
Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
constexpr TERSubset(T rhs) : code_(TERtoInt(rhs))
{
}
// Assignment
constexpr TERSubset&
operator=(TERSubset const& rhs) = default;
constexpr TERSubset&
operator=(TERSubset&& rhs) = default;
// Trait tells enable_if which types are allowed for assignment.
template <typename T>
constexpr auto
operator=(T rhs) -> std::enable_if_t<Trait<T>::value, TERSubset&>
{
code_ = TERtoInt(rhs);
return *this;
}
// Conversion to bool.
explicit operator bool() const
{
return code_ < tesSUCCESS || code_ >= tecCLAIM;
}
// Conversion to Json::Value allows assignment to Json::Objects
// without casting.
operator Json::Value() const
{
return Json::Value{code_};
}
// Streaming operator.
friend std::ostream&
operator<<(std::ostream& os, TERSubset const& rhs)
{
return os << rhs.code_;
}
// Return the underlying value. Not a member so similarly named free
// functions can do the same work for the enums.
//
// It's worth noting that an explicit conversion operator was considered
// and rejected. Consider this case, taken from Status.h
//
// class Status {
// int code_;
// public:
// Status (TER ter)
// : code_ (ter) {}
// }
//
// This code compiles with no errors or warnings if TER has an explicit
// (unnamed) conversion to int. To avoid silent conversions like these
// we provide (only) a named conversion.
friend constexpr TERUnderlyingType
TERtoInt(TERSubset v)
{
return v.code_;
}
};
// Comparison operators.
// Only enabled if both arguments return int if TERtiInt is called with them.
template <typename L, typename R>
constexpr auto
operator==(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) == TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator!=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) != TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator<(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) < TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator<=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) <= TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator>(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) > TERtoInt(rhs);
}
template <typename L, typename R>
constexpr auto
operator>=(L const& lhs, R const& rhs) -> std::enable_if_t<
std::is_same<decltype(TERtoInt(lhs)), int>::value &&
std::is_same<decltype(TERtoInt(rhs)), int>::value,
bool>
{
return TERtoInt(lhs) >= TERtoInt(rhs);
}
//------------------------------------------------------------------------------
// Use traits to build a TERSubset that can convert from any of the TE*codes
// enums *except* TECcodes: NotTEC
// NOTE: NotTEC is useful for codes returned by preflight in transactors.
// Preflight checks occur prior to signature checking. If preflight returned
// a tec code, then a malicious user could submit a transaction with a very
// large fee and have that fee charged against an account without using that
// account's valid signature.
template <typename FROM>
class CanCvtToNotTEC : public std::false_type
{
};
template <>
class CanCvtToNotTEC<TELcodes> : public std::true_type
{
};
template <>
class CanCvtToNotTEC<TEMcodes> : public std::true_type
{
};
template <>
class CanCvtToNotTEC<TEFcodes> : public std::true_type
{
};
template <>
class CanCvtToNotTEC<TERcodes> : public std::true_type
{
};
template <>
class CanCvtToNotTEC<TEScodes> : public std::true_type
{
};
using NotTEC = TERSubset<CanCvtToNotTEC>;
//------------------------------------------------------------------------------
// Use traits to build a TERSubset that can convert from any of the TE*codes
// enums as well as from NotTEC.
template <typename FROM>
class CanCvtToTER : public std::false_type
{
};
template <>
class CanCvtToTER<TELcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<TEMcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<TEFcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<TERcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<TEScodes> : public std::true_type
{
};
template <>
class CanCvtToTER<TECcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<NotTEC> : public std::true_type
{
};
// TER allows all of the subsets.
using TER = TERSubset<CanCvtToTER>;
//------------------------------------------------------------------------------
inline bool
isTelLocal(TER x)
{
return ((x) >= telLOCAL_ERROR && (x) < temMALFORMED);
}
inline bool
isTemMalformed(TER x)
{
return ((x) >= temMALFORMED && (x) < tefFAILURE);
}
inline bool
isTefFailure(TER x)
{
return ((x) >= tefFAILURE && (x) < terRETRY);
}
inline bool
isTerRetry(TER x)
{
return ((x) >= terRETRY && (x) < tesSUCCESS);
}
template <typename T>
inline bool
isTesSuccess(T x)
{
return ((x) >= tesSUCCESS) && (x) < tecCLAIM;
}
inline bool
isTesSuccess(TER x)
{
return ((x) >= tesSUCCESS) && (x) < tecCLAIM;
}
inline bool
isTecClaim(TER x)
{
return ((x) >= tecCLAIM);
}
std::unordered_map<
TERUnderlyingType,
std::pair<char const* const, char const* const>> const&
transResults();
bool
transResultInfo(TER code, std::string& token, std::string& text);
std::string
transToken(TER code);
std::string
transHuman(TER code);
std::optional<TER>
transCode(std::string const& token);
} // namespace ripple
#endif

View File

@@ -0,0 +1,227 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_TXFLAGS_H_INCLUDED
#define RIPPLE_PROTOCOL_TXFLAGS_H_INCLUDED
#include <cstdint>
namespace ripple {
/** Transaction flags.
These flags are specified in a transaction's 'Flags' field and modify the
behavior of that transaction.
There are two types of flags:
(1) Universal flags: these are flags which apply to, and are interpreted
the same way by, all transactions, except, perhaps,
to special pseudo-transactions.
(2) Tx-Specific flags: these are flags which are interpreted according
to the type of the transaction being executed.
That is, the same numerical flag value may have
different effects, depending on the transaction
being executed.
@note The universal transaction flags occupy the high-order 8 bits. The
tx-specific flags occupy the remaining 24 bits.
@warning Transaction flags form part of the protocol. **Changing them
should be avoided because without special handling, this will
result in a hard fork.**
@ingroup protocol
*/
// Formatting equals sign aligned 4 spaces after longest prefix, except for
// wrapped lines
// clang-format off
// Universal Transaction flags:
enum UniversalFlags : uint32_t {
tfFullyCanonicalSig = 0x80000000,
};
constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig;
constexpr std::uint32_t tfUniversalMask = ~tfUniversal;
// AccountSet flags:
enum AccountSetFlags : uint32_t {
tfRequireDestTag = 0x00010000,
tfOptionalDestTag = 0x00020000,
tfRequireAuth = 0x00040000,
tfOptionalAuth = 0x00080000,
tfDisallowXRP = 0x00100000,
tfAllowXRP = 0x00200000,
};
constexpr std::uint32_t tfAccountSetMask =
~(tfUniversal | tfRequireDestTag | tfOptionalDestTag | tfRequireAuth |
tfOptionalAuth | tfDisallowXRP | tfAllowXRP);
// AccountSet SetFlag/ClearFlag values
enum AccountFlags : uint32_t {
asfRequireDest = 1,
asfRequireAuth = 2,
asfDisallowXRP = 3,
asfDisableMaster = 4,
asfAccountTxnID = 5,
asfNoFreeze = 6,
asfGlobalFreeze = 7,
asfDefaultRipple = 8,
asfDepositAuth = 9,
asfAuthorizedNFTokenMinter = 10,
asfTshCollect = 11,
asfDisallowIncomingNFTokenOffer = 12,
asfDisallowIncomingCheck = 13,
asfDisallowIncomingPayChan = 14,
asfDisallowIncomingTrustline = 15,
asfDisallowIncomingRemit = 16,
asfAllowTrustLineClawback = 17,
};
// OfferCreate flags:
enum OfferCreateFlags : uint32_t {
tfPassive = 0x00010000,
tfImmediateOrCancel = 0x00020000,
tfFillOrKill = 0x00040000,
tfSell = 0x00080000,
};
constexpr std::uint32_t tfOfferCreateMask =
~(tfUniversal | tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
// Payment flags:
enum PaymentFlags : uint32_t {
tfNoRippleDirect = 0x00010000,
tfPartialPayment = 0x00020000,
tfLimitQuality = 0x00040000,
};
constexpr std::uint32_t tfPaymentMask =
~(tfUniversal | tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
// TrustSet flags:
enum TrustSetFlags : uint32_t {
tfSetfAuth = 0x00010000,
tfSetNoRipple = 0x00020000,
tfClearNoRipple = 0x00040000,
tfSetFreeze = 0x00100000,
tfClearFreeze = 0x00200000,
};
constexpr std::uint32_t tfTrustSetMask =
~(tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple | tfSetFreeze |
tfClearFreeze);
// EnableAmendment flags:
enum EnableAmendmentFlags : std::uint32_t {
tfGotMajority = 0x00010000,
tfLostMajority = 0x00020000,
tfTestSuite = 0x80000000,
};
// PaymentChannelClaim flags:
enum PaymentChannelClaimFlags : uint32_t {
tfRenew = 0x00010000,
tfClose = 0x00020000,
};
constexpr std::uint32_t tfPayChanClaimMask = ~(tfUniversal | tfRenew | tfClose);
// NFTokenMint flags:
enum NFTokenMintFlags : uint32_t {
tfBurnable = 0x00000001,
tfOnlyXRP = 0x00000002,
tfTrustLine = 0x00000004,
tfTransferable = 0x00000008,
tfStrongTSH = 0x00008000,
};
constexpr std::uint32_t const tfNFTokenMintOldMask =
~(tfUniversal | tfBurnable | tfOnlyXRP | tfTrustLine | tfTransferable | tfStrongTSH);
// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between
// accounts allowed a TrustLine to be added to the issuer of that token
// without explicit permission from that issuer. This was enabled by
// minting the NFToken with the tfTrustLine flag set.
//
// That capability could be used to attack the NFToken issuer. It
// would be possible for two accounts to trade the NFToken back and forth
// building up any number of TrustLines on the issuer, increasing the
// issuer's reserve without bound.
//
// The fixRemoveNFTokenAutoTrustLine amendment disables minting with the
// tfTrustLine flag as a way to prevent the attack. But until the
// amendment passes we still need to keep the old behavior available.
constexpr std::uint32_t const tfNFTokenMintMask =
~(tfUniversal | tfBurnable | tfOnlyXRP | tfTransferable | tfStrongTSH);
// NFTokenCreateOffer flags:
enum NFTokenCreateOfferFlags : uint32_t {
tfSellNFToken = 0x00000001,
};
constexpr std::uint32_t const tfNFTokenCreateOfferMask =
~(tfUniversal | tfSellNFToken);
// NFTokenCancelOffer flags:
constexpr std::uint32_t const tfNFTokenCancelOfferMask = ~(tfUniversal);
// NFTokenAcceptOffer flags:
constexpr std::uint32_t const tfNFTokenAcceptOfferMask = ~tfUniversal;
// URIToken mask
constexpr std::uint32_t const tfURITokenMintMask = ~(tfUniversal | tfBurnable);
constexpr std::uint32_t const tfURITokenNonMintMask = ~tfUniversal;
// ClaimReward flags:
enum ClaimRewardFlags : uint32_t {
tfOptOut = 0x00000001,
};
constexpr std::uint32_t const tfClaimRewardMask = ~(tfUniversal | tfOptOut);
// Remarks flags:
constexpr std::uint32_t const tfImmutable = 1;
// Clawback flags:
constexpr std::uint32_t const tfClawbackMask = ~tfUniversal;
// AMM Flags:
constexpr std::uint32_t tfLPToken = 0x00010000;
constexpr std::uint32_t tfWithdrawAll = 0x00020000;
constexpr std::uint32_t tfOneAssetWithdrawAll = 0x00040000;
constexpr std::uint32_t tfSingleAsset = 0x00080000;
constexpr std::uint32_t tfTwoAsset = 0x00100000;
constexpr std::uint32_t tfOneAssetLPToken = 0x00200000;
constexpr std::uint32_t tfLimitLPToken = 0x00400000;
constexpr std::uint32_t tfTwoAssetIfEmpty = 0x00800000;
constexpr std::uint32_t tfWithdrawSubTx =
tfLPToken | tfSingleAsset | tfTwoAsset | tfOneAssetLPToken |
tfLimitLPToken | tfWithdrawAll | tfOneAssetWithdrawAll;
constexpr std::uint32_t tfDepositSubTx =
tfLPToken | tfSingleAsset | tfTwoAsset | tfOneAssetLPToken |
tfLimitLPToken | tfTwoAssetIfEmpty;
constexpr std::uint32_t tfWithdrawMask = ~(tfUniversal | tfWithdrawSubTx);
constexpr std::uint32_t tfDepositMask = ~(tfUniversal | tfDepositSubTx);
// BridgeModify flags:
constexpr std::uint32_t tfClearAccountCreateAmount = 0x00010000;
constexpr std::uint32_t tfBridgeModifyMask = ~(tfUniversal | tfClearAccountCreateAmount);
// clang-format on
} // namespace ripple
#endif

View File

@@ -0,0 +1,268 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_TXFORMATS_H_INCLUDED
#define RIPPLE_PROTOCOL_TXFORMATS_H_INCLUDED
#include <ripple/protocol/KnownFormats.h>
namespace ripple {
/** Transaction type identifiers.
These are part of the binary message format.
@ingroup protocol
*/
/** Transaction type identifieers
Each ledger object requires a unique type identifier, which is stored
within the object itself; this makes it possible to iterate the entire
ledger and determine each object's type and verify that the object you
retrieved from a given hash matches the expected type.
@warning Since these values are included in transactions, which are signed
objects, and used by the code to determine the type of transaction
being invoked, they are part of the protocol. **Changing them
should be avoided because without special handling, this will
result in a hard fork.**
@note When retiring types, the specific values should not be removed but
should be marked as [[deprecated]]. This is to avoid accidental
reuse of identifiers.
@todo The C++ language does not enable checking for duplicate values
here. If it becomes possible then we should do this.
@ingroup protocol
*/
// clang-format off
enum TxType : std::uint16_t
{
/** This transaction type executes a payment. */
ttPAYMENT = 0,
/** This transaction type creates an escrow object. */
ttESCROW_CREATE = 1,
/** This transaction type completes an existing escrow. */
ttESCROW_FINISH = 2,
/** This transaction type adjusts various account settings. */
ttACCOUNT_SET = 3,
/** This transaction type cancels an existing escrow. */
ttESCROW_CANCEL = 4,
/** This transaction type sets or clears an account's "regular key". */
ttREGULAR_KEY_SET = 5,
/** This transaction type is deprecated; it is retained for historical purposes. */
ttNICKNAME_SET [[deprecated("This transaction type is not supported and should not be used.")]] = 6,
/** This transaction type creates an offer to trade one asset for another. */
ttOFFER_CREATE = 7,
/** This transaction type cancels existing offers to trade one asset for another. */
ttOFFER_CANCEL = 8,
/** This transaction type is deprecated; it is retained for historical purposes. */
ttCONTRACT [[deprecated("This transaction type is not supported and should not be used.")]] = 9,
/** This transaction type creates a new set of tickets. */
ttTICKET_CREATE = 10,
/** This identifier was never used, but the slot is reserved for historical purposes. */
ttSPINAL_TAP [[deprecated("This transaction type is not supported and should not be used.")]] = 11,
/** This transaction type modifies the signer list associated with an account. */
ttSIGNER_LIST_SET = 12,
/** This transaction type creates a new unidirectional XRP payment channel. */
ttPAYCHAN_CREATE = 13,
/** This transaction type funds an existing unidirectional XRP payment channel. */
ttPAYCHAN_FUND = 14,
/** This transaction type submits a claim against an existing unidirectional payment channel. */
ttPAYCHAN_CLAIM = 15,
/** This transaction type creates a new check. */
ttCHECK_CREATE = 16,
/** This transaction type cashes an existing check. */
ttCHECK_CASH = 17,
/** This transaction type cancels an existing check. */
ttCHECK_CANCEL = 18,
/** This transaction type grants or revokes authorization to transfer funds. */
ttDEPOSIT_PREAUTH = 19,
/** This transaction type modifies a trustline between two accounts. */
ttTRUST_SET = 20,
/** This transaction type deletes an existing account. */
ttACCOUNT_DELETE = 21,
/** This transaction type installs a hook. */
ttHOOK_SET = 22,
/** This transaction mints a new NFT. */
ttNFTOKEN_MINT = 25,
/** This transaction burns (i.e. destroys) an existing NFT. */
ttNFTOKEN_BURN = 26,
/** This transaction creates a new offer to buy or sell an NFT. */
ttNFTOKEN_CREATE_OFFER = 27,
/** This transaction cancels an existing offer to buy or sell an existing NFT. */
ttNFTOKEN_CANCEL_OFFER = 28,
/** This transaction accepts an existing offer to buy or sell an existing NFT. */
ttNFTOKEN_ACCEPT_OFFER = 29,
/** This transaction claws back issued tokens. */
ttCLAWBACK = 30,
/** This transaction type creates an AMM instance */
ttAMM_CREATE = 35,
/** This transaction type deposits into an AMM instance */
ttAMM_DEPOSIT = 36,
/** This transaction type withdraws from an AMM instance */
ttAMM_WITHDRAW = 37,
/** This transaction type votes for the trading fee */
ttAMM_VOTE = 38,
/** This transaction type bids for the auction slot */
ttAMM_BID = 39,
/** This transaction type deletes AMM in the empty state */
ttAMM_DELETE = 40,
/** This transaction mints/burns/buys/sells a URI TOKEN */
ttURITOKEN_MINT = 45,
ttURITOKEN_BURN = 46,
ttURITOKEN_BUY = 47,
ttURITOKEN_CREATE_SELL_OFFER = 48,
ttURITOKEN_CANCEL_SELL_OFFER = 49,
/** This transactions creates a crosschain sequence number */
ttXCHAIN_CREATE_CLAIM_ID = 50,
/** This transactions initiates a crosschain transaction */
ttXCHAIN_COMMIT = 51,
/** This transaction completes a crosschain transaction */
ttXCHAIN_CLAIM = 52,
/** This transaction initiates a crosschain account create transaction */
ttXCHAIN_ACCOUNT_CREATE_COMMIT = 53,
/** This transaction adds an attestation to a claimid*/
ttXCHAIN_ADD_CLAIM_ATTESTATION = 54,
/** This transaction adds an attestation to a claimid*/
ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION = 55,
/** This transaction modifies a sidechain */
ttXCHAIN_MODIFY_BRIDGE = 56,
/** This transactions creates a sidechain */
ttXCHAIN_CREATE_BRIDGE = 57,
/** This transaction type creates or updates a DID */
ttDID_SET = 58,
/** This transaction type deletes a DID */
ttDID_DELETE = 59,
/** This transaction type creates an Oracle instance */
ttORACLE_SET = 60,
/** This transaction type deletes an Oracle instance */
ttORACLE_DELETE = 61,
/* A note attaching transactor that allows the owner or issuer (on a object by object basis) to attach remarks */
ttREMARKS_SET = 94,
/* A payment transactor that delivers only the exact amounts specified, creating accounts and TLs as needed
* that the sender pays for. */
ttREMIT = 95,
/** This transaction can only be used by the genesis account, which is controlled exclusively by
* rewards/governance hooks, to print new XRP to be delivered directly to an array of destinations,
* according to reward schedule */
ttGENESIS_MINT = 96,
/** This transaction accepts a proof of burn from an external network as a basis
* for minting according to featureImport */
ttIMPORT = 97,
/** This transaction resets accumulator/counters and claims a reward for holding an average balance
* from a specified hook */
ttCLAIM_REWARD = 98,
/** This transaction invokes a hook, providing arbitrary data. Essentially as a 0 drop payment. **/
ttINVOKE = 99,
/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html
*/
ttAMENDMENT = 100,
/** This system-generated transaction type is used to update the network's fee settings.
For details, see: https://xrpl.org/fee-voting.html
*/
ttFEE = 101,
/** This system-generated transaction type is used to update the network's negative UNL
For details, see: https://xrpl.org/negative-unl.html
*/
ttUNL_MODIFY = 102,
ttEMIT_FAILURE = 103,
ttUNL_REPORT = 104,
};
// clang-format on
/** Manages the list of known transaction formats.
*/
class TxFormats : public KnownFormats<TxType, TxFormats>
{
private:
/** Create the object.
This will load the object with all the known transaction formats.
*/
TxFormats();
public:
static TxFormats const&
getInstance();
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,183 @@
//------------------------------------------------------------------------------
/*
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_APP_TX_TRANSACTIONMETA_H_INCLUDED
#define RIPPLE_APP_TX_TRANSACTIONMETA_H_INCLUDED
#include <ripple/beast/utility/Journal.h>
#include <ripple/protocol/STArray.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/TER.h>
#include <boost/container/flat_set.hpp>
#include <optional>
namespace ripple {
class TxMeta
{
private:
struct CtorHelper
{
explicit CtorHelper() = default;
};
template <class T>
TxMeta(
uint256 const& txID,
std::uint32_t ledger,
T const& data,
CtorHelper);
public:
TxMeta(uint256 const& transactionID, std::uint32_t ledger);
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
uint256 const&
getTxID() const
{
return mTransactionID;
}
std::uint32_t
getLgrSeq() const
{
return mLedger;
}
int
getResult() const
{
return mResult;
}
TER
getResultTER() const
{
return TER::fromInt(mResult);
}
std::uint32_t
getIndex() const
{
return mIndex;
}
void
setResult(TER res, int index);
void
setAffectedNode(uint256 const&, SField const& type, std::uint16_t nodeType);
STObject&
getAffectedNode(SLE::ref node, SField const& type); // create if needed
STObject&
getAffectedNode(uint256 const&);
/** Return a list of accounts affected by this transaction */
boost::container::flat_set<AccountID>
getAffectedAccounts() const;
Json::Value
getJson(JsonOptions p) const
{
return getAsObject().getJson(p);
}
void
addRaw(Serializer&, TER, std::uint32_t index);
STObject
getAsObject() const;
STArray&
getNodes()
{
return (mNodes);
}
STArray const&
getNodes() const
{
return (mNodes);
}
void
setDeliveredAmount(STAmount const& delivered)
{
mDelivered = delivered;
}
STArray const&
getHookExecutions() const
{
return *mHookExecutions;
}
STArray const&
getHookEmissions() const
{
return *mHookEmissions;
}
void
setHookExecutions(STArray const& hookExecutions)
{
mHookExecutions = hookExecutions;
}
void
setHookEmissions(STArray const& hookEmissions)
{
mHookEmissions = hookEmissions;
}
bool
hasHookExecutions() const
{
return static_cast<bool>(mHookExecutions);
}
bool
hasHookEmissions() const
{
return static_cast<bool>(mHookEmissions);
}
STAmount
getDeliveredAmount() const
{
assert(hasDeliveredAmount());
return *mDelivered;
}
bool
hasDeliveredAmount() const
{
return static_cast<bool>(mDelivered);
}
private:
uint256 mTransactionID;
std::uint32_t mLedger;
std::uint32_t mIndex;
int mResult;
std::optional<STAmount> mDelivered;
std::optional<STArray> mHookExecutions;
std::optional<STArray> mHookEmissions;
STArray mNodes;
};
} // namespace ripple
#endif

View File

@@ -0,0 +1,151 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2014 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_PROTOCOL_UINTTYPES_H_INCLUDED
#define RIPPLE_PROTOCOL_UINTTYPES_H_INCLUDED
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/basics/base_uint.h>
#include <ripple/beast/utility/Zero.h>
#include <ripple/protocol/AccountID.h>
namespace ripple {
namespace detail {
class CurrencyTag
{
public:
explicit CurrencyTag() = default;
};
class DirectoryTag
{
public:
explicit DirectoryTag() = default;
};
class NodeIDTag
{
public:
explicit NodeIDTag() = default;
};
} // namespace detail
/** Directory is an index into the directory of offer books.
The last 64 bits of this are the quality. */
using Directory = base_uint<256, detail::DirectoryTag>;
/** Currency is a hash representing a specific currency. */
using Currency = base_uint<160, detail::CurrencyTag>;
/** NodeID is a 160-bit hash representing one node. */
using NodeID = base_uint<160, detail::NodeIDTag>;
/** XRP currency. */
Currency const&
xrpCurrency();
/** A placeholder for empty currencies. */
Currency const&
noCurrency();
/** We deliberately disallow the currency that looks like "XAH" because too
many people were using it instead of the correct XAH currency. */
Currency const&
badCurrency();
inline bool
isXRP(Currency const& c)
{
return c == beast::zero;
}
inline bool
isBadCurrency(Currency const& c)
{
static const std::set<Currency> badCurrencies{
Currency(0x7861680000000000), // xah
Currency(0x7861480000000000), // xaH
Currency(0x7841680000000000), // xAh
Currency(0x7841480000000000), // xAH
Currency(0x5861680000000000), // Xah
Currency(0x5861480000000000), // XaH
Currency(0x5841680000000000), // XAh
Currency(0x5841480000000000) // XAH
};
return badCurrencies.find(c) != badCurrencies.end();
}
/** Returns "", "XAH", or three letter ISO code. */
std::string
to_string(Currency const& c);
/** Tries to convert a string to a Currency, returns true on success.
@note This function will return success if the resulting currency is
badCurrency(). This legacy behavior is unfortunate; changing this
will require very careful checking everywhere and may mean having
to rewrite some unit test code.
*/
bool
to_currency(Currency&, std::string const&);
/** Tries to convert a string to a Currency, returns noCurrency() on failure.
@note This function can return badCurrency(). This legacy behavior is
unfortunate; changing this will require very careful checking
everywhere and may mean having to rewrite some unit test code.
*/
Currency
to_currency(std::string const&);
inline std::ostream&
operator<<(std::ostream& os, Currency const& x)
{
os << to_string(x);
return os;
}
} // namespace ripple
namespace std {
template <>
struct hash<ripple::Currency> : ripple::Currency::hasher
{
explicit hash() = default;
};
template <>
struct hash<ripple::NodeID> : ripple::NodeID::hasher
{
explicit hash() = default;
};
template <>
struct hash<ripple::Directory> : ripple::Directory::hasher
{
explicit hash() = default;
};
} // namespace std
#endif

View File

@@ -0,0 +1,504 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2022 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_PROTOCOL_STXATTESTATIONS_H_INCLUDED
#define RIPPLE_PROTOCOL_STXATTESTATIONS_H_INCLUDED
#include <ripple/basics/Buffer.h>
#include <ripple/basics/Expected.h>
#include <ripple/protocol/AccountID.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STXChainBridge.h>
#include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/TER.h>
#include <boost/container/flat_set.hpp>
#include <boost/container/vector.hpp>
#include <cstddef>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace ripple {
namespace Attestations {
struct AttestationBase
{
// Account associated with the public key
AccountID attestationSignerAccount;
// Public key from the witness server attesting to the event
PublicKey publicKey;
// Signature from the witness server attesting to the event
Buffer signature;
// Account on the sending chain that triggered the event (sent the
// transaction)
AccountID sendingAccount;
// Amount transfered on the sending chain
STAmount sendingAmount;
// Account on the destination chain that collects a share of the attestation
// reward
AccountID rewardAccount;
// Amount was transfered on the locking chain
bool wasLockingChainSend;
explicit AttestationBase(
AccountID attestationSignerAccount_,
PublicKey const& publicKey_,
Buffer signature_,
AccountID const& sendingAccount_,
STAmount const& sendingAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_);
AttestationBase(AttestationBase const&) = default;
virtual ~AttestationBase() = default;
AttestationBase&
operator=(AttestationBase const&) = default;
// verify that the signature attests to the data.
bool
verify(STXChainBridge const& bridge) const;
protected:
explicit AttestationBase(STObject const& o);
explicit AttestationBase(Json::Value const& v);
[[nodiscard]] static bool
equalHelper(AttestationBase const& lhs, AttestationBase const& rhs);
[[nodiscard]] static bool
sameEventHelper(AttestationBase const& lhs, AttestationBase const& rhs);
void
addHelper(STObject& o) const;
private:
[[nodiscard]] virtual std::vector<std::uint8_t>
message(STXChainBridge const& bridge) const = 0;
};
// Attest to a regular cross-chain transfer
struct AttestationClaim : AttestationBase
{
std::uint64_t claimID;
std::optional<AccountID> dst;
explicit AttestationClaim(
AccountID attestationSignerAccount_,
PublicKey const& publicKey_,
Buffer signature_,
AccountID const& sendingAccount_,
STAmount const& sendingAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
std::uint64_t claimID_,
std::optional<AccountID> const& dst_);
explicit AttestationClaim(
STXChainBridge const& bridge,
AccountID attestationSignerAccount_,
PublicKey const& publicKey_,
SecretKey const& secretKey_,
AccountID const& sendingAccount_,
STAmount const& sendingAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
std::uint64_t claimID_,
std::optional<AccountID> const& dst_);
explicit AttestationClaim(STObject const& o);
explicit AttestationClaim(Json::Value const& v);
[[nodiscard]] STObject
toSTObject() const;
// return true if the two attestations attest to the same thing
[[nodiscard]] bool
sameEvent(AttestationClaim const& rhs) const;
[[nodiscard]] static std::vector<std::uint8_t>
message(
STXChainBridge const& bridge,
AccountID const& sendingAccount,
STAmount const& sendingAmount,
AccountID const& rewardAccount,
bool wasLockingChainSend,
std::uint64_t claimID,
std::optional<AccountID> const& dst);
[[nodiscard]] bool
validAmounts() const;
private:
[[nodiscard]] std::vector<std::uint8_t>
message(STXChainBridge const& bridge) const override;
friend bool
operator==(AttestationClaim const& lhs, AttestationClaim const& rhs);
};
struct CmpByClaimID
{
bool
operator()(AttestationClaim const& lhs, AttestationClaim const& rhs) const
{
return lhs.claimID < rhs.claimID;
}
};
// Attest to a cross-chain transfer that creates an account
struct AttestationCreateAccount : AttestationBase
{
// createCount on the sending chain. This is the value of the `CreateCount`
// field of the bridge on the sending chain when the transaction was
// executed.
std::uint64_t createCount;
// Account to create on the destination chain
AccountID toCreate;
// Total amount of the reward pool
STAmount rewardAmount;
explicit AttestationCreateAccount(STObject const& o);
explicit AttestationCreateAccount(Json::Value const& v);
explicit AttestationCreateAccount(
AccountID attestationSignerAccount_,
PublicKey const& publicKey_,
Buffer signature_,
AccountID const& sendingAccount_,
STAmount const& sendingAmount_,
STAmount const& rewardAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
std::uint64_t createCount_,
AccountID const& toCreate_);
explicit AttestationCreateAccount(
STXChainBridge const& bridge,
AccountID attestationSignerAccount_,
PublicKey const& publicKey_,
SecretKey const& secretKey_,
AccountID const& sendingAccount_,
STAmount const& sendingAmount_,
STAmount const& rewardAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
std::uint64_t createCount_,
AccountID const& toCreate_);
[[nodiscard]] STObject
toSTObject() const;
// return true if the two attestations attest to the same thing
[[nodiscard]] bool
sameEvent(AttestationCreateAccount const& rhs) const;
friend bool
operator==(
AttestationCreateAccount const& lhs,
AttestationCreateAccount const& rhs);
[[nodiscard]] static std::vector<std::uint8_t>
message(
STXChainBridge const& bridge,
AccountID const& sendingAccount,
STAmount const& sendingAmount,
STAmount const& rewardAmount,
AccountID const& rewardAccount,
bool wasLockingChainSend,
std::uint64_t createCount,
AccountID const& dst);
[[nodiscard]] bool
validAmounts() const;
private:
[[nodiscard]] std::vector<std::uint8_t>
message(STXChainBridge const& bridge) const override;
};
struct CmpByCreateCount
{
bool
operator()(
AttestationCreateAccount const& lhs,
AttestationCreateAccount const& rhs) const
{
return lhs.createCount < rhs.createCount;
}
};
}; // namespace Attestations
// Result when checking when two attestation match.
enum class AttestationMatch {
// One of the fields doesn't match, and it isn't the dst field
nonDstMismatch,
// all of the fields match, except the dst field
matchExceptDst,
// all of the fields match
match
};
struct XChainClaimAttestation
{
using TSignedAttestation = Attestations::AttestationClaim;
static SField const& ArrayFieldName;
AccountID keyAccount;
PublicKey publicKey;
STAmount amount;
AccountID rewardAccount;
bool wasLockingChainSend;
std::optional<AccountID> dst;
struct MatchFields
{
STAmount amount;
bool wasLockingChainSend;
std::optional<AccountID> dst;
MatchFields(TSignedAttestation const& att);
MatchFields(
STAmount const& a,
bool b,
std::optional<AccountID> const& d)
: amount{a}, wasLockingChainSend{b}, dst{d}
{
}
};
explicit XChainClaimAttestation(
AccountID const& keyAccount_,
PublicKey const& publicKey_,
STAmount const& amount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
std::optional<AccountID> const& dst);
explicit XChainClaimAttestation(
STAccount const& keyAccount_,
PublicKey const& publicKey_,
STAmount const& amount_,
STAccount const& rewardAccount_,
bool wasLockingChainSend_,
std::optional<STAccount> const& dst);
explicit XChainClaimAttestation(TSignedAttestation const& claimAtt);
explicit XChainClaimAttestation(STObject const& o);
explicit XChainClaimAttestation(Json::Value const& v);
AttestationMatch
match(MatchFields const& rhs) const;
[[nodiscard]] STObject
toSTObject() const;
friend bool
operator==(
XChainClaimAttestation const& lhs,
XChainClaimAttestation const& rhs);
};
struct XChainCreateAccountAttestation
{
using TSignedAttestation = Attestations::AttestationCreateAccount;
static SField const& ArrayFieldName;
AccountID keyAccount;
PublicKey publicKey;
STAmount amount;
STAmount rewardAmount;
AccountID rewardAccount;
bool wasLockingChainSend;
AccountID dst;
struct MatchFields
{
STAmount amount;
STAmount rewardAmount;
bool wasLockingChainSend;
AccountID dst;
MatchFields(TSignedAttestation const& att);
};
explicit XChainCreateAccountAttestation(
AccountID const& keyAccount_,
PublicKey const& publicKey_,
STAmount const& amount_,
STAmount const& rewardAmount_,
AccountID const& rewardAccount_,
bool wasLockingChainSend_,
AccountID const& dst_);
explicit XChainCreateAccountAttestation(TSignedAttestation const& claimAtt);
explicit XChainCreateAccountAttestation(STObject const& o);
explicit XChainCreateAccountAttestation(Json::Value const& v);
[[nodiscard]] STObject
toSTObject() const;
AttestationMatch
match(MatchFields const& rhs) const;
friend bool
operator==(
XChainCreateAccountAttestation const& lhs,
XChainCreateAccountAttestation const& rhs);
};
// Attestations from witness servers for a particular claimid and bridge.
// Only one attestation per signature is allowed.
template <class TAttestation>
class XChainAttestationsBase
{
public:
using AttCollection = std::vector<TAttestation>;
private:
// Set a max number of allowed attestations to limit the amount of memory
// allocated and processing time. This number is much larger than the actual
// number of attestation a server would ever expect.
static constexpr std::uint32_t maxAttestations = 256;
AttCollection attestations_;
protected:
// Prevent slicing to the base class
~XChainAttestationsBase() = default;
public:
XChainAttestationsBase() = default;
XChainAttestationsBase(XChainAttestationsBase const& rhs) = default;
XChainAttestationsBase&
operator=(XChainAttestationsBase const& rhs) = default;
explicit XChainAttestationsBase(AttCollection&& sigs);
explicit XChainAttestationsBase(Json::Value const& v);
explicit XChainAttestationsBase(STArray const& arr);
[[nodiscard]] STArray
toSTArray() const;
typename AttCollection::const_iterator
begin() const;
typename AttCollection::const_iterator
end() const;
typename AttCollection::iterator
begin();
typename AttCollection::iterator
end();
template <class F>
std::size_t
erase_if(F&& f);
std::size_t
size() const;
bool
empty() const;
AttCollection const&
attestations() const;
template <class T>
void
emplace_back(T&& att);
};
template <class TAttestation>
[[nodiscard]] inline bool
operator==(
XChainAttestationsBase<TAttestation> const& lhs,
XChainAttestationsBase<TAttestation> const& rhs)
{
return lhs.attestations() == rhs.attestations();
}
template <class TAttestation>
inline typename XChainAttestationsBase<TAttestation>::AttCollection const&
XChainAttestationsBase<TAttestation>::attestations() const
{
return attestations_;
};
template <class TAttestation>
template <class T>
inline void
XChainAttestationsBase<TAttestation>::emplace_back(T&& att)
{
attestations_.emplace_back(std::forward<T>(att));
};
template <class TAttestation>
template <class F>
inline std::size_t
XChainAttestationsBase<TAttestation>::erase_if(F&& f)
{
return std::erase_if(attestations_, std::forward<F>(f));
}
template <class TAttestation>
inline std::size_t
XChainAttestationsBase<TAttestation>::size() const
{
return attestations_.size();
}
template <class TAttestation>
inline bool
XChainAttestationsBase<TAttestation>::empty() const
{
return attestations_.empty();
}
class XChainClaimAttestations final
: public XChainAttestationsBase<XChainClaimAttestation>
{
using TBase = XChainAttestationsBase<XChainClaimAttestation>;
using TBase::TBase;
};
class XChainCreateAccountAttestations final
: public XChainAttestationsBase<XChainCreateAccountAttestation>
{
using TBase = XChainAttestationsBase<XChainCreateAccountAttestation>;
using TBase::TBase;
};
} // namespace ripple
#endif // STXCHAINATTESTATIONS_H_

View File

@@ -0,0 +1,165 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_STVAR_H_INCLUDED
#define RIPPLE_PROTOCOL_STVAR_H_INCLUDED
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/Serializer.h>
#include <cstddef>
#include <cstdint>
#include <typeinfo>
#include <utility>
namespace ripple {
namespace detail {
struct defaultObject_t
{
explicit defaultObject_t() = default;
};
struct nonPresentObject_t
{
explicit nonPresentObject_t() = default;
};
extern defaultObject_t defaultObject;
extern nonPresentObject_t nonPresentObject;
// "variant" that can hold any type of serialized object
// and includes a small-object allocation optimization.
class STVar
{
private:
// The largest "small object" we can accomodate
static std::size_t constexpr max_size = 72;
std::aligned_storage<max_size>::type d_;
STBase* p_ = nullptr;
public:
~STVar();
STVar(STVar const& other);
STVar(STVar&& other);
STVar&
operator=(STVar const& rhs);
STVar&
operator=(STVar&& rhs);
STVar(STBase&& t)
{
p_ = t.move(max_size, &d_);
}
STVar(STBase const& t)
{
p_ = t.copy(max_size, &d_);
}
STVar(defaultObject_t, SField const& name);
STVar(nonPresentObject_t, SField const& name);
STVar(SerialIter& sit, SField const& name, int depth = 0);
STBase&
get()
{
return *p_;
}
STBase&
operator*()
{
return get();
}
STBase*
operator->()
{
return &get();
}
STBase const&
get() const
{
return *p_;
}
STBase const&
operator*() const
{
return get();
}
STBase const*
operator->() const
{
return &get();
}
template <class T, class... Args>
friend STVar
make_stvar(Args&&... args);
private:
STVar() = default;
STVar(SerializedTypeID id, SField const& name);
void
destroy();
template <class T, class... Args>
void
construct(Args&&... args)
{
if constexpr (sizeof(T) > max_size)
p_ = new T(std::forward<Args>(args)...);
else
p_ = new (&d_) T(std::forward<Args>(args)...);
}
bool
on_heap() const
{
return static_cast<void const*>(p_) != static_cast<void const*>(&d_);
}
};
template <class T, class... Args>
inline STVar
make_stvar(Args&&... args)
{
STVar st;
st.construct<T>(std::forward<Args>(args)...);
return st;
}
inline bool
operator==(STVar const& lhs, STVar const& rhs)
{
return lhs.get().isEquivalent(rhs.get());
}
inline bool
operator!=(STVar const& lhs, STVar const& rhs)
{
return !(lhs == rhs);
}
} // namespace detail
} // namespace ripple
#endif

View File

@@ -0,0 +1,192 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2022 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_PROTOCOL_B58_UTILS_H_INCLUDED
#define RIPPLE_PROTOCOL_B58_UTILS_H_INCLUDED
#include <ripple/basics/contract.h>
#include <ripple/protocol/impl/token_errors.h>
#include <boost/outcome.hpp>
#include <boost/outcome/result.hpp>
#include <cassert>
#include <cinttypes>
#include <span>
#include <system_error>
#include <tuple>
namespace ripple {
template <class T>
using Result = boost::outcome_v2::result<T, std::error_code>;
#ifndef _MSC_VER
namespace b58_fast {
namespace detail {
// This optimizes to what hand written asm would do (single divide)
[[nodiscard]] inline std::tuple<std::uint64_t, std::uint64_t>
div_rem(std::uint64_t a, std::uint64_t b)
{
return {a / b, a % b};
}
// This optimizes to what hand written asm would do (single multiply)
[[nodiscard]] inline std::tuple<std::uint64_t, std::uint64_t>
carrying_mul(std::uint64_t a, std::uint64_t b, std::uint64_t carry)
{
unsigned __int128 const x = a;
unsigned __int128 const y = b;
unsigned __int128 const c = x * y + carry;
return {c & 0xffff'ffff'ffff'ffff, c >> 64};
}
[[nodiscard]] inline std::tuple<std::uint64_t, std::uint64_t>
carrying_add(std::uint64_t a, std::uint64_t b)
{
unsigned __int128 const x = a;
unsigned __int128 const y = b;
unsigned __int128 const c = x + y;
return {c & 0xffff'ffff'ffff'ffff, c >> 64};
}
// Add a u64 to a "big uint" value inplace.
// The bigint value is stored with the smallest coefficients first
// (i.e a[0] is the 2^0 coefficient, a[n] is the 2^(64*n) coefficient)
// panics if overflows (this is a specialized adder for b58 decoding.
// it should never overflow).
[[nodiscard]] inline TokenCodecErrc
inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
{
if (a.size() <= 1)
{
return TokenCodecErrc::inputTooSmall;
}
std::uint64_t carry;
std::tie(a[0], carry) = carrying_add(a[0], b);
for (auto& v : a.subspan(1))
{
if (!carry)
{
return TokenCodecErrc::success;
}
std::tie(v, carry) = carrying_add(v, 1);
}
if (carry)
{
return TokenCodecErrc::overflowAdd;
}
return TokenCodecErrc::success;
}
[[nodiscard]] inline TokenCodecErrc
inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
{
if (a.empty())
{
return TokenCodecErrc::inputTooSmall;
}
auto const last_index = a.size() - 1;
if (a[last_index] != 0)
{
return TokenCodecErrc::inputTooLarge;
}
std::uint64_t carry = 0;
for (auto& coeff : a.subspan(0, last_index))
{
std::tie(coeff, carry) = carrying_mul(coeff, b, carry);
}
a[last_index] = carry;
return TokenCodecErrc::success;
}
// divide a "big uint" value inplace and return the mod
// numerator is stored so smallest coefficients come first
[[nodiscard]] inline std::uint64_t
inplace_bigint_div_rem(std::span<uint64_t> numerator, std::uint64_t divisor)
{
if (numerator.size() == 0)
{
// should never happen, but if it does then it seems natural to define
// the a null set of numbers to be zero, so the remainder is also zero.
assert(0);
return 0;
}
auto to_u128 = [](std::uint64_t high,
std::uint64_t low) -> unsigned __int128 {
unsigned __int128 const high128 = high;
unsigned __int128 const low128 = low;
return ((high128 << 64) | low128);
};
auto div_rem_64 =
[](unsigned __int128 num,
std::uint64_t denom) -> std::tuple<std::uint64_t, std::uint64_t> {
unsigned __int128 const denom128 = denom;
unsigned __int128 const d = num / denom128;
unsigned __int128 const r = num - (denom128 * d);
assert(d >> 64 == 0);
assert(r >> 64 == 0);
return {static_cast<std::uint64_t>(d), static_cast<std::uint64_t>(r)};
};
std::uint64_t prev_rem = 0;
int const last_index = numerator.size() - 1;
std::tie(numerator[last_index], prev_rem) =
div_rem(numerator[last_index], divisor);
for (int i = last_index - 1; i >= 0; --i)
{
unsigned __int128 const cur_num = to_u128(prev_rem, numerator[i]);
std::tie(numerator[i], prev_rem) = div_rem_64(cur_num, divisor);
}
return prev_rem;
}
// convert from base 58^10 to base 58
// put largest coeffs first
// the `_be` suffix stands for "big endian"
[[nodiscard]] inline std::array<std::uint8_t, 10>
b58_10_to_b58_be(std::uint64_t input)
{
constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10;
assert(input < B_58_10);
constexpr std::size_t resultSize = 10;
std::array<std::uint8_t, resultSize> result{};
int i = 0;
while (input > 0)
{
std::uint64_t rem;
std::tie(input, rem) = div_rem(input, 58);
result[resultSize - 1 - i] = rem;
i += 1;
}
return result;
}
} // namespace detail
} // namespace b58_fast
#endif
} // namespace ripple
#endif // RIPPLE_PROTOCOL_B58_UTILS_H_INCLUDED

View File

@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_SECP256K1_H_INCLUDED
#define RIPPLE_PROTOCOL_SECP256K1_H_INCLUDED
#include <secp256k1.h>
namespace ripple {
template <class = void>
secp256k1_context const*
secp256k1Context()
{
struct holder
{
secp256k1_context* impl;
holder()
: impl(secp256k1_context_create(
SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN))
{
}
~holder()
{
secp256k1_context_destroy(impl);
}
};
static holder const h;
return h.impl;
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2022 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_PROTOCOL_TOKEN_ERRORS_H_INCLUDED
#define RIPPLE_PROTOCOL_TOKEN_ERRORS_H_INCLUDED
#include <system_error>
namespace ripple {
enum class TokenCodecErrc {
success = 0,
inputTooLarge,
inputTooSmall,
badB58Character,
outputTooSmall,
mismatchedTokenType,
mismatchedChecksum,
invalidEncodingChar,
overflowAdd,
unknown,
};
}
namespace std {
template <>
struct is_error_code_enum<ripple::TokenCodecErrc> : true_type
{
};
} // namespace std
namespace ripple {
namespace detail {
class TokenCodecErrcCategory : public std::error_category
{
public:
// Return a short descriptive name for the category
virtual const char*
name() const noexcept override final
{
return "TokenCodecError";
}
// Return what each enum means in text
virtual std::string
message(int c) const override final
{
switch (static_cast<TokenCodecErrc>(c))
{
case TokenCodecErrc::success:
return "conversion successful";
case TokenCodecErrc::inputTooLarge:
return "input too large";
case TokenCodecErrc::inputTooSmall:
return "input too small";
case TokenCodecErrc::badB58Character:
return "bad base 58 character";
case TokenCodecErrc::outputTooSmall:
return "output too small";
case TokenCodecErrc::mismatchedTokenType:
return "mismatched token type";
case TokenCodecErrc::mismatchedChecksum:
return "mismatched checksum";
case TokenCodecErrc::invalidEncodingChar:
return "invalid encoding char";
case TokenCodecErrc::unknown:
return "unknown";
default:
return "unknown";
}
}
};
} // namespace detail
inline const ripple::detail::TokenCodecErrcCategory&
TokenCodecErrcCategory()
{
static ripple::detail::TokenCodecErrcCategory c;
return c;
}
inline std::error_code
make_error_code(ripple::TokenCodecErrc e)
{
return {static_cast<int>(e), TokenCodecErrcCategory()};
}
} // namespace ripple
#endif // TOKEN_ERRORS_H_

View File

@@ -0,0 +1,242 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_DIGEST_H_INCLUDED
#define RIPPLE_PROTOCOL_DIGEST_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/crypto/secure_erase.h>
#include <boost/endian/conversion.hpp>
#include <algorithm>
#include <array>
namespace ripple {
/** Message digest functions used in the codebase
@note These are modeled to meet the requirements of `Hasher` in the
`hash_append` interface, discussed in proposal:
N3980 "Types Don't Know #"
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3980.html
*/
//------------------------------------------------------------------------------
/** RIPEMD-160 digest
@note This uses the OpenSSL implementation
*/
struct openssl_ripemd160_hasher
{
public:
static constexpr auto const endian = boost::endian::order::native;
using result_type = std::array<std::uint8_t, 20>;
openssl_ripemd160_hasher();
void
operator()(void const* data, std::size_t size) noexcept;
explicit operator result_type() noexcept;
private:
char ctx_[96];
};
/** SHA-512 digest
@note This uses the OpenSSL implementation
*/
struct openssl_sha512_hasher
{
public:
static constexpr auto const endian = boost::endian::order::native;
using result_type = std::array<std::uint8_t, 64>;
openssl_sha512_hasher();
void
operator()(void const* data, std::size_t size) noexcept;
explicit operator result_type() noexcept;
private:
char ctx_[216];
};
/** SHA-256 digest
@note This uses the OpenSSL implementation
*/
struct openssl_sha256_hasher
{
public:
static constexpr auto const endian = boost::endian::order::native;
using result_type = std::array<std::uint8_t, 32>;
openssl_sha256_hasher();
void
operator()(void const* data, std::size_t size) noexcept;
explicit operator result_type() noexcept;
private:
char ctx_[112];
};
//------------------------------------------------------------------------------
using ripemd160_hasher = openssl_ripemd160_hasher;
using sha256_hasher = openssl_sha256_hasher;
using sha512_hasher = openssl_sha512_hasher;
//------------------------------------------------------------------------------
/** Returns the RIPEMD-160 digest of the SHA256 hash of the message.
This operation is used to compute the 160-bit identifier
representing a Ripple account, from a message. Typically the
message is the public key of the account - which is not
stored in the account root.
The same computation is used regardless of the cryptographic
scheme implied by the public key. For example, the public key
may be an ed25519 public key or a secp256k1 public key. Support
for new cryptographic systems may be added, using the same
formula for calculating the account identifier.
Meets the requirements of Hasher (in hash_append)
*/
struct ripesha_hasher
{
private:
sha256_hasher h_;
public:
static constexpr auto const endian = boost::endian::order::native;
using result_type = std::array<std::uint8_t, 20>;
void
operator()(void const* data, std::size_t size) noexcept
{
h_(data, size);
}
explicit operator result_type() noexcept
{
auto const d0 = sha256_hasher::result_type(h_);
ripemd160_hasher rh;
rh(d0.data(), d0.size());
return ripemd160_hasher::result_type(rh);
}
};
//------------------------------------------------------------------------------
namespace detail {
/** Returns the SHA512-Half digest of a message.
The SHA512-Half is the first 256 bits of the
SHA-512 digest of the message.
*/
template <bool Secure>
struct basic_sha512_half_hasher
{
private:
sha512_hasher h_;
public:
static constexpr auto const endian = boost::endian::order::big;
using result_type = uint256;
~basic_sha512_half_hasher()
{
erase(std::integral_constant<bool, Secure>{});
}
void
operator()(void const* data, std::size_t size) noexcept
{
h_(data, size);
}
explicit operator result_type() noexcept
{
auto const digest = sha512_hasher::result_type(h_);
return result_type::fromVoid(digest.data());
}
private:
inline void erase(std::false_type)
{
}
inline void erase(std::true_type)
{
secure_erase(&h_, sizeof(h_));
}
};
} // namespace detail
using sha512_half_hasher = detail::basic_sha512_half_hasher<false>;
// secure version
using sha512_half_hasher_s = detail::basic_sha512_half_hasher<true>;
//------------------------------------------------------------------------------
/** Returns the SHA512-Half of a series of objects. */
template <class... Args>
sha512_half_hasher::result_type
sha512Half(Args const&... args)
{
sha512_half_hasher h;
using beast::hash_append;
hash_append(h, args...);
return static_cast<typename sha512_half_hasher::result_type>(h);
}
/** Returns the SHA512-Half of a series of objects.
Postconditions:
Temporary memory storing copies of
input messages will be cleared.
*/
template <class... Args>
sha512_half_hasher_s::result_type
sha512Half_s(Args const&... args)
{
sha512_half_hasher_s h;
using beast::hash_append;
hash_append(h, args...);
return static_cast<typename sha512_half_hasher_s::result_type>(h);
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,159 @@
#ifndef PROTOCOL_GET_OR_THROW_H_
#define PROTOCOL_GET_OR_THROW_H_
#include <ripple/basics/Buffer.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/contract.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/SField.h>
#include <charconv>
#include <exception>
#include <optional>
#include <string>
namespace Json {
struct JsonMissingKeyError : std::exception
{
char const* const key;
mutable std::string msg;
JsonMissingKeyError(Json::StaticString const& k) : key{k.c_str()}
{
}
const char*
what() const noexcept override
{
if (msg.empty())
{
msg = std::string("Missing json key: ") + key;
}
return msg.c_str();
}
};
struct JsonTypeMismatchError : std::exception
{
char const* const key;
std::string const expectedType;
mutable std::string msg;
JsonTypeMismatchError(Json::StaticString const& k, std::string et)
: key{k.c_str()}, expectedType{std::move(et)}
{
}
const char*
what() const noexcept override
{
if (msg.empty())
{
msg = std::string("Type mismatch on json key: ") + key +
"; expected type: " + expectedType;
}
return msg.c_str();
}
};
template <class T>
T
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
static_assert(sizeof(T) == -1, "This function must be specialized");
}
template <>
inline std::string
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
Json::StaticString const& key = field.getJsonName();
if (!v.isMember(key))
Throw<JsonMissingKeyError>(key);
Json::Value const& inner = v[key];
if (!inner.isString())
Throw<JsonTypeMismatchError>(key, "string");
return inner.asString();
}
// Note, this allows integer numeric fields to act as bools
template <>
inline bool
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
Json::StaticString const& key = field.getJsonName();
if (!v.isMember(key))
Throw<JsonMissingKeyError>(key);
Json::Value const& inner = v[key];
if (inner.isBool())
return inner.asBool();
if (!inner.isIntegral())
Throw<JsonTypeMismatchError>(key, "bool");
return inner.asInt() != 0;
}
template <>
inline std::uint64_t
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
Json::StaticString const& key = field.getJsonName();
if (!v.isMember(key))
Throw<JsonMissingKeyError>(key);
Json::Value const& inner = v[key];
if (inner.isUInt())
return inner.asUInt();
if (inner.isInt())
{
auto const r = inner.asInt();
if (r < 0)
Throw<JsonTypeMismatchError>(key, "uint64");
return r;
}
if (inner.isString())
{
auto const s = inner.asString();
// parse as hex
std::uint64_t val;
auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val, 16);
if (ec != std::errc() || (p != s.data() + s.size()))
Throw<JsonTypeMismatchError>(key, "uint64");
return val;
}
Throw<JsonTypeMismatchError>(key, "uint64");
}
template <>
inline ripple::Buffer
getOrThrow(Json::Value const& v, ripple::SField const& field)
{
using namespace ripple;
std::string const hex = getOrThrow<std::string>(v, field);
if (auto const r = strUnHex(hex))
{
// TODO: mismatch between a buffer and a blob
return Buffer{r->data(), r->size()};
}
Throw<JsonTypeMismatchError>(field.getJsonName(), "Buffer");
}
// This function may be used by external projects (like the witness server).
template <class T>
std::optional<T>
getOptional(Json::Value const& v, ripple::SField const& field)
{
try
{
return getOrThrow<T>(v, field);
}
catch (...)
{
}
return {};
}
} // namespace Json
#endif // PROTOCOL_GET_OR_THROW_H_

879
include/xrpl/protocol/jss.h Normal file
View File

@@ -0,0 +1,879 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_JSONFIELDS_H_INCLUDED
#define RIPPLE_PROTOCOL_JSONFIELDS_H_INCLUDED
#include <ripple/json/json_value.h>
namespace ripple {
namespace jss {
// JSON static strings
#define JSS(x) constexpr ::Json::StaticString x(#x)
/* These "StaticString" field names are used instead of string literals to
optimize the performance of accessing properties of Json::Value objects.
Most strings have a trailing comment. Here is the legend:
in: Read by the given RPC handler from its `Json::Value` parameter.
out: Assigned by the given RPC handler in the `Json::Value` it returns.
field: A field of at least one type of transaction.
RPC: Common properties of RPC requests and responses.
error: Common properties of RPC error responses.
*/
JSS(AL_size); // out: GetCounts
JSS(AL_hit_rate); // out: GetCounts
JSS(Account); // in: TransactionSign; field.
JSS(AccountDelete); // transaction type.
JSS(AccountRoot); // ledger type.
JSS(AccountSet); // transaction type.
JSS(AMM); // ledger type
JSS(AMMBid); // transaction type
JSS(AMMID); // field
JSS(AMMCreate); // transaction type
JSS(AMMDeposit); // transaction type
JSS(AMMDelete); // transaction type
JSS(AMMVote); // transaction type
JSS(AMMWithdraw); // transaction type
JSS(Amendments); // ledger type.
JSS(Amount); // in: TransactionSign; field.
JSS(Authorize); // field
JSS(Amount2); // in/out: AMM IOU/XRP pool, deposit, withdraw amount
JSS(Asset); // in: AMM Asset1
JSS(Asset2); // in: AMM
JSS(AssetClass); // in: Oracle
JSS(AssetPrice); // in: Oracle
JSS(AuthAccount); // in: AMM Auction Slot
JSS(AuthAccounts); // in: AMM Auction Slot
JSS(BaseAsset); // in: Oracle
JSS(Blob);
JSS(Bridge); // ledger type.
JSS(Check); // ledger type.
JSS(CheckCancel); // transaction type.
JSS(CheckCash); // transaction type.
JSS(CheckCreate); // transaction type.
JSS(Clawback); // transaction type.
JSS(ClaimReward); // transaction type.
JSS(ClearFlag); // field.
JSS(CreateCode); // field.
JSS(DID); // ledger type.
JSS(DIDDelete); // transaction type.
JSS(DIDSet); // transaction type.
JSS(DeliverMax); // out: alias to Amount
JSS(DeliverMin); // in: TransactionSign
JSS(DepositPreauth); // transaction and ledger type.
JSS(Destination); // in: TransactionSign; field.
JSS(DirectoryNode); // ledger type.
JSS(EnableAmendment); // transaction type.
JSS(EPrice); // in: AMM Deposit option
JSS(EmitFailure); // transaction type. (cleanup emit)
JSS(Escrow); // ledger type.
JSS(EscrowCancel); // transaction type.
JSS(EscrowCreate); // transaction type.
JSS(EscrowFinish); // transaction type.
JSS(Fee); // in/out: TransactionSign; field.
JSS(FeeSettings); // ledger type.
JSS(FIELDS); // out: RPC server_definitions
JSS(Flags); // in/out: TransactionSign; field.
JSS(incomplete_shards); // out: OverlayImpl, PeerImp
JSS(GenesisMint); // tt
JSS(GenesisMints);
JSS(GovernanceMarks);
JSS(GovernanceFlags);
JSS(HookApiVersion); // field
JSS(HookCanEmit); // field
JSS(HookHash); // field
JSS(HookNamespace); // field
JSS(HookOn); // field
JSS(Hooks); // field
JSS(HookGrants); // field
JSS(HookParameters); // field
JSS(HookParameterName); // field
JSS(HookParameterValue); // field
JSS(HookParameter); // field
JSS(HookGrant); // field
JSS(isSerialized); // out: RPC server_definitions
// matches definitions.json format
JSS(isSigningField); // out: RPC server_definitions
// matches definitions.json format
JSS(isVLEncoded); // out: RPC server_definitions
// matches definitions.json format
JSS(Import);
JSS(ImportVLSequence);
JSS(Invalid); //
JSS(Invoke); // transaction type
JSS(InvoiceID); // field
JSS(LastLedgerSequence); // in: TransactionSign; field
JSS(LastUpdateTime); // field.
JSS(LedgerHashes); // ledger type.
JSS(LimitAmount); // field.
JSS(BidMax); // in: AMM Bid
JSS(BidMin); // in: AMM Bid
JSS(NetworkID); // field.
JSS(NFTokenBurn); // transaction type.
JSS(NFTokenMint); // transaction type.
JSS(NFTokenOffer); // ledger type.
JSS(NFTokenAcceptOffer); // transaction type.
JSS(NFTokenCancelOffer); // transaction type.
JSS(NFTokenCreateOffer); // transaction type.
JSS(NFTokenPage); // ledger type.
JSS(LPTokenOut); // in: AMM Liquidity Provider deposit tokens
JSS(LPTokenIn); // in: AMM Liquidity Provider withdraw tokens
JSS(LPToken); // out: AMM Liquidity Provider tokens info
JSS(Offer); // ledger type.
JSS(OfferCancel); // transaction type.
JSS(OfferCreate); // transaction type.
JSS(OfferSequence); // field.
JSS(Oracle); // ledger type.
JSS(OracleDelete); // transaction type.
JSS(OracleDocumentID); // field
JSS(OracleSet); // transaction type.
JSS(Owner); // field
JSS(Paths); // in/out: TransactionSign
JSS(PayChannel); // ledger type.
JSS(Payment); // transaction type.
JSS(PaymentChannelClaim); // transaction type.
JSS(PaymentChannelCreate); // transaction type.
JSS(PaymentChannelFund); // transaction type.
JSS(PriceDataSeries); // field.
JSS(PriceData); // field.
JSS(Provider); // field.
JSS(QuoteAsset); // in: Oracle.
JSS(Remit); // transaction type.
JSS(RippleState); // ledger type.
JSS(SLE_hit_rate); // out: GetCounts.
JSS(SetFee); // transaction type.
JSS(SetRemarks); // transaction type
JSS(UNLModify); // transaction type.
JSS(Scale); // field.
JSS(UNLReport); // transaction type.
JSS(SettleDelay); // in: TransactionSign
JSS(SendMax); // in: TransactionSign
JSS(Sequence); // in/out: TransactionSign; field.
JSS(SetFlag); // field.
JSS(SetRegularKey); // transaction type.
JSS(SetHook); // transaction type.
JSS(Hook); // ledger type.
JSS(HookDefinition); // ledger type.
JSS(HookState); // ledger type.
JSS(HookStateData); // field.
JSS(HookStateKey); // field.
JSS(EmittedTxn); // ledger type.
JSS(SignerList); // ledger type.
JSS(SignerListSet); // transaction type.
JSS(SigningPubKey); // field.
JSS(TakerGets); // field.
JSS(TakerPays); // field.
JSS(Ticket); // ledger type.
JSS(TicketCreate); // transaction type.
JSS(TxnSignature); // field.
JSS(TradingFee); // in/out: AMM trading fee
JSS(TransactionType); // in: TransactionSign.
JSS(TransferRate); // in: TransferRate.
JSS(TrustSet); // transaction type.
JSS(URI); // field.
JSS(URIToken); // out: LedgerEntry
JSS(URITokenMint); // tx type
JSS(URITokenBurn); // tx type
JSS(URITokenBuy); // tx type
JSS(URITokenCreateSellOffer); // tx type
JSS(URITokenCancelSellOffer); // tx type
JSS(VoteSlots); // out: AMM Vote
JSS(XChainAddAccountCreateAttestation); // transaction type.
JSS(XChainAddClaimAttestation); // transaction type.
JSS(XChainAccountCreateCommit); // transaction type.
JSS(XChainClaim); // transaction type.
JSS(XChainCommit); // transaction type.
JSS(XChainCreateBridge); // transaction type.
JSS(XChainCreateClaimID); // transaction type.
JSS(XChainModifyBridge); // transaction type.
JSS(XChainOwnedClaimID); // ledger type.
JSS(XChainOwnedCreateAccountClaimID); // ledger type.
JSS(aborted); // out: InboundLedger
JSS(accepted); // out: LedgerToJson, OwnerInfo, SubmitTransaction
JSS(account); // in/out: many
JSS(accountState); // out: LedgerToJson
JSS(accountTreeHash); // out: ledger/Ledger.cpp
JSS(account_data); // out: AccountInfo
JSS(account_flags); // out: AccountInfo
JSS(account_hash); // out: LedgerToJson
JSS(account_id); // out: WalletPropose
JSS(account_namespace); // out: AccountNamespace
JSS(account_nfts); // out: AccountNFTs
JSS(account_objects); // out: AccountObjects
JSS(account_root); // in: LedgerEntry
JSS(account_sequence_next); // out: SubmitTransaction
JSS(account_sequence_available); // out: SubmitTransaction
JSS(account_history_tx_stream); // in: Subscribe, Unsubscribe
JSS(account_history_tx_index); // out: Account txn history subscribe
JSS(account_history_tx_first); // out: Account txn history subscribe
JSS(account_history_boundary); // out: Account txn history subscribe
JSS(accounts); // in: LedgerEntry, Subscribe,
// handlers/Ledger, Unsubscribe
JSS(accounts_proposed); // in: Subscribe, Unsubscribe
JSS(acroot);
JSS(action);
JSS(acquiring); // out: LedgerRequest
JSS(address); // out: PeerImp
JSS(affected); // out: AcceptedLedgerTx
JSS(age); // out: NetworkOPs, Peers
JSS(alternatives); // out: PathRequest, RipplePathFind
JSS(amendment_blocked); // out: NetworkOPs
JSS(amendments); // in: AccountObjects, out: NetworkOPs
JSS(amm); // out: amm_info
JSS(amm_account); // in: amm_info
JSS(amount); // out: AccountChannels, amm_info
JSS(amount2); // out: amm_info
JSS(api_version); // in: many, out: Version
JSS(api_version_low); // out: Version
JSS(applied); // out: SubmitTransaction
JSS(asks); // out: Subscribe
JSS(asset); // in: amm_info
JSS(asset2); // in: amm_info
JSS(assets); // out: GatewayBalances
JSS(asset_frozen); // out: amm_info
JSS(asset2_frozen); // out: amm_info
JSS(attestations); //
JSS(attestation_reward_account); //
JSS(auction_slot); // out: amm_info
JSS(authorized); // out: AccountLines
JSS(auth_accounts); // out: amm_info
JSS(auth_change); // out: AccountInfo
JSS(auth_change_queued); // out: AccountInfo
JSS(available); // out: ValidatorList
JSS(avg_bps_recv); // out: Peers
JSS(avg_bps_sent); // out: Peers
JSS(balance); // out: AccountLines
JSS(balances); // out: GatewayBalances
JSS(base); // out: LogLevel
JSS(base_asset); // in: get_aggregate_price
JSS(base_fee); // out: NetworkOPs
JSS(base_fee_no_hooks);
JSS(base_fee_xrp); // out: NetworkOPs
JSS(base_fee_native); // out: NetworkOPs
JSS(bids); // out: Subscribe
JSS(binary); // in: AccountTX, LedgerEntry,
// AccountTxOld, Tx LedgerData
JSS(blob); // out: ValidatorList
JSS(blobs_v2); // out: ValidatorList
// in: UNL
JSS(books); // in: Subscribe, Unsubscribe
JSS(both); // in: Subscribe, Unsubscribe
JSS(both_sides); // in: Subscribe, Unsubscribe
JSS(broadcast); // out: SubmitTransaction
JSS(bridge); // in: LedgerEntry
JSS(bridge_account); // in: LedgerEntry
JSS(build_path); // in: TransactionSign
JSS(build_version); // out: NetworkOPs
JSS(bytes_written);
JSS(cancel_after); // out: AccountChannels
JSS(can_delete); // out: CanDelete
JSS(changes); // out: BookChanges
JSS(channel_id); // out: AccountChannels
JSS(channels); // out: AccountChannels
JSS(check); // in: AccountObjects
JSS(check_nodes); // in: LedgerCleaner
JSS(clear); // in/out: FetchInfo
JSS(close); // out: BookChanges
JSS(close_flags); // out: LedgerToJson
JSS(close_time); // in: Application, out: NetworkOPs,
// RCLCxPeerPos, LedgerToJson
JSS(close_time_iso); // out: Tx, NetworkOPs, TransactionEntry
// AccountTx, LedgerToJson
JSS(close_time_estimated); // in: Application, out: LedgerToJson
JSS(close_time_human); // out: LedgerToJson
JSS(close_time_offset); // out: NetworkOPs
JSS(close_time_resolution); // in: Application; out: LedgerToJson
JSS(closed); // out: NetworkOPs, LedgerToJson,
// handlers/Ledger
JSS(closed_ledger); // out: NetworkOPs
JSS(cluster); // out: PeerImp
JSS(code); // out: errors
JSS(command); // in: RPCHandler
JSS(complete); // out: NetworkOPs, InboundLedger
JSS(complete_ledgers); // out: NetworkOPs, PeerImp
JSS(complete_ledgers_pinned);
JSS(complete_shards); // out: OverlayImpl, PeerImp
JSS(compression_level);
JSS(consensus); // out: NetworkOPs, LedgerConsensus
JSS(converge_time); // out: NetworkOPs
JSS(converge_time_s); // out: NetworkOPs
JSS(cookie); // out: NetworkOPs
JSS(count); // in: AccountTx*, ValidatorList
JSS(counters); // in/out: retrieve counters
JSS(coins);
JSS(children);
JSS(ctid); // in/out: Tx RPC
JSS(cres);
JSS(currency_a); // out: BookChanges
JSS(currency_b); // out: BookChanges
JSS(currentShard); // out: NodeToShardStatus
JSS(currentShardIndex); // out: NodeToShardStatus
JSS(currency); // in: paths/PathRequest, STAmount
// out: STPathSet, STAmount,
// AccountLines
JSS(current); // out: OwnerInfo
JSS(current_activities);
JSS(current_ledger_size); // out: TxQ
JSS(current_ledger);
JSS(current_queue_size); // out: TxQ
JSS(data); // out: LedgerData
JSS(date); // out: tx/Transaction, NetworkOPs
JSS(dbKBLedger); // out: getCounts
JSS(dbKBTotal); // out: getCounts
JSS(dbKBTransaction); // out: getCounts
JSS(debug_signing); // in: TransactionSign
JSS(deletion_blockers_only); // in: AccountObjects
JSS(delivered_amount); // out: insertDeliveredAmount
JSS(deposit_authorized); // out: deposit_authorized
JSS(deposit_preauth); // in: AccountObjects, LedgerData
JSS(deprecated); // out
JSS(descending); // in: AccountTx*
JSS(description); // in/out: Reservations
JSS(destination); // in: nft_buy_offers, nft_sell_offers
JSS(destination_account); // in: PathRequest, RipplePathFind, account_lines
// out: AccountChannels
JSS(destination_amount); // in: PathRequest, RipplePathFind
JSS(destination_currencies); // in: PathRequest, RipplePathFind
JSS(destination_tag); // in: PathRequest
// out: AccountChannels
JSS(details); // out: Manifest, server_info
JSS(did); // in: LedgerEntry
JSS(dir_entry); // out: DirectoryEntryIterator
JSS(dir_index); // out: DirectoryEntryIterator
JSS(dir_root); // out: DirectoryEntryIterator
JSS(directory); // in: LedgerEntry
JSS(discounted_fee); // out: amm_info
JSS(domain); // out: ValidatorInfo, Manifest
JSS(drops); // out: TxQ
JSS(duration_us); // out: NetworkOPs
JSS(effective); // out: ValidatorList
// in: UNL
JSS(elapsed_seconds);
JSS(enabled); // out: AmendmentTable
JSS(engine_result); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_code); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_message); // out: NetworkOPs, TransactionSign, Submit
JSS(entire_set); // out: get_aggregate_price
JSS(ephemeral_key); // out: ValidatorInfo
// in/out: Manifest
JSS(error); // out: error
JSS(errored);
JSS(error_code); // out: error
JSS(error_exception); // out: Submit
JSS(error_message); // out: error
JSS(escrow); // in: LedgerEntry
JSS(estimated_time_remaining);
JSS(emitted_txn); // in: LedgerEntry
JSS(expand); // in: handler/Ledger
JSS(expected_date); // out: any (warnings)
JSS(expected_date_UTC); // out: any (warnings)
JSS(expected_ledger_size); // out: TxQ
JSS(expiration); // out: AccountOffers, AccountChannels,
// ValidatorList, amm_info
JSS(fail_hard); // in: Sign, Submit
JSS(failed); // out: InboundLedger
JSS(failed_ledgers); // out: catalogue
JSS(feature); // in: Feature
JSS(features); // out: Feature
JSS(fee); // out: NetworkOPs, Peers
JSS(fee_base); // out: NetworkOPs
JSS(fee_div_max); // in: TransactionSign
JSS(fee_hooks_feeunits); // out: Fee rpc call
JSS(fee_level); // out: AccountInfo
JSS(fee_mult_max); // in: TransactionSign
JSS(fee_ref); // out: NetworkOPs, DEPRECATED
JSS(fetch_pack); // out: NetworkOPs
JSS(first); // out: rpc/Version
JSS(firstSequence); // out: NodeToShardStatus
JSS(firstShardIndex); // out: NodeToShardStatus
JSS(finished);
JSS(fix_txns); // in: LedgerCleaner
JSS(file);
JSS(file_size);
JSS(file_size_estimated_human);
JSS(file_size_human);
JSS(flags); // out: AccountOffers,
// NetworkOPs
JSS(force); // in: catalogue
JSS(forward); // in: AccountTx
JSS(freeze); // out: AccountLines
JSS(freeze_peer); // out: AccountLines
JSS(frozen_balances); // out: GatewayBalances
JSS(full); // in: LedgerClearer, handlers/Ledger
JSS(full_reply); // out: PathFind
JSS(fullbelow_size); // out: GetCounts
JSS(good); // out: RPCVersion
JSS(hash); // out: NetworkOPs, InboundLedger,
JSS(hash_mismatches); // out: catalogue
// LedgerToJson, STTx; field
JSS(hashes); // in: AccountObjects
JSS(have_header); // out: InboundLedger
JSS(have_state); // out: InboundLedger
JSS(have_transactions); // out: InboundLedger
JSS(high); // out: BookChanges
JSS(highest_sequence); // out: AccountInfo
JSS(highest_ticket); // out: AccountInfo
JSS(historical_perminute); // historical_perminute.
JSS(hook); // in: LedgerEntry
JSS(hook_definition); // in: LedgerEntry
JSS(hook_state); // in: LedgerEntry
JSS(hostid); // out: NetworkOPs
JSS(hotwallet); // in: GatewayBalances
JSS(id); // websocket.
JSS(ident); // in: AccountCurrencies, AccountInfo,
// OwnerInfo
JSS(ignore_default); // in: AccountLines
JSS(ignore_hash);
JSS(import_vlseq); // in: LedgerEntry
JSS(imported); // out: catalogue
JSS(inLedger); // out: tx/Transaction
JSS(in_queue);
JSS(inbound); // out: PeerImp
JSS(index); // in: LedgerEntry, DownloadShard
// out: STLedgerEntry,
// LedgerEntry, TxHistory, LedgerData
JSS(info); // out: ServerInfo, ConsensusInfo, FetchInfo
JSS(initial_sync_duration_us);
JSS(internal_command); // in: Internal
JSS(invalid_API_version); // out: Many, when a request has an invalid
// version
JSS(io_latency_ms); // out: NetworkOPs
JSS(ip); // in: Connect, out: OverlayImpl
JSS(is_burned); // out: nft_info (clio)
JSS(issuer); // in: RipplePathFind, Subscribe,
// Unsubscribe, BookOffers
// out: STPathSet, STAmount
JSS(job);
JSS(job_queue);
JSS(job_type);
JSS(job_status);
JSS(jobs);
JSS(jsonrpc); // json version
JSS(jq_trans_overflow); // JobQueue transaction limit overflow.
JSS(kept); // out: SubmitTransaction
JSS(key); // out
JSS(key_type); // in/out: WalletPropose, TransactionSign
JSS(latency); // out: PeerImp
JSS(last); // out: RPCVersion
JSS(lastSequence); // out: NodeToShardStatus
JSS(lastShardIndex); // out: NodeToShardStatus
JSS(last_close); // out: NetworkOPs
JSS(last_refresh_time); // out: ValidatorSite
JSS(last_refresh_status); // out: ValidatorSite
JSS(last_refresh_message); // out: ValidatorSite
JSS(ledger); // in: NetworkOPs, LedgerCleaner,
// RPCHelpers
// out: NetworkOPs, PeerImp
JSS(ledger_count);
JSS(ledgers_loaded);
JSS(ledgers_written);
JSS(ledger_current_index); // out: NetworkOPs, RPCHelpers,
// LedgerCurrent, LedgerAccept,
// AccountLines
JSS(ledger_data); // out: LedgerHeader
JSS(ledger_hash); // in: RPCHelpers, LedgerRequest,
// RipplePathFind, TransactionEntry,
// handlers/Ledger
// out: NetworkOPs, RPCHelpers,
// LedgerClosed, LedgerData,
// AccountLines
JSS(ledger_hit_rate); // out: GetCounts
JSS(ledger_index); // in/out: many
JSS(ledger_index_max); // in, out: AccountTx*
JSS(ledger_index_min); // in, out: AccountTx*
JSS(ledger_max); // in, out: AccountTx*
JSS(ledger_min); // in, out: AccountTx*
JSS(ledger_time); // out: NetworkOPs
JSS(LEDGER_ENTRY_TYPES); // out: RPC server_definitions
JSS(levels); // LogLevels
JSS(level);
JSS(limit); // in/out: AccountTx*, AccountOffers,
// AccountLines, AccountObjects
// in: LedgerData, BookOffers
JSS(limit_peer); // out: AccountLines
JSS(lines); // out: AccountLines
JSS(list); // out: ValidatorList
JSS(load); // out: NetworkOPs, PeerImp
JSS(load_base); // out: NetworkOPs
JSS(load_factor); // out: NetworkOPs
JSS(load_factor_cluster); // out: NetworkOPs
JSS(load_factor_fee_escalation); // out: NetworkOPs
JSS(load_factor_fee_queue); // out: NetworkOPs
JSS(load_factor_fee_reference); // out: NetworkOPs
JSS(load_factor_local); // out: NetworkOPs
JSS(load_factor_net); // out: NetworkOPs
JSS(load_factor_server); // out: NetworkOPs
JSS(load_fee); // out: LoadFeeTrackImp, NetworkOPs
JSS(local); // out: resource/Logic.h
JSS(local_txs); // out: GetCounts
JSS(local_static_keys); // out: ValidatorList
JSS(locked_balance); // out: AccountLines
JSS(low); // out: BookChanges
JSS(lock_count); // out: AccountLines
JSS(lowest_sequence); // out: AccountInfo
JSS(lowest_ticket); // out: AccountInfo
JSS(lp_token); // out: amm_info
JSS(majority); // out: RPC feature
JSS(manifest); // out: ValidatorInfo, Manifest
JSS(marker); // in/out: AccountTx, AccountOffers,
// AccountLines, AccountObjects,
// LedgerData
// in: BookOffers
JSS(master_key); // out: WalletPropose, NetworkOPs,
// ValidatorInfo
// in/out: Manifest
JSS(master_seed); // out: WalletPropose
JSS(master_seed_hex); // out: WalletPropose
JSS(master_signature); // out: pubManifest
JSS(max_ledger); // in/out: LedgerCleaner
JSS(max_queue_size); // out: TxQ
JSS(max_spend_drops); // out: AccountInfo
JSS(max_spend_drops_total); // out: AccountInfo
JSS(mean); // out: get_aggregate_price
JSS(median); // out: get_aggregate_price
JSS(median_fee); // out: TxQ
JSS(median_level); // out: TxQ
JSS(message); // error.
JSS(meta); // out: NetworkOPs, AccountTx*, Tx
JSS(meta_blob); // out: NetworkOPs, AccountTx*, Tx
JSS(metaData);
JSS(metadata); // out: TransactionEntry
JSS(method); // RPC
JSS(methods);
JSS(metrics); // out: Peers
JSS(Memo); // Field
JSS(Memos); // Field
JSS(MemoFormat); // Field
JSS(MemoData); // Field
JSS(MemoType); // Field
JSS(min_count); // in: GetCounts
JSS(min_ledger); // in: LedgerCleaner
JSS(minimum_fee); // out: TxQ
JSS(minimum_level); // out: TxQ
JSS(missingCommand); // error
JSS(name); // out: AmendmentTableImpl, PeerImp
JSS(namespace_entries); // out: AccountNamespace
JSS(namespace_id); // in/out: AccountNamespace
JSS(native_currency_code); // out: RPC
JSS(needed_state_hashes); // out: InboundLedger
JSS(needed_transaction_hashes); // out: InboundLedger
JSS(network_id); // out: NetworkOPs
JSS(network_ledger); // out: NetworkOPs
JSS(next_refresh_time); // out: ValidatorSite
JSS(nft_id); // in: nft_sell_offers, nft_buy_offers
JSS(nft_offer); // in: LedgerEntry
JSS(nft_offer_index); // out nft_buy_offers, nft_sell_offers
JSS(nft_page); // in: LedgerEntry
JSS(nft_serial); // out: account_nfts
JSS(nft_taxon); // out: nft_info (clio)
JSS(nftoken_id); // out: insertNFTokenID
JSS(nftoken_ids); // out: insertNFTokenID
JSS(no_ripple); // out: AccountLines
JSS(no_ripple_peer); // out: AccountLines
JSS(node); // out: LedgerEntry
JSS(node_binary); // out: LedgerEntry
JSS(node_read_bytes); // out: GetCounts
JSS(node_read_errors); // out: GetCounts
JSS(node_read_retries); // out: GetCounts
JSS(node_reads_hit); // out: GetCounts
JSS(node_reads_total); // out: GetCounts
JSS(node_reads_duration_us); // out: GetCounts
JSS(node_size); // out: server_info
JSS(nodestore); // out: GetCounts
JSS(node_writes); // out: GetCounts
JSS(node_written_bytes); // out: GetCounts
JSS(node_writes_duration_us); // out: GetCounts
JSS(node_write_retries); // out: GetCounts
JSS(node_writes_delayed); // out::GetCounts
JSS(nth); // out: RPC server_definitions
JSS(nunl); // in: AccountObjects
JSS(obligations); // out: GatewayBalances
JSS(offer); // in: LedgerEntry
JSS(offers); // out: NetworkOPs, AccountOffers, Subscribe
JSS(offer_id); // out: insertNFTokenOfferID
JSS(offline); // in: TransactionSign
JSS(offset); // in/out: AccountTxOld
JSS(open); // out: handlers/Ledger
JSS(open_ledger_cost); // out: SubmitTransaction
JSS(open_ledger_fee); // out: TxQ
JSS(open_ledger_level); // out: TxQ
JSS(oracle); // in: LedgerEntry
JSS(oracles); // in: get_aggregate_price
JSS(oracle_document_id); // in: get_aggregate_price
JSS(owner); // in: LedgerEntry, out: NetworkOPs
JSS(owner_funds); // in/out: Ledger, NetworkOPs, AcceptedLedgerTx
JSS(page_index);
JSS(params); // RPC
JSS(parent_close_time); // out: LedgerToJson
JSS(parent_hash); // out: LedgerToJson
JSS(partition); // in: LogLevel
JSS(passphrase); // in: WalletPropose
JSS(password); // in: Subscribe
JSS(paths); // in: RipplePathFind
JSS(paths_canonical); // out: RipplePathFind
JSS(paths_computed); // out: PathRequest, RipplePathFind
JSS(output_file); // in: CatalogueCreate
JSS(input_file); // in: CatalogueLoad
JSS(payment_channel); // in: LedgerEntry
JSS(pclose);
JSS(peer); // in: AccountLines
JSS(peer_authorized); // out: AccountLines
JSS(peer_id); // out: RCLCxPeerPos
JSS(peers); // out: InboundLedger, handlers/Peers, Overlay
JSS(peer_disconnects); // Severed peer connection counter.
JSS(peer_disconnects_resources); // Severed peer connections because of
// excess resource consumption.
JSS(percent_complete);
JSS(phash);
JSS(port); // in: Connect, out: NetworkOPs
JSS(ports); // out: NetworkOPs
JSS(previous); // out: Reservations
JSS(previous_ledger); // out: LedgerPropose
JSS(price); // out: amm_info, AuctionSlot
JSS(proof); // in: BookOffers
JSS(propose_seq); // out: LedgerPropose
JSS(proposers); // out: NetworkOPs, LedgerConsensus
JSS(protocol); // out: NetworkOPs, PeerImp
JSS(proxied); // out: RPC ping
JSS(pubkey_node); // out: NetworkOPs
JSS(pubkey_publisher); // out: ValidatorList
JSS(pubkey_validator); // out: NetworkOPs, ValidatorList
JSS(public_key); // out: OverlayImpl, PeerImp, WalletPropose,
// ValidatorInfo
// in/out: Manifest
JSS(public_key_hex); // out: WalletPropose
JSS(published_ledger); // out: NetworkOPs
JSS(publisher_lists); // out: ValidatorList
JSS(quality); // out: NetworkOPs
JSS(quality_in); // out: AccountLines
JSS(quality_out); // out: AccountLines
JSS(queue); // in: AccountInfo
JSS(queue_data); // out: AccountInfo
JSS(queued); // out: SubmitTransaction
JSS(queued_duration_us);
JSS(quote_asset); // in: get_aggregate_price
JSS(random); // out: Random
JSS(raw_meta); // out: AcceptedLedgerTx
JSS(receive_currencies); // out: AccountCurrencies
JSS(reference_level); // out: TxQ
JSS(refresh_interval); // in: UNL
JSS(refresh_interval_min); // out: ValidatorSites
JSS(regular_seed); // in/out: LedgerEntry
JSS(remaining); // out: ValidatorList
JSS(remote); // out: Logic.h
JSS(request); // RPC
JSS(requested); // out: Manifest
JSS(reservations); // out: Reservations
JSS(reserve_base); // out: NetworkOPs
JSS(reserve_base_xrp); // out: NetworkOPs
JSS(reserve_base_native); // out: NetworkOPs
JSS(reserve_inc); // out: NetworkOPs
JSS(reserve_inc_xrp); // out: NetworkOPs
JSS(reserve_inc_native); // out: NetworkOPs
JSS(response); // websocket
JSS(result); // RPC
JSS(ripple_lines); // out: NetworkOPs
JSS(ripple_state); // in: LedgerEntr
JSS(ripplerpc); // ripple RPC version
JSS(role); // out: Ping.cpp
JSS(rpc);
JSS(rt_accounts); // in: Subscribe, Unsubscribe
JSS(running_duration_us);
JSS(search_depth); // in: RipplePathFind
JSS(searched_all); // out: Tx
JSS(secret); // in: TransactionSign,
// ValidationCreate, ValidationSeed,
// channel_authorize
JSS(seed); //
JSS(seed_hex); // in: WalletPropose, TransactionSign
JSS(send_currencies); // out: AccountCurrencies
JSS(send_max); // in: PathRequest, RipplePathFind
JSS(seq); // in: LedgerEntry;
// out: NetworkOPs, RPCSub, AccountOffers,
// ValidatorList, ValidatorInfo, Manifest
JSS(sequence); // in: UNL
JSS(sequence_count); // out: AccountInfo
JSS(server_domain); // out: NetworkOPs
JSS(server_state); // out: NetworkOPs
JSS(server_state_duration_us); // out: NetworkOPs
JSS(server_status); // out: NetworkOPs
JSS(server_version); // out: NetworkOPs
JSS(settle_delay); // out: AccountChannels
JSS(severity); // in: LogLevel
JSS(shards); // in/out: GetCounts, DownloadShard
JSS(signature); // out: NetworkOPs, ChannelAuthorize
JSS(signature_verified); // out: ChannelVerify
JSS(signing_key); // out: NetworkOPs
JSS(signing_keys); // out: ValidatorList
JSS(signing_time); // out: NetworkOPs
JSS(signer_list); // in: AccountObjects
JSS(signer_lists); // in/out: AccountInfo
JSS(size); // out: get_aggregate_price
JSS(snapshot); // in: Subscribe
JSS(source_account); // in: PathRequest, RipplePathFind
JSS(source_amount); // in: PathRequest, RipplePathFind
JSS(source_currencies); // in: PathRequest, RipplePathFind
JSS(source_tag); // out: AccountChannels
JSS(stand_alone); // out: NetworkOPs
JSS(standard_deviation); // out: get_aggregate_price
JSS(start); // in: TxHistory
JSS(start_time);
JSS(started);
JSS(state); // out: Logic.h, ServerState, LedgerData
JSS(state_accounting); // out: NetworkOPs
JSS(state_now); // in: Subscribe
JSS(status); // error
JSS(stop); // in: LedgerCleaner
JSS(stop_history_tx_only); // in: Unsubscribe, stop history tx stream
JSS(storedSeqs); // out: NodeToShardStatus
JSS(streams); // in: Subscribe, Unsubscribe
JSS(strict); // in: AccountCurrencies, AccountInfo
JSS(sub_index); // in: LedgerEntry
JSS(subcommand); // in: PathFind
JSS(success); // rpc
JSS(supported); // out: AmendmentTableImpl
JSS(sync_mode); // in: Submit
JSS(system_time_offset); // out: NetworkOPs
JSS(tag); // out: Peers
JSS(taker); // in: Subscribe, BookOffers
JSS(taker_gets); // in: Subscribe, Unsubscribe, BookOffers
JSS(taker_gets_funded); // out: NetworkOPs
JSS(taker_pays); // in: Subscribe, Unsubscribe, BookOffers
JSS(taker_pays_funded); // out: NetworkOPs
JSS(threshold); // in: Blacklist
JSS(ticket); // in: AccountObjects
JSS(ticket_count); // out: AccountInfo
JSS(ticket_seq); // in: LedgerEntry
JSS(time);
JSS(timeouts); // out: InboundLedger
JSS(time_threshold); // in/out: Oracle aggregate
JSS(time_interval); // out: AMM Auction Slot
JSS(track); // out: PeerImp
JSS(traffic); // out: Overlay
JSS(trim); // in: get_aggregate_price
JSS(trimmed_set); // out: get_aggregate_price
JSS(total); // out: counters
JSS(total_bytes_recv); // out: Peers
JSS(total_bytes_sent); // out: Peers
JSS(total_coins); // out: LedgerToJson
JSS(trading_fee); // out: amm_info
JSS(transTreeHash); // out: ledger/Ledger.cpp
JSS(transaction); // in: Tx
// out: NetworkOPs, AcceptedLedgerTx,
JSS(transaction_hash); // out: RCLCxPeerPos, LedgerToJson
JSS(transactions); // out: LedgerToJson,
// in: AccountTx*, Unsubscribe
JSS(transfer_rate); // out: nft_info (clio)
JSS(transitions); // out: NetworkOPs
JSS(treenode_cache_size); // out: GetCounts
JSS(treenode_track_size); // out: GetCounts
JSS(trusted); // out: UnlList
JSS(trusted_validator_keys); // out: ValidatorList
JSS(tx); // out: STTx, AccountTx*
JSS(txroot);
JSS(tx_blob); // in/out: Submit,
// in: TransactionSign, AccountTx*
JSS(tx_hash); // in: TransactionEntry
JSS(tx_json); // in/out: TransactionSign
// out: TransactionEntry
JSS(tx_signing_hash); // out: TransactionSign
JSS(tx_unsigned); // out: TransactionSign
JSS(txn_count); // out: NetworkOPs
JSS(txr_tx_cnt); // out: protocol message tx's count
JSS(txr_tx_sz); // out: protocol message tx's size
JSS(txr_have_txs_cnt); // out: protocol message have tx count
JSS(txr_have_txs_sz); // out: protocol message have tx size
JSS(txr_get_ledger_cnt); // out: protocol message get ledger count
JSS(txr_get_ledger_sz); // out: protocol message get ledger size
JSS(txr_ledger_data_cnt); // out: protocol message ledger data count
JSS(txr_ledger_data_sz); // out: protocol message ledger data size
JSS(txr_transactions_cnt); // out: protocol message get object count
JSS(txr_transactions_sz); // out: protocol message get object size
JSS(txr_selected_cnt); // out: selected peers count
JSS(txr_suppressed_cnt); // out: suppressed peers count
JSS(txr_not_enabled_cnt); // out: peers with tx reduce-relay disabled count
JSS(txr_missing_tx_freq); // out: missing tx frequency average
JSS(txs); // out: TxHistory
JSS(type); // in: AccountObjects
// out: NetworkOPs RPC server_definitions
// OverlayImpl, Logic
JSS(TRANSACTION_RESULTS); // out: RPC server_definitions
// matches definitions.json format
JSS(TRANSACTION_TYPES); // out: RPC server_definitions
// matches definitions.json format
JSS(TYPES); // out: RPC server_definitions
// matches definitions.json format
JSS(TRANSACTION_FLAGS); // out: RPC server_definitions
JSS(TRANSACTION_FLAGS_INDICES); // out: RPC server_definitions
JSS(type_hex); // out: STPathSet
JSS(unl); // out: UnlList
JSS(unlimited); // out: Connection.h
JSS(unl_report); // in: LedgerEntry
JSS(uptime); // out: GetCounts
JSS(uri); // out: ValidatorSites
JSS(uri_token); // in: LedgerEntry
JSS(url); // in/out: Subscribe, Unsubscribe
JSS(url_password); // in: Subscribe
JSS(url_username); // in: Subscribe
JSS(urlgravatar); //
JSS(username); // in: Subscribe
JSS(validated); // out: NetworkOPs, RPCHelpers, AccountTx*
// Tx
JSS(validator_list_expires); // out: NetworkOps, ValidatorList
JSS(validator_list); // out: NetworkOps, ValidatorList
JSS(validators);
JSS(validated_hash); // out: NetworkOPs
JSS(validated_ledger); // out: NetworkOPs
JSS(validated_ledger_index); // out: SubmitTransaction
JSS(validated_ledgers); // out: NetworkOPs
JSS(validation_key); // out: ValidationCreate, ValidationSeed
JSS(validation_private_key); // out: ValidationCreate
JSS(validation_public_key); // out: ValidationCreate, ValidationSeed
JSS(validation_quorum); // out: NetworkOPs
JSS(validation_seed); // out: ValidationCreate, ValidationSeed
JSS(validation);
JSS(validations); // out: AmendmentTableImpl
JSS(validator_sites); // out: ValidatorSites
JSS(value); // out: STAmount
JSS(version); // out: RPCVersion
JSS(vetoed); // out: AmendmentTableImpl
JSS(volume_a); // out: BookChanges
JSS(volume_b); // out: BookChanges
JSS(vote); // in: Feature
JSS(vote_slots); // out: amm_info
JSS(vote_weight); // out: amm_info
JSS(warning); // rpc:
JSS(warnings); // out: server_info, server_state
JSS(workers);
JSS(write_load); // out: GetCounts
JSS(xchain_owned_claim_id); // in: LedgerEntry, AccountObjects
JSS(xchain_owned_create_account_claim_id); // in: LedgerEntry
JSS(NegativeUNL); // out: ValidatorList; ledger type
#undef JSS
} // namespace jss
} // namespace ripple
#endif

View File

@@ -0,0 +1,36 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_MESSAGES_H_INCLUDED
#define RIPPLE_PROTOCOL_MESSAGES_H_INCLUDED
// Some versions of protobuf generate code that will produce errors during
// compilation. See https://github.com/google/protobuf/issues/549 for more
// details. We work around this by undefining this macro.
//
// TODO: Remove this after the protoc we use is upgraded to not generate
// code that conflicts with the TYPE_BOOL macro.
#ifdef TYPE_BOOL
#undef TYPE_BOOL
#endif
#include <ripple/proto/ripple.pb.h>
#endif

127
include/xrpl/protocol/nft.h Normal file
View File

@@ -0,0 +1,127 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_NFT_H_INCLUDED
#define RIPPLE_PROTOCOL_NFT_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/basics/tagged_integer.h>
#include <ripple/protocol/AccountID.h>
#include <boost/endian/conversion.hpp>
#include <cstdint>
#include <cstring>
namespace ripple {
namespace nft {
// Separate taxons from regular integers.
struct TaxonTag
{
};
using Taxon = tagged_integer<std::uint32_t, TaxonTag>;
inline Taxon
toTaxon(std::uint32_t i)
{
return static_cast<Taxon>(i);
}
inline std::uint32_t
toUInt32(Taxon t)
{
return static_cast<std::uint32_t>(t);
}
constexpr std::uint16_t const flagBurnable = 0x0001;
constexpr std::uint16_t const flagOnlyXRP = 0x0002;
constexpr std::uint16_t const flagCreateTrustLines = 0x0004;
constexpr std::uint16_t const flagTransferable = 0x0008;
inline std::uint16_t
getFlags(uint256 const& id)
{
std::uint16_t flags;
memcpy(&flags, id.begin(), 2);
return boost::endian::big_to_native(flags);
}
inline std::uint16_t
getTransferFee(uint256 const& id)
{
std::uint16_t fee;
memcpy(&fee, id.begin() + 2, 2);
return boost::endian::big_to_native(fee);
}
inline std::uint32_t
getSerial(uint256 const& id)
{
std::uint32_t seq;
memcpy(&seq, id.begin() + 28, 4);
return boost::endian::big_to_native(seq);
}
inline Taxon
cipheredTaxon(std::uint32_t tokenSeq, Taxon taxon)
{
// An issuer may issue several NFTs with the same taxon; to ensure that NFTs
// are spread across multiple pages we lightly mix the taxon up by using the
// sequence (which is not under the issuer's direct control) as the seed for
// a simple linear congruential generator.
//
// From the Hull-Dobell theorem we know that f(x)=(m*x+c) mod n will yield a
// permutation of [0, n) when n is a power of 2 if m is congruent to 1 mod 4
// and c is odd.
//
// Here we use m = 384160001 and c = 2459. The modulo is implicit because we
// use 2^32 for n and the arithmetic gives it to us for "free".
//
// Note that the scramble value we calculate is not cryptographically secure
// but that's fine since all we're looking for is some dispersion.
//
// **IMPORTANT** Changing these numbers would be a breaking change requiring
// an amendment along with a way to distinguish token IDs that
// were generated with the old code.
return taxon ^ toTaxon(((384160001 * tokenSeq) + 2459));
}
inline Taxon
getTaxon(uint256 const& id)
{
std::uint32_t taxon;
memcpy(&taxon, id.begin() + 24, 4);
taxon = boost::endian::big_to_native(taxon);
// The taxon cipher is just an XOR, so it is reversible by applying the
// XOR a second time.
return cipheredTaxon(getSerial(id), toTaxon(taxon));
}
inline AccountID
getIssuer(uint256 const& id)
{
return AccountID::fromVoid(id.data() + 4);
}
} // namespace nft
} // namespace ripple
#endif

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2022 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_PROTOCOL_NFT_PAGE_MASK_H_INCLUDED
#define RIPPLE_PROTOCOL_NFT_PAGE_MASK_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <string_view>
namespace ripple {
namespace nft {
// NFT directory pages order their contents based only on the low 96 bits of
// the NFToken value. This mask provides easy access to the necessary mask.
uint256 constexpr pageMask(std::string_view(
"0000000000000000000000000000000000000000ffffffffffffffffffffffff"));
} // namespace nft
} // namespace ripple
#endif

View File

@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2023 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_PROTOCOL_SERIALIZE_H_INCLUDED
#define RIPPLE_PROTOCOL_SERIALIZE_H_INCLUDED
#include <ripple/basics/strHex.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/Serializer.h>
namespace ripple {
/** Serialize an object to a blob. */
template <class Object>
Blob
serializeBlob(Object const& o)
{
Serializer s;
o.add(s);
return s.peekData();
}
/** Serialize an object to a hex string. */
inline std::string
serializeHex(STObject const& o)
{
return strHex(serializeBlob(o));
}
} // namespace ripple
#endif

View File

@@ -0,0 +1,39 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_ST_H_INCLUDED
#define RIPPLE_PROTOCOL_ST_H_INCLUDED
#include <ripple/protocol/SField.h>
#include <ripple/protocol/STAccount.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STArray.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STBitString.h>
#include <ripple/protocol/STBlob.h>
#include <ripple/protocol/STInteger.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/STPathSet.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/STVector256.h>
#endif

View File

@@ -0,0 +1,135 @@
//------------------------------------------------------------------------------
/*
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_PROTOCOL_TOKENS_H_INCLUDED
#define RIPPLE_PROTOCOL_TOKENS_H_INCLUDED
#include <ripple/basics/Expected.h>
#include <ripple/basics/contract.h>
#include <ripple/protocol/impl/token_errors.h>
#include <cstdint>
#include <optional>
#include <span>
#include <string>
#include <string_view>
namespace ripple {
template <class T>
using B58Result = Expected<T, std::error_code>;
enum class TokenType : std::uint8_t {
None = 1, // unused
NodePublic = 28,
NodePrivate = 32,
AccountID = 0,
AccountPublic = 35,
AccountSecret = 34,
FamilyGenerator = 41, // unused
FamilySeed = 33
};
template <class T>
[[nodiscard]] std::optional<T>
parseBase58(std::string const& s);
template <class T>
[[nodiscard]] std::optional<T>
parseBase58(TokenType type, std::string const& s);
/** Encode data in Base58Check format using XRPL alphabet
For details on the format see
https://xrpl.org/base58-encodings.html#base58-encodings
@param type The type of token to encode.
@param token Pointer to the data to encode.
@param size The size of the data to encode.
@return the encoded token.
*/
[[nodiscard]] std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size);
[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type);
namespace b58_ref {
// The reference version does not use gcc extensions (int128 in particular)
[[nodiscard]] std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size);
[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type);
namespace detail {
// Expose detail functions for unit tests only
std::string
encodeBase58(
void const* message,
std::size_t size,
void* temp,
std::size_t temp_size);
std::string
decodeBase58(std::string const& s);
} // namespace detail
} // namespace b58_ref
#ifndef _MSC_VER
namespace b58_fast {
// Use the fast version (10-15x faster) is using gcc extensions (int128 in
// particular)
[[nodiscard]] B58Result<std::span<std::uint8_t>>
encodeBase58Token(
TokenType token_type,
std::span<std::uint8_t const> input,
std::span<std::uint8_t> out);
[[nodiscard]] B58Result<std::span<std::uint8_t>>
decodeBase58Token(
TokenType type,
std::string_view s,
std::span<std::uint8_t> outBuf);
// This interface matches the old interface, but requires additional allocation
[[nodiscard]] std::string
encodeBase58Token(TokenType type, void const* token, std::size_t size);
// This interface matches the old interface, but requires additional allocation
[[nodiscard]] std::string
decodeBase58Token(std::string const& s, TokenType type);
namespace detail {
// Expose detail functions for unit tests only
B58Result<std::span<std::uint8_t>>
b256_to_b58_be(
std::span<std::uint8_t const> input,
std::span<std::uint8_t> out);
B58Result<std::span<std::uint8_t>>
b58_to_b256_be(std::string_view input, std::span<std::uint8_t> out);
} // namespace detail
} // namespace b58_fast
#endif // _MSC_VER
} // namespace ripple
#endif