mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-20 11:45:53 +00:00
@@ -22,6 +22,7 @@
|
|||||||
#include "rpc/Errors.hpp"
|
#include "rpc/Errors.hpp"
|
||||||
#include "rpc/RPCHelpers.hpp"
|
#include "rpc/RPCHelpers.hpp"
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
|
#include "util/TimeUtils.hpp"
|
||||||
|
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
#include <boost/json/value.hpp>
|
#include <boost/json/value.hpp>
|
||||||
@@ -65,10 +66,8 @@ TimeFormatValidator::verify(boost::json::value const& value, std::string_view ke
|
|||||||
if (not value.as_object().at(key).is_string())
|
if (not value.as_object().at(key).is_string())
|
||||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||||
|
|
||||||
std::tm time = {};
|
auto const ret = util::SystemTpFromUTCStr(value_to<std::string>(value.as_object().at(key)), format_);
|
||||||
std::stringstream stream(value_to<std::string>(value.as_object().at(key)));
|
if (!ret)
|
||||||
stream >> std::get_time(&time, format_.c_str());
|
|
||||||
if (stream.fail())
|
|
||||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -22,19 +22,16 @@
|
|||||||
#include "rpc/Errors.hpp"
|
#include "rpc/Errors.hpp"
|
||||||
#include "rpc/JS.hpp"
|
#include "rpc/JS.hpp"
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
|
#include "util/TimeUtils.hpp"
|
||||||
|
|
||||||
#include <boost/json/conversion.hpp>
|
#include <boost/json/conversion.hpp>
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
#include <boost/json/value.hpp>
|
#include <boost/json/value.hpp>
|
||||||
#include <xrpl/basics/chrono.h>
|
|
||||||
#include <xrpl/basics/strHex.h>
|
#include <xrpl/basics/strHex.h>
|
||||||
#include <xrpl/protocol/jss.h>
|
#include <xrpl/protocol/jss.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ctime>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -61,18 +58,16 @@ LedgerIndexHandler::process(LedgerIndexHandler::Input input, Context const& ctx)
|
|||||||
return fillOutputByIndex(maxIndex);
|
return fillOutputByIndex(maxIndex);
|
||||||
|
|
||||||
auto const convertISOTimeStrToTicks = [](std::string const& isoTimeStr) {
|
auto const convertISOTimeStrToTicks = [](std::string const& isoTimeStr) {
|
||||||
std::tm time = {};
|
auto const systemTime = util::SystemTpFromUTCStr(isoTimeStr, DATE_FORMAT);
|
||||||
std::stringstream ss(isoTimeStr);
|
// systemTime must be valid after validation passed
|
||||||
ss >> std::get_time(&time, DATE_FORMAT);
|
return systemTime->time_since_epoch().count();
|
||||||
return std::chrono::system_clock::from_time_t(std::mktime(&time)).time_since_epoch().count();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const ticks = convertISOTimeStrToTicks(*input.date);
|
auto const ticks = convertISOTimeStrToTicks(*input.date);
|
||||||
|
|
||||||
auto const earlierThan = [&](std::uint32_t ledgerIndex) {
|
auto const earlierThan = [&](std::uint32_t ledgerIndex) {
|
||||||
auto const header = sharedPtrBackend_->fetchLedgerBySequence(ledgerIndex, ctx.yield);
|
auto const header = sharedPtrBackend_->fetchLedgerBySequence(ledgerIndex, ctx.yield);
|
||||||
auto const ledgerTime =
|
auto const ledgerTime = util::SystemTpFromLedgerCloseTime(header->closeTime);
|
||||||
std::chrono::system_clock::time_point{header->closeTime.time_since_epoch() + ripple::epoch_offset};
|
|
||||||
return ticks < ledgerTime.time_since_epoch().count();
|
return ticks < ledgerTime.time_since_epoch().count();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ target_sources(
|
|||||||
requests/impl/SslContext.cpp
|
requests/impl/SslContext.cpp
|
||||||
Taggable.cpp
|
Taggable.cpp
|
||||||
TerminationHandler.cpp
|
TerminationHandler.cpp
|
||||||
|
TimeUtils.cpp
|
||||||
TxUtils.cpp
|
TxUtils.cpp
|
||||||
LedgerUtils.cpp
|
LedgerUtils.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
42
src/util/TimeUtils.cpp
Normal file
42
src/util/TimeUtils.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and 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.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "util/TimeUtils.hpp"
|
||||||
|
|
||||||
|
#include <xrpl/basics/chrono.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
[[nodiscard]] std::optional<std::chrono::system_clock::time_point>
|
||||||
|
SystemTpFromUTCStr(std::string const& dateStr, std::string const& format)
|
||||||
|
{
|
||||||
|
std::tm timeStruct;
|
||||||
|
auto const ret = strptime(dateStr.c_str(), format.c_str(), &timeStruct);
|
||||||
|
if (ret == nullptr) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return std::chrono::system_clock::from_time_t(timegm(&timeStruct));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::chrono::system_clock::time_point
|
||||||
|
SystemTpFromLedgerCloseTime(ripple::NetClock::time_point closeTime)
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::time_point{closeTime.time_since_epoch() + ripple::epoch_offset};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
46
src/util/TimeUtils.hpp
Normal file
46
src/util/TimeUtils.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and 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.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/basics/chrono.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a UTC date string to a system_clock::time_point if possible.
|
||||||
|
* @param dateStr The UTC date string to convert.
|
||||||
|
* @param format The format of the date string.
|
||||||
|
* @return The system_clock::time_point if the conversion was successful, otherwise std::nullopt.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::optional<std::chrono::system_clock::time_point>
|
||||||
|
SystemTpFromUTCStr(std::string const& dateStr, std::string const& format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a ledger close time which is XRPL network clock to a system_clock::time_point.
|
||||||
|
* @param closeTime The ledger close time to convert.
|
||||||
|
* @return The system_clock::time_point.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::chrono::system_clock::time_point
|
||||||
|
SystemTpFromLedgerCloseTime(ripple::NetClock::time_point closeTime);
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
@@ -119,6 +119,7 @@ target_sources(
|
|||||||
util/RandomTests.cpp
|
util/RandomTests.cpp
|
||||||
util/RetryTests.cpp
|
util/RetryTests.cpp
|
||||||
util/SignalsHandlerTests.cpp
|
util/SignalsHandlerTests.cpp
|
||||||
|
util/TimeUtilsTests.cpp
|
||||||
util/TxUtilTests.cpp
|
util/TxUtilTests.cpp
|
||||||
# Webserver
|
# Webserver
|
||||||
web/AdminVerificationTests.cpp
|
web/AdminVerificationTests.cpp
|
||||||
|
|||||||
@@ -90,6 +90,24 @@ TEST_F(RPCLedgerIndexTest, EarlierThanMinLedger)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RPCLedgerIndexTest, ChangeTimeZone)
|
||||||
|
{
|
||||||
|
setenv("TZ", "EST+5", 1);
|
||||||
|
backend->setRange(RANGEMIN, RANGEMAX);
|
||||||
|
auto const handler = AnyHandler{LedgerIndexHandler{backend}};
|
||||||
|
auto const req = json::parse(R"({"date": "2024-06-25T12:23:05Z"})");
|
||||||
|
auto const ledgerHeader =
|
||||||
|
CreateLedgerHeaderWithUnixTime(LEDGERHASH, RANGEMIN, 1719318190); //"2024-06-25T12:23:10Z"
|
||||||
|
EXPECT_CALL(*backend, fetchLedgerBySequence(RANGEMIN, _)).WillOnce(Return(ledgerHeader));
|
||||||
|
runSpawn([&](auto yield) {
|
||||||
|
auto const output = handler.process(req, Context{yield});
|
||||||
|
ASSERT_FALSE(output);
|
||||||
|
auto const err = rpc::makeError(output.result.error());
|
||||||
|
EXPECT_EQ(err.at("error").as_string(), "lgrNotFound");
|
||||||
|
});
|
||||||
|
unsetenv("TZ");
|
||||||
|
}
|
||||||
|
|
||||||
struct LedgerIndexTestsCaseBundle {
|
struct LedgerIndexTestsCaseBundle {
|
||||||
std::string testName;
|
std::string testName;
|
||||||
std::string json;
|
std::string json;
|
||||||
|
|||||||
51
tests/unit/util/TimeUtilsTests.cpp
Normal file
51
tests/unit/util/TimeUtilsTests.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and 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.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "util/TimeUtils.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
TEST(TimeUtilTests, SystemTpFromUTCStrSuccess)
|
||||||
|
{
|
||||||
|
auto const tp = util::SystemTpFromUTCStr("2024-01-01T10:50:40Z", "%Y-%m-%dT%H:%M:%SZ");
|
||||||
|
ASSERT_TRUE(tp.has_value());
|
||||||
|
auto const time = std::chrono::system_clock::to_time_t(tp.value());
|
||||||
|
std::tm timeStruct;
|
||||||
|
gmtime_r(&time, &timeStruct);
|
||||||
|
EXPECT_EQ(timeStruct.tm_year + 1900, 2024);
|
||||||
|
EXPECT_EQ(timeStruct.tm_mon, 0);
|
||||||
|
EXPECT_EQ(timeStruct.tm_mday, 1);
|
||||||
|
EXPECT_EQ(timeStruct.tm_hour, 10);
|
||||||
|
EXPECT_EQ(timeStruct.tm_min, 50);
|
||||||
|
EXPECT_EQ(timeStruct.tm_sec, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimeUtilTests, SystemTpFromUTCStrFail)
|
||||||
|
{
|
||||||
|
auto const tp = util::SystemTpFromUTCStr("2024-01-01T", "%Y-%m-%dT%H:%M:%SZ");
|
||||||
|
ASSERT_FALSE(tp.has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimeUtilTests, SystemTpFromLedgerCloseTime)
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
auto const tp = util::SystemTpFromLedgerCloseTime(ripple::NetClock::time_point{seconds{0}});
|
||||||
|
EXPECT_EQ(tp.time_since_epoch(), ripple::epoch_offset);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user