mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 18:15:50 +00:00
Add safe_cast (RIPD-1702):
This change ensures that no overflow can occur when casting between enums and integral types.
This commit is contained in:
committed by
Nik Bougalis
parent
494724578a
commit
148bbf4e8f
@@ -1474,6 +1474,7 @@ install (
|
||||
src/ripple/basics/FileUtilities.h
|
||||
src/ripple/basics/LocalValue.h
|
||||
src/ripple/basics/Log.h
|
||||
src/ripple/basics/safe_cast.h
|
||||
src/ripple/basics/Slice.h
|
||||
src/ripple/basics/StringUtilities.h
|
||||
src/ripple/basics/ToString.h
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/basics/ByteUtilities.h>
|
||||
#include <ripple/basics/ResolverAsio.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/Sustain.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
@@ -1068,7 +1069,7 @@ public:
|
||||
*db << "PRAGMA page_count;", soci::into(pageCount);
|
||||
std::uint32_t freePages = maxPages - pageCount;
|
||||
std::uint64_t freeSpace =
|
||||
static_cast<std::uint64_t>(freePages) * pageSize;
|
||||
safe_cast<std::uint64_t>(freePages) * pageSize;
|
||||
JLOG(m_journal.info())
|
||||
<< "Transaction DB pathname: " << dbPath.string()
|
||||
<< "; file size: " << dbSize.value_or(-1) << " bytes"
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <ripple/basics/base64.h>
|
||||
#include <ripple/basics/mulDiv.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/UptimeClock.h>
|
||||
#include <ripple/core/ConfigSections.h>
|
||||
#include <ripple/crypto/csprng.h>
|
||||
@@ -1664,7 +1665,7 @@ void NetworkOPsImp::pubServer ()
|
||||
if(f.em)
|
||||
{
|
||||
auto const loadFactor =
|
||||
std::max(static_cast<std::uint64_t>(f.loadFactorServer),
|
||||
std::max(safe_cast<std::uint64_t>(f.loadFactorServer),
|
||||
mulDiv(f.em->openLedgerFeeLevel, f.loadBaseServer,
|
||||
f.em->referenceFeeLevel).second);
|
||||
|
||||
@@ -2121,7 +2122,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
|
||||
{
|
||||
if (when)
|
||||
info[jss::validator_list_expires] =
|
||||
static_cast<Json::UInt>(when->time_since_epoch().count());
|
||||
safe_cast<Json::UInt>(when->time_since_epoch().count());
|
||||
else
|
||||
info[jss::validator_list_expires] = 0;
|
||||
}
|
||||
@@ -2227,7 +2228,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
|
||||
auto const loadBaseFeeEscalation =
|
||||
escalationMetrics.referenceFeeLevel;
|
||||
|
||||
auto const loadFactor = std::max(static_cast<std::uint64_t>(loadFactorServer),
|
||||
auto const loadFactor = std::max(safe_cast<std::uint64_t>(loadFactorServer),
|
||||
mulDiv(loadFactorFeeEscalation, loadBaseServer, loadBaseFeeEscalation).second);
|
||||
|
||||
if (!human)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
@@ -149,8 +150,8 @@ scaleFeeLoad(std::uint64_t fee, LoadFeeTrack const& feeTrack,
|
||||
// The denominator of the fraction we're trying to compute.
|
||||
// fees.units and lftNormalFee are both 32 bit,
|
||||
// so the multiplication can't overflow.
|
||||
auto den = static_cast<std::uint64_t>(fees.units)
|
||||
* static_cast<std::uint64_t>(feeTrack.getLoadBase());
|
||||
auto den = safe_cast<std::uint64_t>(fees.units)
|
||||
* safe_cast<std::uint64_t>(feeTrack.getLoadBase());
|
||||
// Reduce fee * baseFee * feeFactor / (fees.units * lftNormalFee)
|
||||
// to lowest terms.
|
||||
lowestTerms(fee, den);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ripple/app/misc/HashRouter.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/conditions/Condition.h>
|
||||
#include <ripple/conditions/Fulfillment.h>
|
||||
#include <ripple/ledger/ApplyView.h>
|
||||
@@ -358,7 +359,7 @@ EscrowFinish::calculateBaseFee (
|
||||
if (auto const fb = tx[~sfFulfillment])
|
||||
{
|
||||
extraFee += view.fees().units *
|
||||
(32 + static_cast<std::uint64_t> (fb->size() / 16));
|
||||
(32 + safe_cast<std::uint64_t> (fb->size() / 16));
|
||||
}
|
||||
|
||||
return Transactor::calculateBaseFee (view, tx) + extraFee;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/Sustain.h>
|
||||
#include <ripple/beast/core/CurrentThreadName.h>
|
||||
#include <boost/format.hpp>
|
||||
@@ -41,8 +42,8 @@ namespace ripple {
|
||||
static auto const sleepBeforeWaiting = 10;
|
||||
static auto const sleepBetweenWaits = 1;
|
||||
|
||||
static pid_t pManager = static_cast<pid_t> (0);
|
||||
static pid_t pChild = static_cast<pid_t> (0);
|
||||
static pid_t pManager = safe_cast<pid_t> (0);
|
||||
static pid_t pChild = safe_cast<pid_t> (0);
|
||||
|
||||
static void pass_signal (int a)
|
||||
{
|
||||
|
||||
78
src/ripple/basics/safe_cast.h
Normal file
78
src/ripple/basics/safe_cast.h
Normal file
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_BASICS_SAFE_CAST_H_INCLUDED
|
||||
#define RIPPLE_BASICS_SAFE_CAST_H_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// safe_cast adds compile-time checks to a static_cast to ensure that
|
||||
// the destination can hold all values of the source. This is particularly
|
||||
// handy when the source or destination is an enumeration type.
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline
|
||||
constexpr
|
||||
std::enable_if_t
|
||||
<
|
||||
std::is_integral<Dest>::value && std::is_integral<Src>::value,
|
||||
Dest
|
||||
>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
static_assert(std::is_signed<Dest>::value || std::is_unsigned<Src>::value,
|
||||
"Cannot cast signed to unsigned");
|
||||
constexpr unsigned not_same = std::is_signed<Dest>::value !=
|
||||
std::is_signed<Src>::value;
|
||||
static_assert(sizeof(Dest) >= sizeof(Src) + not_same,
|
||||
"Destination is too small to hold all values of source");
|
||||
return static_cast<Dest>(s);
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline
|
||||
constexpr
|
||||
std::enable_if_t
|
||||
<
|
||||
std::is_enum<Dest>::value && std::is_integral<Src>::value,
|
||||
Dest
|
||||
>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
inline
|
||||
constexpr
|
||||
std::enable_if_t
|
||||
<
|
||||
std::is_integral<Dest>::value && std::is_enum<Src>::value,
|
||||
Dest
|
||||
>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/conditions/Condition.h>
|
||||
#include <ripple/conditions/Fulfillment.h>
|
||||
#include <ripple/conditions/impl/PreimageSha256.h>
|
||||
@@ -116,31 +117,32 @@ Fulfillment::deserialize(
|
||||
|
||||
std::unique_ptr<Fulfillment> f;
|
||||
|
||||
switch (static_cast<Type>(p.tag))
|
||||
using TagType = decltype(p.tag);
|
||||
switch (p.tag)
|
||||
{
|
||||
case Type::preimageSha256:
|
||||
case safe_cast<TagType>(Type::preimageSha256):
|
||||
f = PreimageSha256::deserialize(Slice(s.data(), p.length), ec);
|
||||
if (ec)
|
||||
return {};
|
||||
s += p.length;
|
||||
break;
|
||||
|
||||
case Type::prefixSha256:
|
||||
case safe_cast<TagType>(Type::prefixSha256):
|
||||
ec = error::unsupported_type;
|
||||
return {};
|
||||
break;
|
||||
|
||||
case Type::thresholdSha256:
|
||||
case safe_cast<TagType>(Type::thresholdSha256):
|
||||
ec = error::unsupported_type;
|
||||
return {};
|
||||
break;
|
||||
|
||||
case Type::rsaSha256:
|
||||
case safe_cast<TagType>(Type::rsaSha256):
|
||||
ec = error::unsupported_type;
|
||||
return {};
|
||||
break;
|
||||
|
||||
case Type::ed25519Sha256:
|
||||
case safe_cast<TagType>(Type::ed25519Sha256):
|
||||
ec = error::unsupported_type;
|
||||
return {};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/conditions/impl/error.h>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
@@ -41,7 +42,7 @@ public:
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
switch (static_cast<error>(ev))
|
||||
switch (safe_cast<error>(ev))
|
||||
{
|
||||
case error::unsupported_type:
|
||||
return "Specification: Requested type not supported.";
|
||||
@@ -136,7 +137,7 @@ std::error_code
|
||||
make_error_code(error ev)
|
||||
{
|
||||
return std::error_code {
|
||||
static_cast<std::underlying_type<error>::type>(ev),
|
||||
safe_cast<std::underlying_type<error>::type>(ev),
|
||||
detail::get_cryptoconditions_error_category()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/ledger/RawView.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <boost/optional.hpp>
|
||||
@@ -27,6 +28,7 @@
|
||||
namespace ripple {
|
||||
|
||||
enum ApplyFlags
|
||||
: std::uint32_t
|
||||
{
|
||||
tapNONE = 0x00,
|
||||
|
||||
@@ -48,14 +50,14 @@ ApplyFlags
|
||||
operator|(ApplyFlags const& lhs,
|
||||
ApplyFlags const& rhs)
|
||||
{
|
||||
return static_cast<ApplyFlags>(
|
||||
static_cast<std::underlying_type_t<ApplyFlags>>(lhs) |
|
||||
static_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
return safe_cast<ApplyFlags>(
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) |
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
}
|
||||
|
||||
static_assert((tapPREFER_QUEUE | tapRETRY) == static_cast<ApplyFlags>(0x60),
|
||||
static_assert((tapPREFER_QUEUE | tapRETRY) == safe_cast<ApplyFlags>(0x60u),
|
||||
"ApplyFlags operator |");
|
||||
static_assert((tapRETRY | tapPREFER_QUEUE) == static_cast<ApplyFlags>(0x60),
|
||||
static_assert((tapRETRY | tapPREFER_QUEUE) == safe_cast<ApplyFlags>(0x60u),
|
||||
"ApplyFlags operator |");
|
||||
|
||||
constexpr
|
||||
@@ -63,9 +65,9 @@ ApplyFlags
|
||||
operator&(ApplyFlags const& lhs,
|
||||
ApplyFlags const& rhs)
|
||||
{
|
||||
return static_cast<ApplyFlags>(
|
||||
static_cast<std::underlying_type_t<ApplyFlags>>(lhs) &
|
||||
static_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
return safe_cast<ApplyFlags>(
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) &
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
}
|
||||
|
||||
static_assert((tapPREFER_QUEUE & tapRETRY) == tapNONE,
|
||||
@@ -77,11 +79,11 @@ constexpr
|
||||
ApplyFlags
|
||||
operator~(ApplyFlags const& flags)
|
||||
{
|
||||
return static_cast<ApplyFlags>(
|
||||
~static_cast<std::underlying_type_t<ApplyFlags>>(flags));
|
||||
return safe_cast<ApplyFlags>(
|
||||
~safe_cast<std::underlying_type_t<ApplyFlags>>(flags));
|
||||
}
|
||||
|
||||
static_assert(~tapRETRY == static_cast<ApplyFlags>(~0x20),
|
||||
static_assert(~tapRETRY == safe_cast<ApplyFlags>(0xFFFFFFDFu),
|
||||
"ApplyFlags operator ~");
|
||||
|
||||
inline
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_LEDGER_CASHDIFF_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_CASHDIFF_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <memory> // std::unique_ptr
|
||||
|
||||
@@ -44,13 +45,13 @@ inline CashFilter operator| (CashFilter lhs, CashFilter rhs)
|
||||
{
|
||||
using ul_t = std::underlying_type<CashFilter>::type;
|
||||
return static_cast<CashFilter>(
|
||||
static_cast<ul_t>(lhs) | static_cast<ul_t>(rhs));
|
||||
safe_cast<ul_t>(lhs) | safe_cast<ul_t>(rhs));
|
||||
}
|
||||
inline CashFilter operator& (CashFilter lhs, CashFilter rhs)
|
||||
{
|
||||
using ul_t = std::underlying_type<CashFilter>::type;
|
||||
return static_cast<CashFilter>(
|
||||
static_cast<ul_t>(lhs) & static_cast<ul_t>(rhs));
|
||||
safe_cast<ul_t>(lhs) & safe_cast<ul_t>(rhs));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace ripple {
|
||||
|
||||
/** The types of node objects. */
|
||||
enum NodeObjectType
|
||||
: std::uint32_t
|
||||
{
|
||||
hotUNKNOWN = 0,
|
||||
hotLEDGER = 1,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/nodestore/impl/DecodedBlob.h>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -48,7 +49,7 @@ DecodedBlob::DecodedBlob (void const* key, void const* value, int valueBytes)
|
||||
if (valueBytes > 8)
|
||||
{
|
||||
unsigned char const* byte = static_cast <unsigned char const*> (value);
|
||||
m_objectType = static_cast <NodeObjectType> (byte [8]);
|
||||
m_objectType = safe_cast <NodeObjectType> (byte [8]);
|
||||
}
|
||||
|
||||
if (valueBytes > 9)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/overlay/Message.h>
|
||||
#include <ripple/overlay/impl/TrafficCount.h>
|
||||
#include <cstdint>
|
||||
@@ -38,7 +39,7 @@ Message::Message (::google::protobuf::Message const& message, int type)
|
||||
message.SerializeToArray (&mBuffer [Message::kHeaderBytes], messageBytes);
|
||||
}
|
||||
|
||||
mCategory = static_cast<int>(TrafficCount::categorize
|
||||
mCategory = safe_cast<int>(TrafficCount::categorize
|
||||
(message, type, false));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <ripple/app/misc/ValidatorList.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/basics/random.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/UptimeClock.h>
|
||||
#include <ripple/beast/core/LexicalCast.h>
|
||||
#include <ripple/beast/core/SemanticVersion.h>
|
||||
@@ -192,7 +193,7 @@ PeerImp::send (Message::pointer const& m)
|
||||
return;
|
||||
|
||||
overlay_.reportTraffic (
|
||||
static_cast<TrafficCount::category>(m->getCategory()),
|
||||
safe_cast<TrafficCount::category>(m->getCategory()),
|
||||
false, static_cast<int>(m->getBuffer().size()));
|
||||
|
||||
auto sendq_size = send_queue_.size();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/basics/base64.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/beast/rfc2616.h>
|
||||
#include <ripple/beast/core/LexicalCast.h>
|
||||
#include <ripple/protocol/digest.h>
|
||||
@@ -226,11 +227,11 @@ parseHello (bool request, boost::beast::http::fields const& h, beast::Journal jo
|
||||
if (versions.empty())
|
||||
return boost::none;
|
||||
hello.set_protoversion(
|
||||
(static_cast<std::uint32_t>(versions.back().first) << 16) |
|
||||
(static_cast<std::uint32_t>(versions.back().second)));
|
||||
(safe_cast<std::uint32_t>(versions.back().first) << 16) |
|
||||
(safe_cast<std::uint32_t>(versions.back().second)));
|
||||
hello.set_protoversionmin(
|
||||
(static_cast<std::uint32_t>(versions.front().first) << 16) |
|
||||
(static_cast<std::uint32_t>(versions.front().second)));
|
||||
(safe_cast<std::uint32_t>(versions.front().first) << 16) |
|
||||
(safe_cast<std::uint32_t>(versions.front().second)));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -362,7 +363,7 @@ verifyHello (protocol::TMHello const& h,
|
||||
|
||||
JLOG(journal.trace()) <<
|
||||
"Connect: time offset " <<
|
||||
static_cast<std::int64_t>(ourTime) - h.nettime();
|
||||
safe_cast<std::int64_t>(ourTime) - h.nettime();
|
||||
}
|
||||
|
||||
if (h.protoversionmin () > to_packed (BuildInfo::getCurrentProtocol()))
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_OVERLAY_TRAFFIC_H_INCLUDED
|
||||
#define RIPPLE_OVERLAY_TRAFFIC_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/messages.h>
|
||||
|
||||
#include <atomic>
|
||||
@@ -99,7 +100,7 @@ public:
|
||||
{
|
||||
for (category i = category::CT_base;
|
||||
i <= category::CT_unknown;
|
||||
i = static_cast<category>(static_cast<int>(i) + 1))
|
||||
i = safe_cast<category>(safe_cast<std::underlying_type_t<category>>(i) + 1))
|
||||
{
|
||||
counts_[i];
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#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 <utility>
|
||||
@@ -86,7 +87,7 @@ inline
|
||||
int
|
||||
field_code(SerializedTypeID id, int index)
|
||||
{
|
||||
return (static_cast<int>(id) << 16) | index;
|
||||
return (safe_cast<int>(id) << 16) | index;
|
||||
}
|
||||
|
||||
// constexpr
|
||||
|
||||
@@ -20,12 +20,13 @@
|
||||
#ifndef RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED
|
||||
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Buffer.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/beast/crypto/secure_erase.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
@@ -158,7 +159,7 @@ public:
|
||||
int addFieldID (int type, int name);
|
||||
int addFieldID (SerializedTypeID type, int name)
|
||||
{
|
||||
return addFieldID (static_cast<int> (type), name);
|
||||
return addFieldID (safe_cast<int> (type), name);
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
@@ -266,7 +267,7 @@ public:
|
||||
std::setw (2) <<
|
||||
std::hex <<
|
||||
std::setfill ('0') <<
|
||||
static_cast<unsigned int>(element);
|
||||
safe_cast<unsigned int>(element);
|
||||
}
|
||||
return h.str ();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#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 <boost/optional.hpp>
|
||||
@@ -270,22 +271,22 @@ enum TECcodes : TERUnderlyingType
|
||||
|
||||
// For generic purposes, a free function that returns the value of a TE*codes.
|
||||
constexpr TERUnderlyingType TERtoInt (TELcodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
constexpr TERUnderlyingType TERtoInt (TEMcodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
constexpr TERUnderlyingType TERtoInt (TEFcodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
constexpr TERUnderlyingType TERtoInt (TERcodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
constexpr TERUnderlyingType TERtoInt (TEScodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
constexpr TERUnderlyingType TERtoInt (TECcodes v)
|
||||
{ return static_cast<TERUnderlyingType>(v); }
|
||||
{ return safe_cast<TERUnderlyingType>(v); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Template class that is specific to selected ranges of error codes. The
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
@@ -358,7 +359,7 @@ SField::getField (int code)
|
||||
if (it != unknownCodeToField.end ())
|
||||
return * (it->second);
|
||||
return *(unknownCodeToField[code] = std::unique_ptr<SField const>(
|
||||
new SField(static_cast<SerializedTypeID>(type), field)));
|
||||
new SField(safe_cast<SerializedTypeID>(type), field)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +386,7 @@ std::string SField::getName () const
|
||||
if (fieldValue == 0)
|
||||
return "";
|
||||
|
||||
return std::to_string(static_cast<int> (fieldType)) + "/" +
|
||||
return std::to_string(safe_cast<int> (fieldType)) + "/" +
|
||||
std::to_string(fieldValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
#include <ripple/protocol/SystemParameters.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
@@ -246,13 +247,13 @@ STAmount::STAmount (Issue const& issue,
|
||||
|
||||
STAmount::STAmount (Issue const& issue,
|
||||
std::uint32_t mantissa, int exponent, bool negative)
|
||||
: STAmount (issue, static_cast<std::uint64_t>(mantissa), exponent, negative)
|
||||
: STAmount (issue, safe_cast<std::uint64_t>(mantissa), exponent, negative)
|
||||
{
|
||||
}
|
||||
|
||||
STAmount::STAmount (Issue const& issue,
|
||||
int mantissa, int exponent)
|
||||
: STAmount (issue, static_cast<std::int64_t>(mantissa), exponent)
|
||||
: STAmount (issue, safe_cast<std::int64_t>(mantissa), exponent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
#include <ripple/protocol/STInteger.h>
|
||||
#include <ripple/protocol/TxFormats.h>
|
||||
@@ -98,7 +99,7 @@ STUInt16::getText () const
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
auto item = LedgerFormats::getInstance ().findByType (
|
||||
static_cast <LedgerEntryType> (value_));
|
||||
safe_cast<LedgerEntryType> (value_));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
@@ -107,7 +108,7 @@ STUInt16::getText () const
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
auto item =TxFormats::getInstance().findByType (
|
||||
static_cast <TxType> (value_));
|
||||
safe_cast<TxType> (value_));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
@@ -123,7 +124,7 @@ STUInt16::getJson (int) const
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
auto item = LedgerFormats::getInstance ().findByType (
|
||||
static_cast <LedgerEntryType> (value_));
|
||||
safe_cast<LedgerEntryType> (value_));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
@@ -132,7 +133,7 @@ STUInt16::getJson (int) const
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
auto item = TxFormats::getInstance().findByType (
|
||||
static_cast <TxType> (value_));
|
||||
safe_cast<TxType> (value_));
|
||||
|
||||
if (item != nullptr)
|
||||
return item->getName ();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
@@ -32,6 +33,10 @@ STLedgerEntry::STLedgerEntry (Keylet const& k)
|
||||
, key_ (k.key)
|
||||
, type_ (k.type)
|
||||
{
|
||||
if (!(0u <= type_ &&
|
||||
type_ <= std::min<unsigned>(std::numeric_limits<std::uint16_t>::max(),
|
||||
std::numeric_limits<std::underlying_type_t<LedgerEntryType>>::max())))
|
||||
Throw<std::runtime_error> ("invalid ledger entry type: out of range");
|
||||
auto const format =
|
||||
LedgerFormats::getInstance().findByType (type_);
|
||||
|
||||
@@ -66,7 +71,7 @@ STLedgerEntry::STLedgerEntry (
|
||||
void STLedgerEntry::setSLEType ()
|
||||
{
|
||||
auto format = LedgerFormats::getInstance().findByType (
|
||||
static_cast <LedgerEntryType> (
|
||||
safe_cast <LedgerEntryType> (
|
||||
getFieldU16 (sfLedgerEntryType)));
|
||||
|
||||
if (format == nullptr)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
@@ -275,6 +276,9 @@ static boost::optional<detail::STVar> parseLeaf (
|
||||
TxType const txType (TxFormats::getInstance().
|
||||
findTypeByName (strValue));
|
||||
|
||||
if (txType == ttINVALID)
|
||||
Throw<std::runtime_error>(
|
||||
"Invalid transaction format name");
|
||||
ret = detail::make_stvar <STUInt16> (field,
|
||||
static_cast <std::uint16_t> (txType));
|
||||
|
||||
@@ -287,6 +291,13 @@ static boost::optional<detail::STVar> parseLeaf (
|
||||
LedgerFormats::getInstance().
|
||||
findTypeByName (strValue));
|
||||
|
||||
if (!(0u <= type &&
|
||||
type <= std::min<unsigned>(
|
||||
std::numeric_limits<std::uint16_t>::max(),
|
||||
std::numeric_limits<std::underlying_type_t
|
||||
<LedgerEntryType>>::max())))
|
||||
Throw<std::runtime_error>(
|
||||
"Invalid ledger entry type: out of range");
|
||||
ret = detail::make_stvar <STUInt16> (field,
|
||||
static_cast <std::uint16_t> (type));
|
||||
|
||||
@@ -346,7 +357,7 @@ static boost::optional<detail::STVar> parseLeaf (
|
||||
else if (value.isUInt ())
|
||||
{
|
||||
ret = detail::make_stvar <STUInt32> (field,
|
||||
static_cast <std::uint32_t> (value.asUInt ()));
|
||||
safe_cast <std::uint32_t> (value.asUInt ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -378,7 +389,7 @@ static boost::optional<detail::STVar> parseLeaf (
|
||||
else if (value.isUInt ())
|
||||
{
|
||||
ret = detail::make_stvar <STUInt64> (field,
|
||||
static_cast <std::uint64_t> (value.asUInt ()));
|
||||
safe_cast <std::uint64_t> (value.asUInt ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/HashPrefix.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
@@ -27,9 +31,6 @@
|
||||
#include <ripple/protocol/STArray.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <boost/format.hpp>
|
||||
#include <array>
|
||||
@@ -49,7 +50,7 @@ auto getTxFormat (TxType type)
|
||||
Throw<std::runtime_error> (
|
||||
"Invalid transaction type " +
|
||||
std::to_string (
|
||||
static_cast<std::underlying_type_t<TxType>>(type)));
|
||||
safe_cast<std::underlying_type_t<TxType>>(type)));
|
||||
}
|
||||
|
||||
return format;
|
||||
@@ -58,7 +59,7 @@ auto getTxFormat (TxType type)
|
||||
STTx::STTx (STObject&& object) noexcept (false)
|
||||
: STObject (std::move (object))
|
||||
{
|
||||
tx_type_ = static_cast <TxType> (getFieldU16 (sfTransactionType));
|
||||
tx_type_ = safe_cast<TxType> (getFieldU16 (sfTransactionType));
|
||||
applyTemplate (getTxFormat (tx_type_)->elements); // may throw
|
||||
tid_ = getHash(HashPrefix::transactionID);
|
||||
}
|
||||
@@ -74,7 +75,7 @@ STTx::STTx (SerialIter& sit) noexcept (false)
|
||||
if (set (sit))
|
||||
Throw<std::runtime_error> ("Transaction contains an object terminator");
|
||||
|
||||
tx_type_ = static_cast<TxType> (getFieldU16 (sfTransactionType));
|
||||
tx_type_ = safe_cast<TxType> (getFieldU16 (sfTransactionType));
|
||||
|
||||
applyTemplate (getTxFormat (tx_type_)->elements); // May throw
|
||||
tid_ = getHash(HashPrefix::transactionID);
|
||||
@@ -92,7 +93,7 @@ STTx::STTx (
|
||||
|
||||
assembler (*this);
|
||||
|
||||
tx_type_ = static_cast<TxType>(getFieldU16 (sfTransactionType));
|
||||
tx_type_ = safe_cast<TxType>(getFieldU16 (sfTransactionType));
|
||||
|
||||
if (tx_type_ != type)
|
||||
LogicError ("Transaction type was mutated during assembly");
|
||||
@@ -523,7 +524,7 @@ isPseudoTx(STObject const& tx)
|
||||
auto t = tx[~sfTransactionType];
|
||||
if (!t)
|
||||
return false;
|
||||
auto tt = static_cast<TxType>(*t);
|
||||
auto tt = safe_cast<TxType>(*t);
|
||||
return tt == ttAMENDMENT || tt == ttFEE;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/protocol/tokens.h>
|
||||
#include <ripple/protocol/digest.h>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
@@ -166,7 +167,7 @@ encodeToken (TokenType type,
|
||||
|
||||
// Lay the data out as
|
||||
// <type><token><checksum>
|
||||
buf[0] = static_cast<std::underlying_type_t <TokenType>>(type);
|
||||
buf[0] = safe_cast<std::underlying_type_t <TokenType>>(type);
|
||||
if (size)
|
||||
std::memcpy(buf.data() + 1, token, size);
|
||||
checksum(buf.data() + 1 + size, buf.data(), 1 + size);
|
||||
@@ -259,14 +260,14 @@ std::string
|
||||
decodeBase58Token (std::string const& s,
|
||||
TokenType type, InverseArray const& inv)
|
||||
{
|
||||
auto ret = decodeBase58(s, inv);
|
||||
std::string const ret = decodeBase58(s, inv);
|
||||
|
||||
// Reject zero length tokens
|
||||
if (ret.size() < 6)
|
||||
return {};
|
||||
|
||||
// The type must match.
|
||||
if (type != static_cast<TokenType>(ret[0]))
|
||||
if (type != safe_cast<TokenType>(static_cast<std::uint8_t>(ret[0])))
|
||||
return {};
|
||||
|
||||
// And the checksum must as well.
|
||||
|
||||
@@ -864,12 +864,11 @@ ServerHandlerImp::processRequest (Port const& port,
|
||||
}
|
||||
auto response = to_string (reply);
|
||||
|
||||
rpc_time_.notify (static_cast <beast::insight::Event::value_type> (
|
||||
rpc_time_.notify (
|
||||
std::chrono::duration_cast <std::chrono::milliseconds> (
|
||||
std::chrono::high_resolution_clock::now () - start)));
|
||||
std::chrono::high_resolution_clock::now () - start));
|
||||
++rpc_requests_;
|
||||
rpc_size_.notify (static_cast <beast::insight::Event::value_type> (
|
||||
response.size ()));
|
||||
rpc_size_.notify (beast::insight::Event::value_type{response.size()});
|
||||
|
||||
response += '\n';
|
||||
|
||||
|
||||
@@ -187,8 +187,8 @@ ShardArchiveHandler::complete(path dstPath)
|
||||
auto const mode {ptr->app_.getOPs().getOperatingMode()};
|
||||
if (ptr->validate_ && mode != NetworkOPs::omFULL)
|
||||
{
|
||||
timer_.expires_from_now(static_cast<std::chrono::seconds>(
|
||||
(NetworkOPs::omFULL - mode) * 10));
|
||||
timer_.expires_from_now(std::chrono::seconds{
|
||||
(NetworkOPs::omFULL - mode) * 10});
|
||||
timer_.async_wait(
|
||||
[=, dstPath = std::move(dstPath), ptr = std::move(ptr)]
|
||||
(boost::system::error_code const& ec)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_SERVER_BASEWSPEER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_BASEWSPEER_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/server/impl/BasePeer.h>
|
||||
#include <ripple/protocol/BuildInfo.h>
|
||||
#include <ripple/beast/utility/rngfill.h>
|
||||
@@ -214,8 +215,9 @@ send(std::shared_ptr<WSMsg> w)
|
||||
{
|
||||
JLOG(this->j_.info()) <<
|
||||
"closing slow client";
|
||||
cr_.code = static_cast<boost::beast::websocket::close_code>(4000);
|
||||
cr_.reason = "Client is too slow.";
|
||||
cr_.code = safe_cast<decltype(cr_.code)>
|
||||
(boost::beast::websocket::close_code::policy_error);
|
||||
cr_.reason = "Policy error: client is too slow.";
|
||||
wq_.erase(std::next(wq_.begin()), wq_.end());
|
||||
close();
|
||||
return;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/beast/rfc2616.h>
|
||||
#include <ripple/beast/core/LexicalCast.h>
|
||||
@@ -192,7 +193,7 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
|
||||
{
|
||||
try
|
||||
{
|
||||
port.limit = static_cast<int> (
|
||||
port.limit = safe_cast<int> (
|
||||
beast::lexicalCastThrow<std::uint16_t>(lim));
|
||||
}
|
||||
catch (std::exception const&)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/app/paths/impl/Steps.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/ApplyViewImpl.h>
|
||||
#include <ripple/ledger/PaymentSandbox.h>
|
||||
@@ -183,6 +184,7 @@ allpe(AccountID const& a, Issue const& iss)
|
||||
class ElementComboIter
|
||||
{
|
||||
enum class SB /*state bit*/
|
||||
: std::uint16_t
|
||||
{ acc,
|
||||
iss,
|
||||
cur,
|
||||
@@ -200,7 +202,7 @@ class ElementComboIter
|
||||
last };
|
||||
|
||||
std::uint16_t state_ = 0;
|
||||
static_assert(static_cast<size_t>(SB::last) <= sizeof(decltype(state_)) * 8, "");
|
||||
static_assert(safe_cast<size_t>(SB::last) <= sizeof(decltype(state_)) * 8, "");
|
||||
STPathElement const* prev_ = nullptr;
|
||||
// disallow iss and cur to be specified with acc is specified (simplifies some tests)
|
||||
bool const allowCompound_ = false;
|
||||
@@ -208,7 +210,7 @@ class ElementComboIter
|
||||
bool
|
||||
has(SB s) const
|
||||
{
|
||||
return state_ & (1 << static_cast<int>(s));
|
||||
return state_ & (1 << safe_cast<int>(s));
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <test/jtx/Account.h>
|
||||
#include <test/jtx/amount.h>
|
||||
#include <cassert>
|
||||
@@ -119,7 +120,7 @@ PrettyAmount
|
||||
IOU::operator()(detail::epsilon_multiple m) const
|
||||
{
|
||||
return { STAmount(issue(),
|
||||
static_cast<std::uint64_t>(m.n), -81),
|
||||
safe_cast<std::uint64_t>(m.n), -81),
|
||||
account.name() };
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <ripple/nodestore/DummyScheduler.h>
|
||||
#include <ripple/nodestore/Manager.h>
|
||||
#include <ripple/basics/BasicConfig.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/unity/rocksdb.h>
|
||||
#include <ripple/beast/utility/temp_dir.h>
|
||||
#include <ripple/beast/xor_shift_engine.h>
|
||||
@@ -121,7 +122,7 @@ public:
|
||||
Blob value(d_size_(gen_));
|
||||
rngcpy (&value[0], value.size(), gen_);
|
||||
return NodeObject::createObject (
|
||||
static_cast<NodeObjectType>(d_type_(gen_)),
|
||||
safe_cast<NodeObjectType>(d_type_(gen_)),
|
||||
std::move(value), key);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <ripple/peerfinder/impl/Livecache.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/basics/safe_cast.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <ripple/beast/clock/manual_clock.h>
|
||||
#include <test/beast/IPEndpointCommon.h>
|
||||
@@ -134,7 +135,7 @@ public:
|
||||
add(
|
||||
beast::IP::randomEP(true),
|
||||
c,
|
||||
ripple::rand_int(0, static_cast<int>(Tuning::maxHops + 1)));
|
||||
ripple::rand_int(0, safe_cast<int>(Tuning::maxHops + 1)));
|
||||
auto h = c.hops.histogram();
|
||||
if(! BEAST_EXPECT(! h.empty()))
|
||||
return;
|
||||
@@ -159,7 +160,7 @@ public:
|
||||
add(
|
||||
beast::IP::randomEP(true),
|
||||
c,
|
||||
ripple::rand_int(0, static_cast<int>(Tuning::maxHops + 1)));
|
||||
ripple::rand_int(0, safe_cast<int>(Tuning::maxHops + 1)));
|
||||
|
||||
using at_hop = std::vector <ripple::PeerFinder::Endpoint>;
|
||||
using all_hops = std::array <at_hop, 1 + Tuning::maxHops + 1>;
|
||||
|
||||
Reference in New Issue
Block a user