mirror of
https://github.com/XRPLF/clio.git
synced 2026-07-27 09:00:27 +00:00
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
*clio*.log
|
||||
build*/
|
||||
.build
|
||||
.vscode
|
||||
.python-version
|
||||
CMakeUserPresets.json
|
||||
config.json
|
||||
src/main/impl/Build.cpp
|
||||
|
||||
15
CMake/CheckCompiler.cmake
Normal file
15
CMake/CheckCompiler.cmake
Normal file
@@ -0,0 +1,15 @@
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
|
||||
message(FATAL_ERROR "Clang 12+ required for building clio")
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
|
||||
message(FATAL_ERROR "AppleClang 12+ required for building clio")
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11)
|
||||
message(FATAL_ERROR "GCC 11+ required for building clio")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Supported compilers: AppleClang 12+, Clang 12+, GCC 11+")
|
||||
endif()
|
||||
@@ -1,5 +1,5 @@
|
||||
# call add_converage(module_name) to add coverage targets for the given module
|
||||
function(add_converage module)
|
||||
# call add_coverage(module_name) to add coverage targets for the given module
|
||||
function(add_coverage module)
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
message("[Coverage] Building with llvm Code Coverage Tools")
|
||||
@@ -10,15 +10,21 @@ function(add_converage module)
|
||||
endif()
|
||||
|
||||
# set Flags
|
||||
target_compile_options(${module} PRIVATE -fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
target_link_options(${module} PUBLIC -fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
target_compile_options(${module} PRIVATE
|
||||
-fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
|
||||
target_link_options(${module} PUBLIC
|
||||
-fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
|
||||
target_compile_options(clio PRIVATE -fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
target_link_options(clio PUBLIC -fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
target_compile_options(clio PRIVATE
|
||||
-fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
|
||||
target_link_options(clio PUBLIC
|
||||
-fprofile-instr-generate
|
||||
-fcoverage-mapping)
|
||||
|
||||
# llvm-cov
|
||||
add_custom_target(
|
||||
@@ -60,8 +66,7 @@ function(add_converage module)
|
||||
COMMENT
|
||||
"Open ${module}-llvm-cov/index.html in your browser to view the coverage report."
|
||||
)
|
||||
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR "${CMAKE_CXX_COMPILER_ID}"
|
||||
MATCHES "GNU")
|
||||
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
message("[Coverage] Building with Gcc Code Coverage Tools")
|
||||
|
||||
find_program(GCOV_PATH gcov)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
find_package(Boost 1.75 COMPONENTS filesystem log_setup log thread system REQUIRED)
|
||||
|
||||
target_link_libraries(clio PUBLIC ${Boost_LIBRARIES})
|
||||
find_package(Boost 1.82 REQUIRED
|
||||
COMPONENTS
|
||||
program_options
|
||||
coroutine
|
||||
system
|
||||
log
|
||||
log_setup
|
||||
)
|
||||
|
||||
5
CMake/deps/OpenSSL.cmake
Normal file
5
CMake/deps/OpenSSL.cmake
Normal file
@@ -0,0 +1,5 @@
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
|
||||
)
|
||||
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
2
CMake/deps/Threads.cmake
Normal file
2
CMake/deps/Threads.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads)
|
||||
@@ -1,153 +1 @@
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
find_library(cassandra NAMES cassandra)
|
||||
if(NOT cassandra)
|
||||
message("System installed Cassandra cpp driver not found. Will build")
|
||||
find_library(zlib NAMES zlib1g-dev zlib-devel zlib z)
|
||||
if(NOT zlib)
|
||||
message("zlib not found. will build")
|
||||
add_library(zlib STATIC IMPORTED GLOBAL)
|
||||
ExternalProject_Add(zlib_src
|
||||
PREFIX ${nih_cache_path}
|
||||
GIT_REPOSITORY https://github.com/madler/zlib.git
|
||||
GIT_TAG v1.2.12
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS <BINARY_DIR>/${CMAKE_STATIC_LIBRARY_PREFIX}z.a
|
||||
)
|
||||
ExternalProject_Get_Property (zlib_src SOURCE_DIR)
|
||||
ExternalProject_Get_Property (zlib_src BINARY_DIR)
|
||||
set (zlib_src_SOURCE_DIR "${SOURCE_DIR}")
|
||||
file (MAKE_DIRECTORY ${zlib_src_SOURCE_DIR}/include)
|
||||
set_target_properties (zlib PROPERTIES
|
||||
IMPORTED_LOCATION
|
||||
${BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}z.a
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
${SOURCE_DIR}/include)
|
||||
add_dependencies(zlib zlib_src)
|
||||
file(TO_CMAKE_PATH "${zlib_src_SOURCE_DIR}" zlib_src_SOURCE_DIR)
|
||||
endif()
|
||||
find_library(krb5 NAMES krb5-dev libkrb5-dev)
|
||||
if(NOT krb5)
|
||||
message("krb5 not found. will build")
|
||||
add_library(krb5 STATIC IMPORTED GLOBAL)
|
||||
ExternalProject_Add(krb5_src
|
||||
PREFIX ${nih_cache_path}
|
||||
GIT_REPOSITORY https://github.com/krb5/krb5.git
|
||||
GIT_TAG krb5-1.20
|
||||
UPDATE_COMMAND ""
|
||||
CONFIGURE_COMMAND autoreconf src && CFLAGS=-fcommon ./src/configure --enable-static --disable-shared
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS <SOURCE_DIR>/lib/${CMAKE_STATIC_LIBRARY_PREFIX}krb5.a
|
||||
)
|
||||
message(${ep_lib_prefix}/krb5.a)
|
||||
message(${CMAKE_STATIC_LIBRARY_PREFIX}krb5.a)
|
||||
ExternalProject_Get_Property (krb5_src SOURCE_DIR)
|
||||
ExternalProject_Get_Property (krb5_src BINARY_DIR)
|
||||
set (krb5_src_SOURCE_DIR "${SOURCE_DIR}")
|
||||
file (MAKE_DIRECTORY ${krb5_src_SOURCE_DIR}/include)
|
||||
set_target_properties (krb5 PROPERTIES
|
||||
IMPORTED_LOCATION
|
||||
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}krb5.a
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
${SOURCE_DIR}/include)
|
||||
add_dependencies(krb5 krb5_src)
|
||||
file(TO_CMAKE_PATH "${krb5_src_SOURCE_DIR}" krb5_src_SOURCE_DIR)
|
||||
endif()
|
||||
|
||||
|
||||
find_library(libuv1 NAMES uv1 libuv1 liubuv1-dev libuv1:amd64)
|
||||
|
||||
|
||||
if(NOT libuv1)
|
||||
message("libuv1 not found, will build")
|
||||
add_library(libuv1 STATIC IMPORTED GLOBAL)
|
||||
ExternalProject_Add(libuv_src
|
||||
PREFIX ${nih_cache_path}
|
||||
GIT_REPOSITORY https://github.com/libuv/libuv.git
|
||||
GIT_TAG v1.44.1
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS <BINARY_DIR>/${CMAKE_STATIC_LIBRARY_PREFIX}uv_a.a
|
||||
)
|
||||
|
||||
ExternalProject_Get_Property (libuv_src SOURCE_DIR)
|
||||
ExternalProject_Get_Property (libuv_src BINARY_DIR)
|
||||
set (libuv_src_SOURCE_DIR "${SOURCE_DIR}")
|
||||
file (MAKE_DIRECTORY ${libuv_src_SOURCE_DIR}/include)
|
||||
|
||||
set_target_properties (libuv1 PROPERTIES
|
||||
IMPORTED_LOCATION
|
||||
${BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}uv_a.a
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
${SOURCE_DIR}/include)
|
||||
add_dependencies(libuv1 libuv_src)
|
||||
|
||||
file(TO_CMAKE_PATH "${libuv_src_SOURCE_DIR}" libuv_src_SOURCE_DIR)
|
||||
endif()
|
||||
add_library (cassandra STATIC IMPORTED GLOBAL)
|
||||
ExternalProject_Add(cassandra_src
|
||||
PREFIX ${nih_cache_path}
|
||||
GIT_REPOSITORY https://github.com/datastax/cpp-driver.git
|
||||
GIT_TAG 2.16.2
|
||||
CMAKE_ARGS
|
||||
-DLIBUV_ROOT_DIR=${BINARY_DIR}
|
||||
-DLIBUV_INCLUDE_DIR=${SOURCE_DIR}/include
|
||||
-DCASS_BUILD_STATIC=ON
|
||||
-DCASS_BUILD_SHARED=OFF
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_BYPRODUCTS <BINARY_DIR>/${CMAKE_STATIC_LIBRARY_PREFIX}cassandra_static.a
|
||||
)
|
||||
|
||||
ExternalProject_Get_Property (cassandra_src SOURCE_DIR)
|
||||
ExternalProject_Get_Property (cassandra_src BINARY_DIR)
|
||||
set (cassandra_src_SOURCE_DIR "${SOURCE_DIR}")
|
||||
file (MAKE_DIRECTORY ${cassandra_src_SOURCE_DIR}/include)
|
||||
|
||||
set_target_properties (cassandra PROPERTIES
|
||||
IMPORTED_LOCATION
|
||||
${BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}cassandra_static.a
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
${SOURCE_DIR}/include)
|
||||
message("cass dirs")
|
||||
message(${BINARY_DIR})
|
||||
message(${SOURCE_DIR})
|
||||
message(${BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}cassandra_static.a)
|
||||
add_dependencies(cassandra cassandra_src)
|
||||
|
||||
if(NOT libuv1)
|
||||
ExternalProject_Add_StepDependencies(cassandra_src build libuv1)
|
||||
target_link_libraries(cassandra INTERFACE libuv1)
|
||||
else()
|
||||
target_link_libraries(cassandra INTERFACE ${libuv1})
|
||||
endif()
|
||||
if(NOT krb5)
|
||||
|
||||
ExternalProject_Add_StepDependencies(cassandra_src build krb5)
|
||||
target_link_libraries(cassandra INTERFACE krb5)
|
||||
else()
|
||||
target_link_libraries(cassandra INTERFACE ${krb5})
|
||||
endif()
|
||||
|
||||
if(NOT zlib)
|
||||
ExternalProject_Add_StepDependencies(cassandra_src build zlib)
|
||||
target_link_libraries(cassandra INTERFACE zlib)
|
||||
else()
|
||||
target_link_libraries(cassandra INTERFACE ${zlib})
|
||||
endif()
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(cassandra INTERFACE OpenSSL::SSL)
|
||||
|
||||
file(TO_CMAKE_PATH "${cassandra_src_SOURCE_DIR}" cassandra_src_SOURCE_DIR)
|
||||
target_link_libraries(clio PUBLIC cassandra)
|
||||
else()
|
||||
message("Found system installed cassandra cpp driver")
|
||||
message(${cassandra})
|
||||
find_path(cassandra_includes NAMES cassandra.h REQUIRED)
|
||||
message(${cassandra_includes})
|
||||
get_filename_component(CASSANDRA_HEADER ${cassandra_includes}/cassandra.h REALPATH)
|
||||
get_filename_component(CASSANDRA_HEADER_DIR ${CASSANDRA_HEADER} DIRECTORY)
|
||||
target_link_libraries (clio PUBLIC ${cassandra})
|
||||
target_include_directories(clio PUBLIC ${CASSANDRA_HEADER_DIR})
|
||||
endif()
|
||||
find_package(cassandra-cpp-driver REQUIRED)
|
||||
|
||||
@@ -1,22 +1,4 @@
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(googletest)
|
||||
|
||||
if(NOT googletest_POPULATED)
|
||||
FetchContent_Populate(googletest)
|
||||
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(clio_tests PUBLIC clio gmock_main)
|
||||
target_include_directories(clio_tests PRIVATE unittests)
|
||||
find_package(gtest REQUIRED)
|
||||
|
||||
enable_testing()
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
#increase timeout for tests discovery to 10 seconds, by default it is 5s. As more unittests added, we start to hit this issue
|
||||
#https://github.com/google/googletest/issues/3475
|
||||
gtest_discover_tests(clio_tests DISCOVERY_TIMEOUT 10)
|
||||
|
||||
@@ -1,14 +1 @@
|
||||
FetchContent_Declare(
|
||||
libfmt
|
||||
URL https://github.com/fmtlib/fmt/releases/download/9.1.0/fmt-9.1.0.zip
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(libfmt)
|
||||
|
||||
if(NOT libfmt_POPULATED)
|
||||
FetchContent_Populate(libfmt)
|
||||
add_subdirectory(${libfmt_SOURCE_DIR} ${libfmt_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(clio PUBLIC fmt)
|
||||
|
||||
find_package(fmt REQUIRED)
|
||||
|
||||
1
CMake/deps/libxrpl.cmake
Normal file
1
CMake/deps/libxrpl.cmake
Normal file
@@ -0,0 +1 @@
|
||||
find_package(xrpl REQUIRED)
|
||||
@@ -1,20 +0,0 @@
|
||||
set(RIPPLED_REPO "https://github.com/ripple/rippled.git")
|
||||
set(RIPPLED_BRANCH "1.9.2")
|
||||
set(NIH_CACHE_ROOT "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "")
|
||||
set(patch_command ! grep operator!= src/ripple/protocol/Feature.h || git apply < ${CMAKE_CURRENT_SOURCE_DIR}/CMake/deps/Remove-bitset-operator.patch)
|
||||
message(STATUS "Cloning ${RIPPLED_REPO} branch ${RIPPLED_BRANCH}")
|
||||
FetchContent_Declare(rippled
|
||||
GIT_REPOSITORY "${RIPPLED_REPO}"
|
||||
GIT_TAG "${RIPPLED_BRANCH}"
|
||||
GIT_SHALLOW ON
|
||||
PATCH_COMMAND "${patch_command}"
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(rippled)
|
||||
if(NOT rippled_POPULATED)
|
||||
FetchContent_Populate(rippled)
|
||||
add_subdirectory(${rippled_SOURCE_DIR} ${rippled_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(clio PUBLIC xrpl_core grpc_pbufs)
|
||||
target_include_directories(clio PUBLIC ${rippled_SOURCE_DIR}/src ) # TODO: Seems like this shouldn't be needed?
|
||||
@@ -1,6 +1,7 @@
|
||||
target_compile_options(clio
|
||||
PUBLIC -Wall
|
||||
-Werror
|
||||
-Wno-narrowing
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-dangling-else)
|
||||
target_compile_options(clio PUBLIC
|
||||
-Wall
|
||||
-Werror
|
||||
-Wno-narrowing
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-dangling-else
|
||||
-Wno-unused-but-set-variable)
|
||||
|
||||
100
CMakeLists.txt
100
CMakeLists.txt
@@ -1,21 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.16.3)
|
||||
|
||||
project(clio)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11)
|
||||
message(FATAL_ERROR "GCC 11+ required for building clio")
|
||||
endif()
|
||||
# ==================================================== #
|
||||
# Options #
|
||||
# ==================================================== #
|
||||
option(verbose "Verbose build" FALSE)
|
||||
option(tests "Build tests" FALSE)
|
||||
option(coverage "Build test coverage report" FALSE)
|
||||
option(packaging "Create distribution packages" FALSE)
|
||||
# ==================================================== #
|
||||
|
||||
option(BUILD_TESTS "Build tests" TRUE)
|
||||
|
||||
option(VERBOSE "Verbose build" TRUE)
|
||||
if(VERBOSE)
|
||||
if(verbose)
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
set(FETCHCONTENT_QUIET FALSE CACHE STRING "Verbose FetchContent()")
|
||||
endif()
|
||||
|
||||
|
||||
if(PACKAGING)
|
||||
if(packaging)
|
||||
add_definitions(-DPKG=1)
|
||||
endif()
|
||||
|
||||
@@ -23,18 +22,48 @@ endif()
|
||||
add_definitions(-DBOOST_ASIO_HAS_STD_INVOKE_RESULT=1)
|
||||
|
||||
add_library(clio)
|
||||
target_compile_features(clio PUBLIC cxx_std_20)
|
||||
target_include_directories(clio PUBLIC src)
|
||||
|
||||
include(FetchContent)
|
||||
include(ExternalProject)
|
||||
include(CMake/settings.cmake)
|
||||
# Clio tweaks and checks
|
||||
include(CMake/CheckCompiler.cmake)
|
||||
include(CMake/Settings.cmake)
|
||||
include(CMake/ClioVersion.cmake)
|
||||
include(CMake/deps/rippled.cmake)
|
||||
include(CMake/deps/libfmt.cmake)
|
||||
include(CMake/SourceLocation.cmake)
|
||||
|
||||
# Clio deps
|
||||
include(CMake/deps/libxrpl.cmake)
|
||||
include(CMake/deps/Boost.cmake)
|
||||
include(CMake/deps/OpenSSL.cmake)
|
||||
include(CMake/deps/Threads.cmake)
|
||||
include(CMake/deps/libfmt.cmake)
|
||||
include(CMake/deps/cassandra.cmake)
|
||||
include(CMake/deps/SourceLocation.cmake)
|
||||
|
||||
# TODO: Include directory will be wrong when installed.
|
||||
target_include_directories(clio PUBLIC src)
|
||||
target_compile_features(clio PUBLIC cxx_std_20)
|
||||
|
||||
target_link_libraries(clio
|
||||
PUBLIC Boost::boost
|
||||
PUBLIC Boost::coroutine
|
||||
PUBLIC Boost::program_options
|
||||
PUBLIC Boost::system
|
||||
PUBLIC Boost::log
|
||||
PUBLIC Boost::log_setup
|
||||
PUBLIC cassandra-cpp-driver::cassandra-cpp-driver
|
||||
PUBLIC fmt::fmt
|
||||
PUBLIC OpenSSL::Crypto
|
||||
PUBLIC OpenSSL::SSL
|
||||
PUBLIC xrpl::libxrpl
|
||||
|
||||
INTERFACE Threads::Threads
|
||||
)
|
||||
|
||||
target_compile_definitions(clio PUBLIC
|
||||
BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS
|
||||
BOOST_ASIO_HAS_STD_INVOKE_RESULT
|
||||
BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
|
||||
BOOST_BEAST_ALLOW_DEPRECATED
|
||||
BOOST_CONTAINER_FWD_BAD_DEQUE
|
||||
BOOST_COROUTINES_NO_DEPRECATION_WARNING)
|
||||
|
||||
target_sources(clio PRIVATE
|
||||
## Main
|
||||
@@ -42,7 +71,6 @@ target_sources(clio PRIVATE
|
||||
## Backend
|
||||
src/backend/BackendInterface.cpp
|
||||
src/backend/LedgerCache.cpp
|
||||
## NextGen Backend
|
||||
src/backend/cassandra/impl/Future.cpp
|
||||
src/backend/cassandra/impl/Cluster.cpp
|
||||
src/backend/cassandra/impl/Batch.cpp
|
||||
@@ -70,9 +98,8 @@ target_sources(clio PRIVATE
|
||||
src/rpc/common/Validators.cpp
|
||||
src/rpc/common/MetaProcessors.cpp
|
||||
src/rpc/common/impl/APIVersionParser.cpp
|
||||
# RPC impl
|
||||
src/rpc/common/impl/HandlerProvider.cpp
|
||||
## RPC handler
|
||||
## RPC handlers
|
||||
src/rpc/handlers/AccountChannels.cpp
|
||||
src/rpc/handlers/AccountCurrencies.cpp
|
||||
src/rpc/handlers/AccountInfo.cpp
|
||||
@@ -103,12 +130,16 @@ target_sources(clio PRIVATE
|
||||
src/log/Logger.cpp
|
||||
src/util/Taggable.cpp)
|
||||
|
||||
add_executable(clio_server src/main/main.cpp)
|
||||
# Clio server
|
||||
add_executable(clio_server src/main/Main.cpp)
|
||||
target_link_libraries(clio_server PUBLIC clio)
|
||||
|
||||
if(BUILD_TESTS)
|
||||
# Unittesting
|
||||
if(tests)
|
||||
set(TEST_TARGET clio_tests)
|
||||
add_executable(${TEST_TARGET}
|
||||
# Common
|
||||
unittests/Main.cpp
|
||||
unittests/Playground.cpp
|
||||
unittests/Logger.cpp
|
||||
unittests/Config.cpp
|
||||
@@ -170,23 +201,30 @@ if(BUILD_TESTS)
|
||||
unittests/backend/cassandra/SettingsProviderTests.cpp
|
||||
unittests/backend/cassandra/ExecutionStrategyTests.cpp
|
||||
unittests/backend/cassandra/AsyncExecutorTests.cpp
|
||||
# Webserver
|
||||
unittests/webserver/ServerTest.cpp
|
||||
unittests/webserver/RPCServerHandlerTest.cpp)
|
||||
|
||||
include(CMake/deps/gtest.cmake)
|
||||
|
||||
# fix for dwarf5 bug on ci
|
||||
# See https://github.com/google/googletest/issues/3475
|
||||
gtest_discover_tests(clio_tests DISCOVERY_TIMEOUT 10)
|
||||
|
||||
# Fix for dwarf5 bug on ci
|
||||
target_compile_options(clio PUBLIC -gdwarf-4)
|
||||
|
||||
target_compile_definitions(${TEST_TARGET} PUBLIC UNITTEST_BUILD)
|
||||
target_include_directories(${TEST_TARGET} PRIVATE unittests)
|
||||
target_link_libraries(${TEST_TARGET} PUBLIC clio gtest::gtest)
|
||||
|
||||
# if CODE_COVERAGE enable, add clio_test-ccov
|
||||
if(CODE_COVERAGE)
|
||||
include(CMake/coverage.cmake)
|
||||
add_converage(${TEST_TARGET})
|
||||
# Generate `clio_test-ccov` if coverage is enabled
|
||||
if(coverage)
|
||||
include(CMake/Coverage.cmake)
|
||||
add_coverage(${TEST_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/install/install.cmake)
|
||||
if(PACKAGING)
|
||||
include(CMake/packaging.cmake)
|
||||
if(packaging)
|
||||
include(CMake/packaging.cmake) # TODO: file is actually missing?
|
||||
endif()
|
||||
|
||||
75
README.md
75
README.md
@@ -1,3 +1,78 @@
|
||||
# Temporary build instructions
|
||||
|
||||
## Prerequisites
|
||||
1. Make sure you have conan 1.x installed and active (use brew on mac). Conan may have been upgraded to v2 and that may not work.
|
||||
2. You should already have a Conan profile after building rippled. Example:
|
||||
```
|
||||
[settings]
|
||||
os=Macos
|
||||
os_build=Macos
|
||||
arch=armv8
|
||||
arch_build=armv8
|
||||
compiler=apple-clang
|
||||
compiler.version=14
|
||||
compiler.libcxx=libc++
|
||||
build_type=Release
|
||||
compiler.cppstd=20
|
||||
[options]
|
||||
boost:extra_b2_flags=define=BOOST_ASIO_HAS_STD_INVOKE_RESULT
|
||||
[build_requires]
|
||||
[env]
|
||||
CFLAGS=-DBOOST_ASIO_HAS_STD_INVOKE_RESULT
|
||||
CXXFLAGS=-DBOOST_ASIO_HAS_STD_INVOKE_RESULT
|
||||
[conf]
|
||||
tools.build:cxxflags=['-DBOOST_ASIO_HAS_STD_INVOKE_RESULT']
|
||||
tools.build:cflags=['-DBOOST_ASIO_HAS_STD_INVOKE_RESULT']
|
||||
```
|
||||
|
||||
## Using artifactory (temporary packages)
|
||||
```sh
|
||||
conan remote add conan-non-prod http://18.143.149.228:8081/artifactory/api/conan/conan-non-prod
|
||||
```
|
||||
Now you should be able to download prebuilt `xrpl` package on some platforms. At the very least you should be able to skip the local package step for `rippled` (as described below) and conan should be able to fetch it from artifactory instead.
|
||||
|
||||
## Preparing local packages (alternative to artifactory)
|
||||
1. Get rippled from [this branch](https://github.com/thejohnfreeman/clio/tree/conan)
|
||||
2. Remove old packages you may have cached:
|
||||
```sh
|
||||
conan remove -f xrpl/1.12.0-b2
|
||||
conan remove -f cassandra-cpp-driver/2.16.2
|
||||
```
|
||||
3. In a clone of rippled from step 1, build rippled as per their instructions. pay attention to these commands:
|
||||
```sh
|
||||
conan export external/snappy snappy/1.1.9@
|
||||
conan export external/soci soci/4.0.3@
|
||||
mkdir build && cd build
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
|
||||
cd - # to go back to root of rippled
|
||||
```
|
||||
4. Perform this command at the root directory of rippled
|
||||
```sh
|
||||
conan export .
|
||||
```
|
||||
this will export a local package `xrpl/1.12.0-b2`.
|
||||
|
||||
5. Navigate to clio's root directory and perform
|
||||
```sh
|
||||
conan export external/cassandra # export our "custom" cassandra driver package
|
||||
mkdir build && cd build
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release -o tests=True
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
|
||||
```
|
||||
If all goes well, `conan install` will find required packages and `cmake` will do the rest. you should end up with `clio_server` and `clio_unittests` in the `build` directory (the current directory).
|
||||
Please note that a few unittests are currently failing. See below.
|
||||
|
||||
## Things to fix
|
||||
|
||||
1. Figure out what to do with `ripple::Fees` that is now missing the `units` member. It was used in a few places and couple unittests are broken because of it.
|
||||
2. Fix build on CI (currently using old CMake. need to use conan instead).
|
||||
3. Fix code coverage support (see 'coverage' option in conanfile).
|
||||
4. See if we can contribute/push our cassandra-cpp-driver to conan center so we don't need to export it before we able to use it.
|
||||
5. Try to improve the new asio code that is using `async_compose` and potentially the `FutureWithCallback` way of accepting the callback.
|
||||
|
||||
# Clio
|
||||
Clio is an XRP Ledger API server. Clio is optimized for RPC calls, over WebSocket or JSON-RPC. Validated
|
||||
historical ledger and transaction data are stored in a more space-efficient format,
|
||||
|
||||
79
conanfile.py
Normal file
79
conanfile.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
import re
|
||||
|
||||
class Clio(ConanFile):
|
||||
name = 'clio'
|
||||
license = 'ISC'
|
||||
author = 'Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>'
|
||||
url = 'https://github.com/xrplf/clio'
|
||||
description = 'Clio RPC server'
|
||||
settings = 'os', 'compiler', 'build_type', 'arch'
|
||||
options = {
|
||||
'fPIC': [True, False],
|
||||
'verbose': [True, False],
|
||||
'tests': [True, False], # build unit tests
|
||||
'packaging': [True, False], # create distribution packages
|
||||
'coverage': [True, False], # build for test coverage report
|
||||
}
|
||||
|
||||
requires = [
|
||||
'boost/1.82.0',
|
||||
'cassandra-cpp-driver/2.16.2',
|
||||
'fmt/10.0.0',
|
||||
'grpc/1.50.1',
|
||||
'gtest/1.13.0',
|
||||
'openssl/1.1.1u',
|
||||
'xrpl/1.12.0-b2',
|
||||
]
|
||||
|
||||
default_options = {
|
||||
'fPIC': True,
|
||||
'verbose': False,
|
||||
'tests': False,
|
||||
'packaging': False,
|
||||
'coverage': False,
|
||||
|
||||
'cassandra-driver/*:shared': False,
|
||||
'date/*:header_only': True,
|
||||
'grpc/*:shared': False,
|
||||
'grpc/*:secure': True,
|
||||
'libpq/*:shared': False,
|
||||
'lz4/*:shared': False,
|
||||
'openssl/*:shared': False,
|
||||
'protobuf/*:shared': False,
|
||||
'protobuf/*:with_zlib': True,
|
||||
'snappy/*:shared': False,
|
||||
'gtest/*:no_main': True,
|
||||
}
|
||||
|
||||
exports_sources = (
|
||||
'CMakeLists.txt', 'CMake/*', 'src/*'
|
||||
)
|
||||
|
||||
def configure(self):
|
||||
if self.settings.compiler == 'apple-clang':
|
||||
self.options['boost'].visibility = 'global'
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
# Fix this setting to follow the default introduced in Conan 1.48
|
||||
# to align with our build instructions.
|
||||
self.folders.generators = 'build/generators'
|
||||
|
||||
generators = 'CMakeDeps'
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.variables['verbose'] = self.options.verbose
|
||||
tc.variables['tests'] = self.options.tests
|
||||
tc.variables['coverage'] = self.options.coverage
|
||||
tc.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
87
external/cassandra/conanfile.py
vendored
Normal file
87
external/cassandra/conanfile.py
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
from conan import ConanFile, tools
|
||||
from conan.tools.cmake import CMake, CMakeToolchain
|
||||
|
||||
class Cassandra(ConanFile):
|
||||
name = 'cassandra-cpp-driver'
|
||||
version = '2.16.2'
|
||||
license = 'Apache-2.0'
|
||||
url = 'https://github.com/conan-io/conan-center-index'
|
||||
homepage = 'https://docs.datastax.com/en/developer/cpp-driver/'
|
||||
description = 'Cassandra C++ Driver'
|
||||
topics = ('conan', 'cassandra', 'driver')
|
||||
|
||||
settings = 'os', 'arch', 'compiler', 'build_type'
|
||||
options = {
|
||||
'shared': [True, False],
|
||||
'fPIC': [True, False],
|
||||
'install_header_in_subdir': [True, False],
|
||||
'use_atomic': [None, 'boost', 'std'],
|
||||
'with_openssl': [True, False],
|
||||
'with_zlib': [True, False],
|
||||
'with_kerberos': [True, False],
|
||||
'use_timerfd': [True, False],
|
||||
}
|
||||
default_options = {
|
||||
'shared': False,
|
||||
'fPIC': True,
|
||||
'install_header_in_subdir': False,
|
||||
'use_atomic': None,
|
||||
'with_openssl': True,
|
||||
'with_zlib': True,
|
||||
'with_kerberos': False,
|
||||
'use_timerfd': True,
|
||||
}
|
||||
|
||||
def requirements(self):
|
||||
self.requires('libuv/1.44.1')
|
||||
self.requires('http_parser/2.9.4')
|
||||
if self.options.with_openssl:
|
||||
self.requires('openssl/1.1.1q')
|
||||
if self.options.with_zlib:
|
||||
self.requires('minizip/1.2.12')
|
||||
self.requires('zlib/1.2.13')
|
||||
if self.options.use_atomic == 'boost':
|
||||
self.requires('boost/1.79.0')
|
||||
|
||||
exports_sources = ['CMakeLists.txt']
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == 'Windows':
|
||||
del self.options.fPIC
|
||||
|
||||
def configure(self):
|
||||
self.options['libuv'].shared = self.options.shared
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
if self.settings.get_safe('compiler.cppstd') == '20':
|
||||
tc.blocks['cppstd'].values['cppstd'] = 17
|
||||
tc.variables['CASS_BUILD_STATIC'] = not self.options.shared
|
||||
tc.variables['CASS_USE_STATIC_LIBS'] = not self.options.shared
|
||||
tc.variables['CASS_BUILD_SHARED'] = self.options.shared
|
||||
tc.variables['LIBUV_ROOT_DIR'] = self.deps_cpp_info['libuv'].rootpath
|
||||
if self.options.with_openssl:
|
||||
tc.variables['OPENSSL_ROOT_DIR'] = self.deps_cpp_info['openssl'].rootpath
|
||||
tc.generate()
|
||||
|
||||
def source(self):
|
||||
tools.files.get(self, f'https://github.com/datastax/cpp-driver/archive/refs/tags/{self.version}.tar.gz', strip_root=True)
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
if self.options.shared:
|
||||
self.cpp_info.libs = ['cassandra']
|
||||
else:
|
||||
self.cpp_info.libs = ['cassandra_static']
|
||||
if self.settings.os == 'Windows':
|
||||
self.cpp_info.libs.extend(['iphlpapi', 'psapi', 'wsock32', 'crypt32', 'ws2_32', 'userenv'])
|
||||
if not self.options.shared:
|
||||
self.cpp_info.defines = ['CASS_STATIC']
|
||||
@@ -308,8 +308,9 @@ BackendInterface::fetchFees(std::uint32_t const seq, boost::asio::yield_context&
|
||||
if (sle.getFieldIndex(ripple::sfBaseFee) != -1)
|
||||
fees.base = sle.getFieldU64(ripple::sfBaseFee);
|
||||
|
||||
if (sle.getFieldIndex(ripple::sfReferenceFeeUnits) != -1)
|
||||
fees.units = sle.getFieldU32(ripple::sfReferenceFeeUnits);
|
||||
// deprecated?
|
||||
// if (sle.getFieldIndex(ripple::sfReferenceFeeUnits) != -1)
|
||||
// fees.units = sle.getFieldU32(ripple::sfReferenceFeeUnits);
|
||||
|
||||
if (sle.getFieldIndex(ripple::sfReserveBase) != -1)
|
||||
fees.reserve = sle.getFieldU32(ripple::sfReserveBase);
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <backend/DBHelpers.h>
|
||||
#include <backend/LedgerCache.h>
|
||||
#include <backend/Types.h>
|
||||
#include <config/Config.h>
|
||||
#include <log/Logger.h>
|
||||
|
||||
#include <ripple/protocol/Fees.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json.hpp>
|
||||
|
||||
@@ -98,7 +99,7 @@ synchronous(F&& f)
|
||||
* ctx, and is used to pass a stream of data into the method.
|
||||
*/
|
||||
boost::asio::io_context ctx;
|
||||
boost::asio::io_context::strand strand(ctx);
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand(ctx.get_executor());
|
||||
std::optional<boost::asio::io_context::work> work;
|
||||
|
||||
/*! @brief Place the ctx within the vector of serialized handlers. */
|
||||
@@ -203,11 +204,11 @@ public:
|
||||
}
|
||||
|
||||
/*! @brief Fetches a specific ledger by sequence number. */
|
||||
virtual std::optional<ripple::LedgerInfo>
|
||||
virtual std::optional<ripple::LedgerHeader>
|
||||
fetchLedgerBySequence(std::uint32_t const sequence, boost::asio::yield_context& yield) const = 0;
|
||||
|
||||
/*! @brief Fetches a specific ledger by hash. */
|
||||
virtual std::optional<ripple::LedgerInfo>
|
||||
virtual std::optional<ripple::LedgerHeader>
|
||||
fetchLedgerByHash(ripple::uint256 const& hash, boost::asio::yield_context& yield) const = 0;
|
||||
|
||||
/*! @brief Fetches the latest ledger sequence. */
|
||||
@@ -475,11 +476,11 @@ public:
|
||||
/**
|
||||
* @brief Writes to a specific ledger.
|
||||
*
|
||||
* @param ledgerInfo Const on ledger information.
|
||||
* @param ledgerHeader r-value string representing ledger header.
|
||||
* @param ledgerHeader Ledger header.
|
||||
* @param blob r-value string serialization of ledger header.
|
||||
*/
|
||||
virtual void
|
||||
writeLedger(ripple::LedgerInfo const& ledgerInfo, std::string&& ledgerHeader) = 0;
|
||||
writeLedger(ripple::LedgerHeader const& ledgerHeader, std::string&& blob) = 0;
|
||||
|
||||
/**
|
||||
* @brief Writes a new ledger object.
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/Profiler.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/nft.h>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
namespace Backend::Cassandra {
|
||||
@@ -199,9 +200,9 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
writeLedger(ripple::LedgerInfo const& ledgerInfo, std::string&& header) override
|
||||
writeLedger(ripple::LedgerHeader const& ledgerInfo, std::string&& blob) override
|
||||
{
|
||||
executor_.write(schema_->insertLedgerHeader, ledgerInfo.seq, std::move(header));
|
||||
executor_.write(schema_->insertLedgerHeader, ledgerInfo.seq, std::move(blob));
|
||||
|
||||
executor_.write(schema_->insertLedgerHash, ledgerInfo.hash, ledgerInfo.seq);
|
||||
|
||||
@@ -232,7 +233,7 @@ public:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<ripple::LedgerInfo>
|
||||
std::optional<ripple::LedgerHeader>
|
||||
fetchLedgerBySequence(std::uint32_t const sequence, boost::asio::yield_context& yield) const override
|
||||
{
|
||||
log_.trace() << __func__ << " call for seq " << sequence;
|
||||
@@ -261,7 +262,7 @@ public:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<ripple::LedgerInfo>
|
||||
std::optional<ripple::LedgerHeader>
|
||||
fetchLedgerByHash(ripple::uint256 const& hash, boost::asio::yield_context& yield) const override
|
||||
{
|
||||
log_.trace() << __func__ << " call";
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
#include <ripple/protocol/STAccount.h>
|
||||
#include <ripple/protocol/TxMeta.h>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <boost/json.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <log/Logger.h>
|
||||
#include <util/Expected.h>
|
||||
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
#include <atomic>
|
||||
@@ -75,11 +75,7 @@ public:
|
||||
using FutureType = typename HandleType::FutureType;
|
||||
using FutureWithCallbackType = typename HandleType::FutureWithCallbackType;
|
||||
using ResultType = typename HandleType::ResultType;
|
||||
|
||||
using CompletionTokenType = boost::asio::yield_context;
|
||||
using FunctionType = void(boost::system::error_code);
|
||||
using AsyncResultType = boost::asio::async_result<CompletionTokenType, FunctionType>;
|
||||
using HandlerType = typename AsyncResultType::completion_handler_type;
|
||||
|
||||
DefaultExecutionStrategy(Settings settings, HandleType const& handle)
|
||||
: maxWriteRequestsOutstanding_{settings.maxWriteRequestsOutstanding}
|
||||
@@ -224,29 +220,29 @@ public:
|
||||
[[maybe_unused]] ResultOrErrorType
|
||||
read(CompletionTokenType token, std::vector<StatementType> const& statements)
|
||||
{
|
||||
auto handler = HandlerType{token};
|
||||
auto result = AsyncResultType{handler};
|
||||
auto const numStatements = statements.size();
|
||||
std::optional<FutureWithCallbackType> future;
|
||||
|
||||
// todo: perhaps use policy instead
|
||||
while (true)
|
||||
{
|
||||
numReadRequestsOutstanding_ += numStatements;
|
||||
// TODO: see if we can avoid using shared_ptr for self here
|
||||
auto init = [this, &statements, &future]<typename Self>(Self& self) {
|
||||
future.emplace(handle_.get().asyncExecute(
|
||||
statements, [sself = std::make_shared<Self>(std::move(self))](auto&& res) mutable {
|
||||
boost::asio::post(
|
||||
sself->get_io_executor(), [sself = std::move(sself), res = std::move(res)]() mutable {
|
||||
sself->complete(std::move(res));
|
||||
sself.reset();
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
auto const future = handle_.get().asyncExecute(statements, [handler](auto&&) mutable {
|
||||
boost::asio::post(boost::asio::get_associated_executor(handler), [handler]() mutable {
|
||||
handler(boost::system::error_code{});
|
||||
});
|
||||
});
|
||||
|
||||
// suspend coroutine until completion handler is called
|
||||
result.get();
|
||||
|
||||
auto res = boost::asio::async_compose<CompletionTokenType, void(ResultOrErrorType)>(init, token);
|
||||
numReadRequestsOutstanding_ -= numStatements;
|
||||
|
||||
// it's safe to call blocking get on future here as we already
|
||||
// waited for the coroutine to resume above.
|
||||
if (auto res = future.get(); res)
|
||||
if (res)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@@ -271,28 +267,28 @@ public:
|
||||
[[maybe_unused]] ResultOrErrorType
|
||||
read(CompletionTokenType token, StatementType const& statement)
|
||||
{
|
||||
auto handler = HandlerType{token};
|
||||
auto result = AsyncResultType{handler};
|
||||
std::optional<FutureWithCallbackType> future;
|
||||
|
||||
// todo: perhaps use policy instead
|
||||
while (true)
|
||||
{
|
||||
++numReadRequestsOutstanding_;
|
||||
// TODO: see if we can avoid using shared_ptr for self here
|
||||
auto init = [this, &statement, &future]<typename Self>(Self& self) {
|
||||
future.emplace(handle_.get().asyncExecute(
|
||||
statement, [sself = std::make_shared<Self>(std::move(self))](auto&& res) mutable {
|
||||
boost::asio::post(
|
||||
sself->get_io_executor(), [sself = std::move(sself), res = std::move(res)]() mutable {
|
||||
sself->complete(std::move(res));
|
||||
sself.reset();
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
auto const future = handle_.get().asyncExecute(statement, [handler](auto const&) mutable {
|
||||
boost::asio::post(boost::asio::get_associated_executor(handler), [handler]() mutable {
|
||||
handler(boost::system::error_code{});
|
||||
});
|
||||
});
|
||||
|
||||
// suspend coroutine until completion handler is called
|
||||
result.get();
|
||||
|
||||
auto res = boost::asio::async_compose<CompletionTokenType, void(ResultOrErrorType)>(init, token);
|
||||
--numReadRequestsOutstanding_;
|
||||
|
||||
// it's safe to call blocking get on future here as we already
|
||||
// waited for the coroutine to resume above.
|
||||
if (auto res = future.get(); res)
|
||||
if (res)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@@ -318,9 +314,6 @@ public:
|
||||
std::vector<ResultType>
|
||||
readEach(CompletionTokenType token, std::vector<StatementType> const& statements)
|
||||
{
|
||||
auto handler = HandlerType{token};
|
||||
auto result = AsyncResultType{handler};
|
||||
|
||||
std::atomic_bool hadError = false;
|
||||
std::atomic_int numOutstanding = statements.size();
|
||||
numReadRequestsOutstanding_ += statements.size();
|
||||
@@ -328,29 +321,30 @@ public:
|
||||
auto futures = std::vector<FutureWithCallbackType>{};
|
||||
futures.reserve(numOutstanding);
|
||||
|
||||
// used as the handler for each async statement individually
|
||||
auto executionHandler = [handler, &hadError, &numOutstanding](auto const& res) mutable {
|
||||
if (not res)
|
||||
hadError = true;
|
||||
auto init = [this, &statements, &futures, &hadError, &numOutstanding]<typename Self>(Self& self) {
|
||||
auto sself = std::make_shared<Self>(std::move(self)); // TODO: see if we can avoid this
|
||||
auto executionHandler = [&hadError, &numOutstanding, sself = std::move(sself)](auto const& res) mutable {
|
||||
if (not res)
|
||||
hadError = true;
|
||||
|
||||
// when all async operations complete unblock the result
|
||||
if (--numOutstanding == 0)
|
||||
boost::asio::post(boost::asio::get_associated_executor(handler), [handler]() mutable {
|
||||
handler(boost::system::error_code{});
|
||||
// when all async operations complete unblock the result
|
||||
if (--numOutstanding == 0)
|
||||
boost::asio::post(sself->get_io_executor(), [sself = std::move(sself)]() mutable {
|
||||
sself->complete();
|
||||
sself.reset();
|
||||
});
|
||||
};
|
||||
|
||||
std::transform(
|
||||
std::cbegin(statements),
|
||||
std::cend(statements),
|
||||
std::back_inserter(futures),
|
||||
[this, &executionHandler](auto const& statement) {
|
||||
return handle_.get().asyncExecute(statement, executionHandler);
|
||||
});
|
||||
};
|
||||
|
||||
std::transform(
|
||||
std::cbegin(statements),
|
||||
std::cend(statements),
|
||||
std::back_inserter(futures),
|
||||
[this, &executionHandler](auto const& statement) {
|
||||
return handle_.get().asyncExecute(statement, executionHandler);
|
||||
});
|
||||
|
||||
// suspend coroutine until completion handler is called
|
||||
result.get();
|
||||
|
||||
boost::asio::async_compose<CompletionTokenType, void()>(init, token);
|
||||
numReadRequestsOutstanding_ -= statements.size();
|
||||
|
||||
if (hadError)
|
||||
@@ -359,8 +353,7 @@ public:
|
||||
std::vector<ResultType> results;
|
||||
results.reserve(futures.size());
|
||||
|
||||
// it's safe to call blocking get on futures here as we already
|
||||
// waited for the coroutine to resume above.
|
||||
// it's safe to call blocking get on futures here as we already waited for the coroutine to resume above.
|
||||
std::transform(
|
||||
std::make_move_iterator(std::begin(futures)),
|
||||
std::make_move_iterator(std::end(futures)),
|
||||
|
||||
@@ -90,6 +90,7 @@ invokeHelper(CassFuture* ptr, void* cbPtr)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cb_ can be deleted before cassandra-driver calls it if the user fails to hold onto the future object
|
||||
/* implicit */ FutureWithCallback::FutureWithCallback(CassFuture* ptr, fn_t&& cb)
|
||||
: Future{ptr}, cb_{std::make_unique<fn_t>(std::move(cb))}
|
||||
{
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <etl/ETLService.h>
|
||||
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
|
||||
using namespace clio;
|
||||
|
||||
// Database must be populated when this starts
|
||||
@@ -80,7 +82,7 @@ ETLService::monitor()
|
||||
if (!rng)
|
||||
{
|
||||
log_.info() << "Database is empty. Will download a ledger from the network.";
|
||||
std::optional<ripple::LedgerInfo> ledger;
|
||||
std::optional<ripple::LedgerHeader> ledger;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <log/Logger.h>
|
||||
#include <subscriptions/SubscriptionManager.h>
|
||||
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#include <log/Logger.h>
|
||||
#include <subscriptions/SubscriptionManager.h>
|
||||
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
class Source;
|
||||
|
||||
@@ -26,9 +26,7 @@
|
||||
#include <log/Logger.h>
|
||||
#include <subscriptions/SubscriptionManager.h>
|
||||
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/beast/core.hpp>
|
||||
@@ -37,6 +35,7 @@
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
class LoadBalancer;
|
||||
class Source;
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
|
||||
#include <log/Logger.h>
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -46,7 +46,7 @@ class ForwardCache
|
||||
|
||||
mutable std::shared_mutex mtx_;
|
||||
std::unordered_map<std::string, ResponseType> latestForwarded_;
|
||||
boost::asio::io_context::strand strand_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
Source const& source_;
|
||||
std::uint32_t duration_ = 10;
|
||||
|
||||
@@ -55,7 +55,7 @@ class ForwardCache
|
||||
|
||||
public:
|
||||
ForwardCache(clio::Config const& config, boost::asio::io_context& ioc, Source const& source)
|
||||
: strand_(ioc), source_(source)
|
||||
: strand_(ioc.get_executor()), source_(source)
|
||||
{
|
||||
if (config.contains("cache"))
|
||||
{
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
#include <etl/Source.h>
|
||||
#include <log/Logger.h>
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <util/Profiler.h>
|
||||
|
||||
#include <ripple/beast/core/CurrentThreadName.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -85,7 +84,7 @@ public:
|
||||
* nft_token_transactions tables (mostly transaction hashes, corresponding nodestore hashes and affected accounts)
|
||||
*/
|
||||
FormattedTransactionsData
|
||||
insertTransactions(ripple::LedgerInfo const& ledger, GetLedgerResponseType& data)
|
||||
insertTransactions(ripple::LedgerHeader const& ledger, GetLedgerResponseType& data)
|
||||
{
|
||||
FormattedTransactionsData result;
|
||||
|
||||
@@ -140,7 +139,7 @@ public:
|
||||
* @param sequence the sequence of the ledger to download
|
||||
* @return The ledger downloaded, with a full transaction and account state map
|
||||
*/
|
||||
std::optional<ripple::LedgerInfo>
|
||||
std::optional<ripple::LedgerHeader>
|
||||
loadInitialLedger(uint32_t sequence)
|
||||
{
|
||||
// check that database is actually empty
|
||||
@@ -158,7 +157,7 @@ public:
|
||||
if (!ledgerData)
|
||||
return {};
|
||||
|
||||
ripple::LedgerInfo lgrInfo = util::deserializeHeader(ripple::makeSlice(ledgerData->ledger_header()));
|
||||
ripple::LedgerHeader lgrInfo = util::deserializeHeader(ripple::makeSlice(ledgerData->ledger_header()));
|
||||
|
||||
log_.debug() << "Deserialized ledger header. " << util::toString(lgrInfo);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/Profiler.h>
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -47,7 +47,7 @@ class LedgerPublisher
|
||||
{
|
||||
clio::Logger log_{"ETL"};
|
||||
|
||||
boost::asio::io_context::strand publishStrand_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> publishStrand_;
|
||||
|
||||
std::shared_ptr<BackendInterface> backend_;
|
||||
std::shared_ptr<SubscriptionManagerType> subscriptions_;
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
std::shared_ptr<SubscriptionManager> subscriptions,
|
||||
SystemState const& state)
|
||||
: publishStrand_{ioc}, backend_{backend}, subscriptions_{subscriptions}, state_{std::cref(state)}
|
||||
: publishStrand_{ioc.get_executor()}, backend_{backend}, subscriptions_{subscriptions}, state_{std::cref(state)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
* @param lgrInfo the ledger to publish
|
||||
*/
|
||||
void
|
||||
publish(ripple::LedgerInfo const& lgrInfo)
|
||||
publish(ripple::LedgerHeader const& lgrInfo)
|
||||
{
|
||||
boost::asio::post(publishStrand_, [this, lgrInfo = lgrInfo]() {
|
||||
log_.info() << "Publishing ledger " << std::to_string(lgrInfo.seq);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <util/Profiler.h>
|
||||
|
||||
#include <ripple/beast/core/CurrentThreadName.h>
|
||||
#include "org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h"
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include <chrono>
|
||||
@@ -163,11 +163,11 @@ private:
|
||||
* @param rawData data extracted from an ETL source
|
||||
* @return the newly built ledger and data to write to the database
|
||||
*/
|
||||
std::pair<ripple::LedgerInfo, bool>
|
||||
std::pair<ripple::LedgerHeader, bool>
|
||||
buildNextLedger(GetLedgerResponseType& rawData)
|
||||
{
|
||||
log_.debug() << "Beginning ledger update";
|
||||
ripple::LedgerInfo lgrInfo = util::deserializeHeader(ripple::makeSlice(rawData.ledger_header()));
|
||||
ripple::LedgerHeader lgrInfo = util::deserializeHeader(ripple::makeSlice(rawData.ledger_header()));
|
||||
|
||||
log_.debug() << "Deserialized ledger header. " << util::toString(lgrInfo);
|
||||
backend_->startWrites();
|
||||
@@ -191,7 +191,7 @@ private:
|
||||
log_.fatal()
|
||||
<< "Failed to build next ledger: " << e.what()
|
||||
<< " Possible cause: The ETL node is not compatible with the version of the rippled lib Clio is using.";
|
||||
return {ripple::LedgerInfo{}, false};
|
||||
return {ripple::LedgerHeader{}, false};
|
||||
}
|
||||
|
||||
log_.debug() << "Inserted all transactions. Number of transactions = "
|
||||
@@ -217,7 +217,7 @@ private:
|
||||
* @param rawData Ledger data from GRPC
|
||||
*/
|
||||
void
|
||||
updateCache(ripple::LedgerInfo const& lgrInfo, GetLedgerResponseType& rawData)
|
||||
updateCache(ripple::LedgerHeader const& lgrInfo, GetLedgerResponseType& rawData)
|
||||
{
|
||||
std::vector<Backend::LedgerObject> cacheUpdates;
|
||||
cacheUpdates.reserve(rawData.ledger_objects().objects_size());
|
||||
@@ -348,7 +348,7 @@ private:
|
||||
* @param rawData Ledger data from GRPC
|
||||
*/
|
||||
void
|
||||
writeSuccessors(ripple::LedgerInfo const& lgrInfo, GetLedgerResponseType& rawData)
|
||||
writeSuccessors(ripple::LedgerHeader const& lgrInfo, GetLedgerResponseType& rawData)
|
||||
{
|
||||
// Write successor info, if included from rippled
|
||||
if (rawData.object_neighbors_included())
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <boost/json.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <main/Build.h>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
@@ -230,6 +230,8 @@ tag_invoke(boost::json::value_from_tag, boost::json::value& jv, BookChange const
|
||||
}
|
||||
|
||||
[[nodiscard]] boost::json::object const
|
||||
computeBookChanges(ripple::LedgerInfo const& lgrInfo, std::vector<Backend::TransactionAndMetadata> const& transactions);
|
||||
computeBookChanges(
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
std::vector<Backend::TransactionAndMetadata> const& transactions);
|
||||
|
||||
} // namespace RPC
|
||||
|
||||
@@ -251,7 +251,7 @@ toJson(ripple::SLE const& sle)
|
||||
}
|
||||
|
||||
boost::json::object
|
||||
toJson(ripple::LedgerInfo const& lgrInfo)
|
||||
toJson(ripple::LedgerHeader const& lgrInfo)
|
||||
{
|
||||
boost::json::object header;
|
||||
header["ledger_sequence"] = lgrInfo.seq;
|
||||
@@ -284,7 +284,7 @@ parseStringAsUInt(std::string const& value)
|
||||
return index;
|
||||
}
|
||||
|
||||
std::variant<Status, ripple::LedgerInfo>
|
||||
std::variant<Status, ripple::LedgerHeader>
|
||||
ledgerInfoFromRequest(std::shared_ptr<Backend::BackendInterface const> const& backend, Web::Context const& ctx)
|
||||
{
|
||||
auto hashValue = ctx.params.contains("ledger_hash") ? ctx.params.at("ledger_hash") : nullptr;
|
||||
@@ -339,7 +339,7 @@ ledgerInfoFromRequest(std::shared_ptr<Backend::BackendInterface const> const& ba
|
||||
}
|
||||
|
||||
// extract ledgerInfoFromRequest's parameter from context
|
||||
std::variant<Status, ripple::LedgerInfo>
|
||||
std::variant<Status, ripple::LedgerHeader>
|
||||
getLedgerInfoFromHashOrSeq(
|
||||
BackendInterface const& backend,
|
||||
boost::asio::yield_context& yield,
|
||||
@@ -347,7 +347,7 @@ getLedgerInfoFromHashOrSeq(
|
||||
std::optional<uint32_t> ledgerIndex,
|
||||
uint32_t maxSeq)
|
||||
{
|
||||
std::optional<ripple::LedgerInfo> lgrInfo;
|
||||
std::optional<ripple::LedgerHeader> lgrInfo;
|
||||
auto const err = Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"};
|
||||
if (ledgerHash)
|
||||
{
|
||||
@@ -373,7 +373,7 @@ getLedgerInfoFromHashOrSeq(
|
||||
}
|
||||
|
||||
std::vector<unsigned char>
|
||||
ledgerInfoToBlob(ripple::LedgerInfo const& info, bool includeHash)
|
||||
ledgerInfoToBlob(ripple::LedgerHeader const& info, bool includeHash)
|
||||
{
|
||||
ripple::Serializer s;
|
||||
s.add32(info.seq);
|
||||
@@ -664,7 +664,7 @@ std::shared_ptr<ripple::SLE const>
|
||||
read(
|
||||
std::shared_ptr<Backend::BackendInterface const> const& backend,
|
||||
ripple::Keylet const& keylet,
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
Web::Context const& context)
|
||||
{
|
||||
if (auto const blob = backend->fetchLedgerObject(keylet.key, lgrInfo.seq, context.yield); blob)
|
||||
|
||||
@@ -23,17 +23,18 @@
|
||||
* This file contains a variety of utility functions used when executing the handlers.
|
||||
*/
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <backend/BackendInterface.h>
|
||||
#include <rpc/JS.h>
|
||||
#include <rpc/common/Types.h>
|
||||
#include <util/JsonUtils.h>
|
||||
#include <webserver/Context.h>
|
||||
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/Rate.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <util/JsonUtils.h>
|
||||
|
||||
namespace RPC {
|
||||
|
||||
@@ -74,7 +75,7 @@ boost::json::object
|
||||
toJson(ripple::SLE const& sle);
|
||||
|
||||
boost::json::object
|
||||
toJson(ripple::LedgerInfo const& info);
|
||||
toJson(ripple::LedgerHeader const& info);
|
||||
|
||||
boost::json::object
|
||||
toJson(ripple::TxMeta const& meta);
|
||||
@@ -85,15 +86,15 @@ toBoostJson(RippledJson const& value);
|
||||
|
||||
boost::json::object
|
||||
generatePubLedgerMessage(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
ripple::Fees const& fees,
|
||||
std::string const& ledgerRange,
|
||||
std::uint32_t txnCount);
|
||||
|
||||
std::variant<Status, ripple::LedgerInfo>
|
||||
std::variant<Status, ripple::LedgerHeader>
|
||||
ledgerInfoFromRequest(std::shared_ptr<Backend::BackendInterface const> const& backend, Web::Context const& ctx);
|
||||
|
||||
std::variant<Status, ripple::LedgerInfo>
|
||||
std::variant<Status, ripple::LedgerHeader>
|
||||
getLedgerInfoFromHashOrSeq(
|
||||
BackendInterface const& backend,
|
||||
boost::asio::yield_context& yield,
|
||||
@@ -129,7 +130,7 @@ std::shared_ptr<ripple::SLE const>
|
||||
read(
|
||||
std::shared_ptr<Backend::BackendInterface const> const& backend,
|
||||
ripple::Keylet const& keylet,
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
Web::Context const& context);
|
||||
|
||||
std::variant<Status, std::pair<ripple::PublicKey, ripple::SecretKey>>
|
||||
@@ -139,7 +140,7 @@ std::vector<ripple::AccountID>
|
||||
getAccountsFromTransaction(boost::json::object const& transaction);
|
||||
|
||||
std::vector<unsigned char>
|
||||
ledgerInfoToBlob(ripple::LedgerInfo const& info, bool includeHash = false);
|
||||
ledgerInfoToBlob(ripple::LedgerHeader const& info, bool includeHash = false);
|
||||
|
||||
bool
|
||||
isGlobalFrozen(
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_from.hpp>
|
||||
|
||||
namespace Server {
|
||||
struct ConnectionBase;
|
||||
|
||||
@@ -56,8 +56,6 @@ struct DefaultProcessor final
|
||||
}
|
||||
else if constexpr (HandlerWithoutInput<HandlerType>)
|
||||
{
|
||||
using OutType = HandlerReturnType<typename HandlerType::Output>;
|
||||
|
||||
// no input to pass, ignore the value
|
||||
if (auto const ret = handler.process(ctx); not ret)
|
||||
return Error{ret.error()}; // forward Status
|
||||
|
||||
@@ -65,7 +65,7 @@ AccountChannelsHandler::process(AccountChannelsHandler::Input input, Context con
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
@@ -139,13 +139,15 @@ tag_invoke(boost::json::value_to_tag<AccountChannelsHandler::Input>, boost::json
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, AccountChannelsHandler::Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
auto obj = boost::json::object{
|
||||
{JS(account), output.account},
|
||||
{JS(ledger_hash), output.ledgerHash},
|
||||
{JS(ledger_index), output.ledgerIndex},
|
||||
{JS(validated), output.validated},
|
||||
{JS(limit), output.limit},
|
||||
{JS(channels), output.channels},
|
||||
{JS(channels), value_from(output.channels)},
|
||||
};
|
||||
|
||||
if (output.marker)
|
||||
|
||||
@@ -30,7 +30,7 @@ AccountCurrenciesHandler::process(AccountCurrenciesHandler::Input input, Context
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
|
||||
auto const accountLedgerObject =
|
||||
@@ -81,12 +81,14 @@ AccountCurrenciesHandler::process(AccountCurrenciesHandler::Input input, Context
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, AccountCurrenciesHandler::Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
jv = {
|
||||
{JS(ledger_hash), output.ledgerHash},
|
||||
{JS(ledger_index), output.ledgerIndex},
|
||||
{JS(validated), output.validated},
|
||||
{JS(receive_currencies), output.receiveCurrencies},
|
||||
{JS(send_currencies), output.sendCurrencies},
|
||||
{JS(receive_currencies), value_from(output.receiveCurrencies)},
|
||||
{JS(send_currencies), value_from(output.sendCurrencies)},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ AccountInfoHandler::process(AccountInfoHandler::Input input, Context const& ctx)
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountStr = input.account.value_or(input.ident.value_or(""));
|
||||
auto const accountID = accountFromStringStrict(accountStr);
|
||||
auto const accountKeylet = ripple::keylet::account(*accountID);
|
||||
|
||||
@@ -99,7 +99,7 @@ AccountLinesHandler::process(AccountLinesHandler::Input input, Context const& ct
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
@@ -185,13 +185,15 @@ tag_invoke(boost::json::value_to_tag<AccountLinesHandler::Input>, boost::json::v
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, AccountLinesHandler::Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
auto obj = boost::json::object{
|
||||
{JS(account), output.account},
|
||||
{JS(ledger_hash), output.ledgerHash},
|
||||
{JS(ledger_index), output.ledgerIndex},
|
||||
{JS(validated), output.validated},
|
||||
{JS(limit), output.limit},
|
||||
{JS(lines), output.lines},
|
||||
{JS(lines), value_from(output.lines)},
|
||||
};
|
||||
|
||||
if (output.marker)
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
#include <rpc/handlers/AccountNFTs.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
#include <ripple/protocol/nft.h>
|
||||
|
||||
namespace RPC {
|
||||
|
||||
@@ -33,7 +34,7 @@ AccountNFTsHandler::process(AccountNFTsHandler::Input input, Context const& ctx)
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
@@ -44,7 +44,7 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
@@ -50,7 +50,7 @@ AccountOffersHandler::process(AccountOffersHandler::Input input, Context const&
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
@@ -61,7 +61,7 @@ AccountTxHandler::process(AccountTxHandler::Input input, Context const& ctx) con
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
maxIndex = minIndex = std::get<ripple::LedgerInfo>(lgrInfoOrStatus).seq;
|
||||
maxIndex = minIndex = std::get<ripple::LedgerHeader>(lgrInfoOrStatus).seq;
|
||||
}
|
||||
|
||||
std::optional<Backend::TransactionsCursor> cursor;
|
||||
|
||||
@@ -31,7 +31,7 @@ BookChangesHandler::process(BookChangesHandler::Input input, Context const& ctx)
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const transactions = sharedPtrBackend_->fetchAllTransactionsInLedger(lgrInfo.seq, ctx.yield);
|
||||
|
||||
Output response;
|
||||
@@ -79,7 +79,9 @@ tag_invoke(boost::json::value_to_tag<BookChangesHandler::Input>, boost::json::va
|
||||
}
|
||||
|
||||
[[nodiscard]] boost::json::object const
|
||||
computeBookChanges(ripple::LedgerInfo const& lgrInfo, std::vector<Backend::TransactionAndMetadata> const& transactions)
|
||||
computeBookChanges(
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
std::vector<Backend::TransactionAndMetadata> const& transactions)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ BookOffersHandler::process(Input input, Context const& ctx) const
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const book = std::get<ripple::Book>(bookMaybe);
|
||||
auto const bookKey = getBookBase(book);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ DepositAuthorizedHandler::process(DepositAuthorizedHandler::Input input, Context
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const sourceAccountID = accountFromStringStrict(input.sourceAccount);
|
||||
auto const destinationAccountID = accountFromStringStrict(input.destinationAccount);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ GatewayBalancesHandler::process(GatewayBalancesHandler::Input input, Context con
|
||||
return Error{*status};
|
||||
|
||||
// check account
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
@@ -30,7 +30,7 @@ LedgerHandler::process(LedgerHandler::Input input, Context const& ctx) const
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
Output output;
|
||||
|
||||
if (input.binary)
|
||||
@@ -51,8 +51,6 @@ LedgerHandler::process(LedgerHandler::Input input, Context const& ctx) const
|
||||
output.header[JS(ledger_index)] = std::to_string(lgrInfo.seq);
|
||||
output.header[JS(parent_close_time)] = lgrInfo.parentCloseTime.time_since_epoch().count();
|
||||
output.header[JS(parent_hash)] = ripple::strHex(lgrInfo.parentHash);
|
||||
output.header[JS(seqNum)] = std::to_string(lgrInfo.seq);
|
||||
output.header[JS(totalCoins)] = ripple::to_string(lgrInfo.drops);
|
||||
output.header[JS(total_coins)] = ripple::to_string(lgrInfo.drops);
|
||||
output.header[JS(transaction_hash)] = ripple::strHex(lgrInfo.txHash);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <rpc/handlers/LedgerData.h>
|
||||
|
||||
#include <ripple/app/ledger/LedgerToJson.h>
|
||||
#include <ripple/protocol/serialize.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -68,7 +68,7 @@ LedgerDataHandler::process(Input input, Context const& ctx) const
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
|
||||
// no marker -> first call, return header information
|
||||
auto header = boost::json::object();
|
||||
@@ -93,8 +93,6 @@ LedgerDataHandler::process(Input input, Context const& ctx) const
|
||||
header[JS(ledger_index)] = std::to_string(lgrInfo.seq);
|
||||
header[JS(parent_close_time)] = lgrInfo.parentCloseTime.time_since_epoch().count();
|
||||
header[JS(parent_hash)] = ripple::strHex(lgrInfo.parentHash);
|
||||
header[JS(seqNum)] = std::to_string(lgrInfo.seq);
|
||||
header[JS(totalCoins)] = ripple::to_string(lgrInfo.drops);
|
||||
header[JS(total_coins)] = ripple::to_string(lgrInfo.drops);
|
||||
header[JS(transaction_hash)] = ripple::strHex(lgrInfo.txHash);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const ledgerObject = sharedPtrBackend_->fetchLedgerObject(key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
if (!ledgerObject || ledgerObject->size() == 0)
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <rpc/handlers/NFTBuyOffers.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
using namespace ripple;
|
||||
|
||||
@@ -63,7 +63,7 @@ NFTHistoryHandler::process(NFTHistoryHandler::Input input, Context const& ctx) c
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
maxIndex = minIndex = std::get<ripple::LedgerInfo>(lgrInfoOrStatus).seq;
|
||||
maxIndex = minIndex = std::get<ripple::LedgerHeader>(lgrInfoOrStatus).seq;
|
||||
}
|
||||
|
||||
std::optional<Backend::TransactionsCursor> cursor;
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <rpc/handlers/NFTInfo.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/nft.h>
|
||||
|
||||
using namespace ripple;
|
||||
using namespace ::RPC;
|
||||
@@ -39,7 +39,7 @@ NFTInfoHandler::process(NFTInfoHandler::Input input, Context const& ctx) const
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const maybeNft = sharedPtrBackend_->fetchNFT(tokenID, lgrInfo.seq, ctx.yield);
|
||||
|
||||
if (not maybeNft.has_value())
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <rpc/handlers/NFTOffersCommon.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
using namespace ripple;
|
||||
@@ -68,7 +67,7 @@ NFTOffersHandlerBase::iterateOfferDirectory(
|
||||
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus);
|
||||
|
||||
// TODO: just check for existence without pulling
|
||||
if (not sharedPtrBackend_->fetchLedgerObject(directory.key, lgrInfo.seq, yield))
|
||||
@@ -139,10 +138,12 @@ NFTOffersHandlerBase::iterateOfferDirectory(
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, NFTOffersHandlerBase::Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
auto object = boost::json::object{
|
||||
{JS(nft_id), output.nftID},
|
||||
{JS(validated), output.validated},
|
||||
{JS(offers), output.offers},
|
||||
{JS(offers), value_from(output.offers)},
|
||||
};
|
||||
|
||||
if (output.marker)
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <rpc/handlers/NFTSellOffers.h>
|
||||
|
||||
#include <ripple/app/tx/impl/details/NFTokenUtils.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
using namespace ripple;
|
||||
|
||||
@@ -34,7 +34,7 @@ NoRippleCheckHandler::process(NoRippleCheckHandler::Input input, Context const&
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const accountID = accountFromStringStrict(input.account);
|
||||
auto const keylet = ripple::keylet::account(*accountID).key;
|
||||
auto const accountObj = sharedPtrBackend_->fetchLedgerObject(keylet, lgrInfo.seq, ctx.yield);
|
||||
@@ -46,7 +46,8 @@ NoRippleCheckHandler::process(NoRippleCheckHandler::Input input, Context const&
|
||||
auto sle = ripple::SLE{it, keylet};
|
||||
auto accountSeq = sle.getFieldU32(ripple::sfSequence);
|
||||
bool const bDefaultRipple = sle.getFieldU32(ripple::sfFlags) & ripple::lsfDefaultRipple;
|
||||
auto const fees = input.transactions ? sharedPtrBackend_->fetchFees(lgrInfo.seq, ctx.yield) : std::nullopt;
|
||||
// TODO: remove if no longer needed
|
||||
// auto const fees = input.transactions ? sharedPtrBackend_->fetchFees(lgrInfo.seq, ctx.yield) : std::nullopt;
|
||||
|
||||
auto output = NoRippleCheckHandler::Output();
|
||||
|
||||
@@ -57,7 +58,8 @@ NoRippleCheckHandler::process(NoRippleCheckHandler::Input input, Context const&
|
||||
boost::json::object tx;
|
||||
tx[JS(Sequence)] = accountSeq;
|
||||
tx[JS(Account)] = ripple::toBase58(accountID);
|
||||
tx[JS(Fee)] = toBoostJson(fees->units.jsonClipped());
|
||||
// TODO: deprecated?
|
||||
// tx[JS(Fee)] = toBoostJson(fees->units.jsonClipped());
|
||||
|
||||
return tx;
|
||||
};
|
||||
@@ -186,10 +188,12 @@ tag_invoke(boost::json::value_to_tag<NoRippleCheckHandler::Input>, boost::json::
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, NoRippleCheckHandler::Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
auto obj = boost::json::object{
|
||||
{JS(ledger_hash), output.ledgerHash},
|
||||
{JS(ledger_index), output.ledgerIndex},
|
||||
{"problems", output.problems},
|
||||
{"problems", value_from(output.problems)},
|
||||
{JS(validated), output.validated},
|
||||
};
|
||||
|
||||
|
||||
@@ -171,8 +171,10 @@ private:
|
||||
friend void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
|
||||
jv = {
|
||||
{JS(info), output.info},
|
||||
{JS(info), value_from(output.info)},
|
||||
{JS(validated), output.validated},
|
||||
};
|
||||
}
|
||||
@@ -180,6 +182,7 @@ private:
|
||||
friend void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, InfoSection const& info)
|
||||
{
|
||||
using boost::json::value_from;
|
||||
using ripple::to_string;
|
||||
|
||||
jv = {
|
||||
@@ -188,8 +191,8 @@ private:
|
||||
{JS(time), to_string(std::chrono::floor<std::chrono::microseconds>(info.time))},
|
||||
{JS(uptime), info.uptime.count()},
|
||||
{"clio_version", info.clioVersion},
|
||||
{JS(validated_ledger), info.validatedLedger},
|
||||
{"cache", info.cache},
|
||||
{JS(validated_ledger), value_from(info.validatedLedger)},
|
||||
{"cache", value_from(info.cache)},
|
||||
};
|
||||
|
||||
if (info.isAmendmentBlocked)
|
||||
|
||||
@@ -31,7 +31,7 @@ TransactionEntryHandler::process(TransactionEntryHandler::Input input, Context c
|
||||
if (auto status = std::get_if<Status>(&lgrInfoOrStatus))
|
||||
return Error{*status};
|
||||
|
||||
auto const lgrInfo = std::get<ripple::LedgerInfo>(lgrInfoOrStatus);
|
||||
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus);
|
||||
auto const dbRet = sharedPtrBackend_->fetchTransaction(ripple::uint256{input.txHash.c_str()}, ctx.yield);
|
||||
// Note: transaction_entry is meant to only search a specified ledger for
|
||||
// the specified transaction. tx searches the entire range of history. For
|
||||
|
||||
@@ -41,7 +41,7 @@ Subscription::publish(std::shared_ptr<std::string> const& message)
|
||||
|
||||
boost::json::object
|
||||
getLedgerPubMessage(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
ripple::Fees const& fees,
|
||||
std::string const& ledgerRange,
|
||||
std::uint32_t txnCount)
|
||||
@@ -53,7 +53,8 @@ getLedgerPubMessage(
|
||||
pubMsg["ledger_hash"] = to_string(lgrInfo.hash);
|
||||
pubMsg["ledger_time"] = lgrInfo.closeTime.time_since_epoch().count();
|
||||
|
||||
pubMsg["fee_ref"] = RPC::toBoostJson(fees.units.jsonClipped());
|
||||
// deprecated?
|
||||
// pubMsg["fee_ref"] = RPC::toBoostJson(fees.units.jsonClipped());
|
||||
pubMsg["fee_base"] = RPC::toBoostJson(fees.base.jsonClipped());
|
||||
pubMsg["reserve_base"] = RPC::toBoostJson(fees.reserve.jsonClipped());
|
||||
pubMsg["reserve_inc"] = RPC::toBoostJson(fees.increment.jsonClipped());
|
||||
@@ -144,7 +145,7 @@ SubscriptionManager::unsubBookChanges(SessionPtrType session)
|
||||
|
||||
void
|
||||
SubscriptionManager::pubLedger(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
ripple::Fees const& fees,
|
||||
std::string const& ledgerRange,
|
||||
std::uint32_t txnCount)
|
||||
@@ -156,7 +157,7 @@ SubscriptionManager::pubLedger(
|
||||
}
|
||||
|
||||
void
|
||||
SubscriptionManager::pubTransaction(Backend::TransactionAndMetadata const& blobs, ripple::LedgerInfo const& lgrInfo)
|
||||
SubscriptionManager::pubTransaction(Backend::TransactionAndMetadata const& blobs, ripple::LedgerHeader const& lgrInfo)
|
||||
{
|
||||
auto [tx, meta] = RPC::deserializeTxPlusMeta(blobs, lgrInfo.seq);
|
||||
boost::json::object pubObj;
|
||||
@@ -244,7 +245,7 @@ SubscriptionManager::pubTransaction(Backend::TransactionAndMetadata const& blobs
|
||||
|
||||
void
|
||||
SubscriptionManager::pubBookChanges(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
std::vector<Backend::TransactionAndMetadata> const& transactions)
|
||||
{
|
||||
auto const json = RPC::computeBookChanges(lgrInfo, transactions);
|
||||
|
||||
@@ -24,13 +24,15 @@
|
||||
#include <log/Logger.h>
|
||||
#include <webserver/interface/ConnectionBase.h>
|
||||
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
using SessionPtrType = std::shared_ptr<Server::ConnectionBase>;
|
||||
|
||||
class Subscription
|
||||
{
|
||||
boost::asio::io_context::strand strand_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
std::unordered_set<SessionPtrType> subscribers_ = {};
|
||||
std::atomic_uint64_t subCount_ = 0;
|
||||
|
||||
@@ -39,7 +41,7 @@ public:
|
||||
Subscription(Subscription&) = delete;
|
||||
Subscription(Subscription&&) = delete;
|
||||
|
||||
explicit Subscription(boost::asio::io_context& ioc) : strand_(ioc)
|
||||
explicit Subscription(boost::asio::io_context& ioc) : strand_(ioc.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ class SubscriptionMap
|
||||
{
|
||||
using subscribers = std::set<SessionPtrType>;
|
||||
|
||||
boost::asio::io_context::strand strand_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
std::unordered_map<Key, subscribers> subscribers_ = {};
|
||||
std::atomic_uint64_t subCount_ = 0;
|
||||
|
||||
@@ -81,7 +83,7 @@ public:
|
||||
SubscriptionMap(SubscriptionMap&) = delete;
|
||||
SubscriptionMap(SubscriptionMap&&) = delete;
|
||||
|
||||
explicit SubscriptionMap(boost::asio::io_context& ioc) : strand_(ioc)
|
||||
explicit SubscriptionMap(boost::asio::io_context& ioc) : strand_(ioc.get_executor())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -253,13 +255,15 @@ public:
|
||||
|
||||
void
|
||||
pubLedger(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
ripple::Fees const& fees,
|
||||
std::string const& ledgerRange,
|
||||
std::uint32_t txnCount);
|
||||
|
||||
void
|
||||
pubBookChanges(ripple::LedgerInfo const& lgrInfo, std::vector<Backend::TransactionAndMetadata> const& transactions);
|
||||
pubBookChanges(
|
||||
ripple::LedgerHeader const& lgrInfo,
|
||||
std::vector<Backend::TransactionAndMetadata> const& transactions);
|
||||
|
||||
void
|
||||
unsubLedger(SessionPtrType session);
|
||||
@@ -271,7 +275,7 @@ public:
|
||||
unsubTransactions(SessionPtrType session);
|
||||
|
||||
void
|
||||
pubTransaction(Backend::TransactionAndMetadata const& blobs, ripple::LedgerInfo const& lgrInfo);
|
||||
pubTransaction(Backend::TransactionAndMetadata const& blobs, ripple::LedgerHeader const& lgrInfo);
|
||||
|
||||
void
|
||||
subAccount(ripple::AccountID const& account, SessionPtrType const& session);
|
||||
|
||||
@@ -19,38 +19,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace util {
|
||||
|
||||
inline ripple::LedgerInfo
|
||||
inline ripple::LedgerHeader
|
||||
deserializeHeader(ripple::Slice data)
|
||||
{
|
||||
ripple::SerialIter sit(data.data(), data.size());
|
||||
ripple::LedgerInfo info;
|
||||
|
||||
info.seq = sit.get32();
|
||||
info.drops = sit.get64();
|
||||
info.parentHash = sit.get256();
|
||||
info.txHash = sit.get256();
|
||||
info.accountHash = sit.get256();
|
||||
info.parentCloseTime = ripple::NetClock::time_point{ripple::NetClock::duration{sit.get32()}};
|
||||
info.closeTime = ripple::NetClock::time_point{ripple::NetClock::duration{sit.get32()}};
|
||||
info.closeTimeResolution = ripple::NetClock::duration{sit.get8()};
|
||||
info.closeFlags = sit.get8();
|
||||
info.hash = sit.get256();
|
||||
|
||||
return info;
|
||||
return ripple::deserializeHeader(data, /*hasHash=*/true);
|
||||
}
|
||||
|
||||
inline std::string
|
||||
toString(ripple::LedgerInfo const& info)
|
||||
toString(ripple::LedgerHeader const& info)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "LedgerInfo { Sequence : " << info.seq << " Hash : " << ripple::strHex(info.hash)
|
||||
ss << "LedgerHeader { Sequence : " << info.seq << " Hash : " << ripple::strHex(info.hash)
|
||||
<< " TxHash : " << strHex(info.txHash) << " AccountHash : " << ripple::strHex(info.accountHash)
|
||||
<< " ParentHash : " << strHex(info.parentHash) << " }";
|
||||
return ss.str();
|
||||
|
||||
27
unittests/Main.cpp
Normal file
27
unittests/Main.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, 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 <gtest/gtest.h>
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -103,8 +103,8 @@ TEST_F(BackendCassandraFactoryTestWithDB, CreateCassandraBackend)
|
||||
R"({{
|
||||
"database":
|
||||
{{
|
||||
"type" : "cassandra",
|
||||
"cassandra" : {{
|
||||
"type": "cassandra",
|
||||
"cassandra": {{
|
||||
"contact_points": "{}",
|
||||
"keyspace": "{}",
|
||||
"replication_factor": 1
|
||||
@@ -113,19 +113,22 @@ TEST_F(BackendCassandraFactoryTestWithDB, CreateCassandraBackend)
|
||||
}})",
|
||||
contactPoints,
|
||||
keyspace))};
|
||||
// FIXME: this currently throws runtime_error (Could not create keyspace). no idea why
|
||||
auto backend = make_Backend(ctx, cfg);
|
||||
EXPECT_TRUE(backend);
|
||||
|
||||
// empty db does not have ledger range
|
||||
EXPECT_FALSE(backend->fetchLedgerRange());
|
||||
|
||||
// insert range table
|
||||
Backend::Cassandra::Handle handle{contactPoints};
|
||||
EXPECT_TRUE(handle.connect());
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (False, 100)", keyspace));
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (False, 100)", keyspace));
|
||||
handle.execute(fmt::format("INSERT INTO {}.ledger_range (is_latest, sequence) VALUES (True, 500)", keyspace));
|
||||
|
||||
backend = make_Backend(ctx, cfg);
|
||||
EXPECT_TRUE(backend);
|
||||
|
||||
auto const range = backend->fetchLedgerRange();
|
||||
EXPECT_EQ(range->minSequence, 100);
|
||||
EXPECT_EQ(range->maxSequence, 500);
|
||||
|
||||
@@ -45,19 +45,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineSuccessful)
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
strat.read(yield, statement);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnTimeoutFailure)
|
||||
@@ -67,26 +58,17 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnTimeoutF
|
||||
|
||||
ON_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const&, auto&& cb) {
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}}};
|
||||
auto res = FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
EXPECT_THROW(strat.read(yield, statement), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnInvalidQueryFailure)
|
||||
@@ -96,26 +78,17 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadOneInCoroutineThrowsOnInvalidQ
|
||||
|
||||
ON_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const&, auto&& cb) {
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}}};
|
||||
auto res = FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(handle, asyncExecute(An<FakeStatement const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statement = FakeStatement{};
|
||||
EXPECT_THROW(strat.read(yield, statement), std::runtime_error);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineSuccessful)
|
||||
@@ -134,19 +107,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineSuccessful)
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
strat.read(yield, statements);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnTimeoutFailure)
|
||||
@@ -158,27 +122,18 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnTimeou
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const& statements, auto&& cb) {
|
||||
EXPECT_EQ(statements.size(), 3);
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}}};
|
||||
auto res = FakeResultOrError{CassandraError{"timeout", CASS_ERROR_LIB_REQUEST_TIMED_OUT}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.read(yield, statements), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnInvalidQueryFailure)
|
||||
@@ -190,27 +145,18 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineThrowsOnInvali
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.WillByDefault([](auto const& statements, auto&& cb) {
|
||||
EXPECT_EQ(statements.size(), 3);
|
||||
cb({}); // notify that item is ready
|
||||
return FakeFutureWithCallback{
|
||||
FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}}};
|
||||
auto res = FakeResultOrError{CassandraError{"invalid", CASS_ERROR_SERVER_INVALID_QUERY}};
|
||||
cb(res); // notify that item is ready
|
||||
return FakeFutureWithCallback{res};
|
||||
});
|
||||
EXPECT_CALL(
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.read(yield, statements), std::runtime_error);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineMarksBusyIfRequestsOutstandingExceeded)
|
||||
@@ -233,21 +179,12 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadBatchInCoroutineMarksBusyIfReq
|
||||
handle, asyncExecute(An<std::vector<FakeStatement> const&>(), An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(1);
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
EXPECT_FALSE(strat.isTooBusy()); // 2 was the limit, 0 atm
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
strat.read(yield, statements);
|
||||
EXPECT_FALSE(strat.isTooBusy()); // after read completes it's 0 again
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineSuccessful)
|
||||
@@ -267,20 +204,11 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineSuccessful)
|
||||
An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(3); // once per statement
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
auto res = strat.readEach(yield, statements);
|
||||
EXPECT_EQ(res.size(), statements.size());
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineThrowsOnFailure)
|
||||
@@ -305,19 +233,10 @@ TEST_F(BackendCassandraExecutionStrategyTest, ReadEachInCoroutineThrowsOnFailure
|
||||
An<std::function<void(FakeResultOrError)>&&>()))
|
||||
.Times(3); // once per statement
|
||||
|
||||
auto called = std::atomic_bool{false};
|
||||
auto work = std::optional<boost::asio::io_context::work>{ctx};
|
||||
|
||||
boost::asio::spawn(ctx, [&work, &called, &strat](boost::asio::yield_context yield) {
|
||||
runSpawn([&strat](boost::asio::yield_context yield) {
|
||||
auto statements = std::vector<FakeStatement>(3);
|
||||
EXPECT_THROW(strat.readEach(yield, statements), DatabaseTimeout);
|
||||
|
||||
called = true;
|
||||
work.reset();
|
||||
});
|
||||
|
||||
ctx.run();
|
||||
ASSERT_TRUE(called);
|
||||
}
|
||||
|
||||
TEST_F(BackendCassandraExecutionStrategyTest, WriteSyncFirstTrySuccessful)
|
||||
|
||||
@@ -229,8 +229,6 @@ TEST_F(RPCLedgerDataHandlerTest, NoMarker)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
@@ -297,8 +295,6 @@ TEST_F(RPCLedgerDataHandlerTest, TypeFilter)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
@@ -368,8 +364,6 @@ TEST_F(RPCLedgerDataHandlerTest, OutOfOrder)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"closed":true
|
||||
|
||||
@@ -267,8 +267,6 @@ TEST_F(RPCLedgerHandlerTest, Default)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
@@ -457,8 +455,6 @@ TEST_F(RPCLedgerHandlerTest, TransactionsExpandNotBinary)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions":[
|
||||
@@ -679,8 +675,6 @@ TEST_F(RPCLedgerHandlerTest, OwnerFundsEmtpy)
|
||||
"ledger_index":"30",
|
||||
"parent_close_time":0,
|
||||
"parent_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum":"30",
|
||||
"totalCoins":"0",
|
||||
"total_coins":"0",
|
||||
"transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions":[
|
||||
@@ -771,9 +765,7 @@ TEST_F(RPCLedgerHandlerTest, OwnerFundsTrueBinaryFalse)
|
||||
"ledger_index": "30",
|
||||
"parent_close_time": 0,
|
||||
"parent_hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"seqNum": "30",
|
||||
"total_coins": "0",
|
||||
"totalCoins": "0",
|
||||
"transaction_hash": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"transactions": [
|
||||
{
|
||||
|
||||
@@ -615,6 +615,7 @@ TEST_F(RPCSubscribeHandlerTest, StreamsLedger)
|
||||
auto const handler = AnyHandler{SubscribeHandler{mockBackendPtr, subManager_}};
|
||||
auto const output = handler.process(input, Context{std::ref(yield), session_});
|
||||
ASSERT_TRUE(output);
|
||||
// FIXME: fee_ref is missing now. this is possibly correct. need to confirm:
|
||||
EXPECT_EQ(output->as_object(), json::parse(expectedOutput));
|
||||
std::this_thread::sleep_for(20ms);
|
||||
auto const report = subManager_->report();
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <webserver/interface/ConnectionBase.h>
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/Protocol.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
|
||||
#include <backend/Types.h>
|
||||
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
#include <ripple/protocol/Protocol.h>
|
||||
#include <ripple/protocol/STBase.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/TxMeta.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
@@ -788,12 +788,12 @@ TEST_F(WebRPCServerHandlerTest, HTTPTooBusy)
|
||||
TEST_F(WebRPCServerHandlerTest, HTTPRequestNotJson)
|
||||
{
|
||||
static auto constexpr request = "not json";
|
||||
static auto constexpr response = "Unable to parse request: syntax error";
|
||||
static auto constexpr responsePrefix = "Unable to parse request: syntax error";
|
||||
|
||||
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
|
||||
|
||||
(*handler)(std::move(request), session);
|
||||
EXPECT_EQ(session->message, response);
|
||||
EXPECT_THAT(session->message, testing::StartsWith(responsePrefix));
|
||||
EXPECT_EQ(session->lastStatus, boost::beast::http::status::bad_request);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user