Compare commits

..

11 Commits

Author SHA1 Message Date
Bart Thomee
3d6cc7dc91 Restore CI env vars 2025-10-20 12:11:03 -04:00
Bart Thomee
3711d40901 Restore CMAKE_UNITY_BUILD_BATCH_SIZE 2025-10-20 11:49:41 -04:00
Bart Thomee
26acbaed64 chore: Set CMake CI variable but reduce its effects 2025-10-20 11:47:59 -04:00
Bart
afb6e0e41b chore: Set fail fast to false, except for when the merge group is used (#5897)
This PR sets the fail-fast strategy option to false (it defaults to true), unless it is run by a merge group.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-17 16:17:02 +00:00
Bart
5523557226 chore: Clean up Conan variables in CI (#5903)
This change sanitizes inputs by setting them as environment variables, and adjusts the number of CPUs used for building. Namely, GitHub inputs should be sanitized, per recommendation by Semgrep, as using them directly poses a security risk. A recent change further overrode the global configuration by having builds use all cores, but as we have noticed an increased number of job cancelation this change updates it to use all cores less one.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-17 16:04:58 +00:00
Bart
b64707f53b chore: Add support for RHEL 8 (#5880)
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-17 14:09:47 +00:00
Ayaz Salikhov
0b113f371f refactor: Update pre-commit workflow to latest version (#5902)
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-17 13:40:10 +00:00
tequ
b4c894c1ba refactor: Autofill signature for Simulate RPC (#5852)
This change enables autofilling of signature-related fields in the Simulate RPC.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-16 21:18:53 +00:00
Mayukha Vadari
92281a4ede refactor: replace string JSONs with Json::Value (#5886)
There are some tests that write out JSONs as a string instead of using the Json::Value library, which are cleaned up by this change.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-16 16:02:25 +00:00
Bronek Kozicki
e80642fc12 fix: Fix regression in ConnectAttempt (#5900)
A regression was introduced in #5669 which would cause rippled to potentially dereference a disengaged std::optional when connecting to a peer. This would cause UB in release build and crash in debug.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-16 12:54:36 +00:00
Mayukha Vadari
640ce4988f refactor: replace boost::lexical_cast<std::string> with to_string (#5883)
This change replaces boost::lexical_cast<std::string> with to_string in some of the tests to make them more readable.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-16 12:46:21 +00:00
34 changed files with 659 additions and 1173 deletions

View File

@@ -28,6 +28,7 @@ runs:
BUILD_DIR: ${{ inputs.build_dir }} BUILD_DIR: ${{ inputs.build_dir }}
BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }} BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }}
BUILD_TYPE: ${{ inputs.build_type }} BUILD_TYPE: ${{ inputs.build_type }}
VERBOSITY: ${{ inputs.verbosity }}
run: | run: |
echo 'Installing dependencies.' echo 'Installing dependencies.'
mkdir -p '${{ env.BUILD_DIR }}' mkdir -p '${{ env.BUILD_DIR }}'
@@ -38,7 +39,6 @@ runs:
--options:host='&:tests=True' \ --options:host='&:tests=True' \
--options:host='&:xrpld=True' \ --options:host='&:xrpld=True' \
--settings:all build_type='${{ env.BUILD_TYPE }}' \ --settings:all build_type='${{ env.BUILD_TYPE }}' \
--conf:all tools.build:verbosity='${{ inputs.verbosity }}' \ --conf:all tools.build:verbosity='${{ env.VERBOSITY }}' \
--conf:all tools.compilation:verbosity='${{ inputs.verbosity }}' \ --conf:all tools.compilation:verbosity='${{ env.VERBOSITY }}' \
--conf:all tools.build:jobs=$(nproc) \
.. ..

View File

@@ -138,7 +138,6 @@ test.toplevel > test.csf
test.toplevel > xrpl.json test.toplevel > xrpl.json
test.unit_test > xrpl.basics test.unit_test > xrpl.basics
tests.libxrpl > xrpl.basics tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.ledger
tests.libxrpl > xrpl.net tests.libxrpl > xrpl.net
xrpl.json > xrpl.basics xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics xrpl.ledger > xrpl.basics

View File

@@ -73,47 +73,61 @@
"compiler_version": "20", "compiler_version": "20",
"image_sha": "6948666" "image_sha": "6948666"
}, },
{
"distro_name": "rhel",
"distro_version": "8",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "10e69b4"
},
{
"distro_name": "rhel",
"distro_version": "8",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "10e69b4"
},
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "12", "compiler_version": "12",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "13", "compiler_version": "13",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "any", "compiler_version": "any",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "10", "distro_version": "10",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "10", "distro_version": "10",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "any", "compiler_version": "any",
"image_sha": "6948666" "image_sha": "10e69b4"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",

View File

@@ -103,6 +103,7 @@ jobs:
if: ${{ needs.should-run.outputs.go == 'true' }} if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/reusable-build-test.yml
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [linux, macos, windows] os: [linux, macos, windows]
with: with:

View File

@@ -65,6 +65,7 @@ jobs:
build-test: build-test:
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/reusable-build-test.yml
strategy: strategy:
fail-fast: ${{ github.event_name == 'merge_group' }}
matrix: matrix:
os: [linux, macos, windows] os: [linux, macos, windows]
with: with:

View File

@@ -9,7 +9,7 @@ on:
jobs: jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks: run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@af1b0f0d764cda2e5435f5ac97b240d4bd4d95d3 uses: XRPLF/actions/.github/workflows/pre-commit.yml@a8d7472b450eb53a1e5228f64552e5974457a21a
with: with:
runs_on: ubuntu-latest runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }' container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'

View File

@@ -42,7 +42,7 @@ jobs:
- generate-matrix - generate-matrix
uses: ./.github/workflows/reusable-build-test-config.yml uses: ./.github/workflows/reusable-build-test-config.yml
strategy: strategy:
fail-fast: false fail-fast: ${{ github.event_name == 'merge_group' }}
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
max-parallel: 10 max-parallel: 10
with: with:

View File

@@ -64,7 +64,9 @@ jobs:
conan_remote_name: ${{ inputs.conan_remote_name }} conan_remote_name: ${{ inputs.conan_remote_name }}
conan_remote_url: ${{ inputs.conan_remote_url }} conan_remote_url: ${{ inputs.conan_remote_url }}
- name: Log into Conan remote - name: Log into Conan remote
run: conan remote login ${{ inputs.conan_remote_name }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}" env:
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
run: conan remote login ${{ env.CONAN_REMOTE_NAME }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
- name: Upload package - name: Upload package
env: env:
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }} CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}

View File

@@ -181,11 +181,6 @@ if(xrpld)
xrpl.libxrpl xrpl.libxrpl
) )
exclude_if_included(rippled) exclude_if_included(rippled)
# define a macro for tests that might need to
# be exluded or run differently in CI environment
if(is_ci)
target_compile_definitions(rippled PRIVATE RIPPLED_RUNNING_IN_CI)
endif ()
if(voidstar) if(voidstar)
target_compile_options(rippled target_compile_options(rippled

View File

@@ -43,6 +43,7 @@ else ()
set (is_linux FALSE) set (is_linux FALSE)
endif () endif ()
# The CI environment variable is set by GitHub Actions.
if ("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true") if ("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
set (is_ci TRUE) set (is_ci TRUE)
else () else ()

View File

@@ -3,4 +3,4 @@
core:non_interactive=True core:non_interactive=True
core.download:parallel={{ os.cpu_count() }} core.download:parallel={{ os.cpu_count() }}
core.upload:parallel={{ os.cpu_count() }} core.upload:parallel={{ os.cpu_count() }}
tools.build:jobs={{ (os.cpu_count() * 4/5) | int }} tools.build:jobs={{ os.cpu_count() - 1 }}

View File

@@ -170,6 +170,9 @@ public:
bool bool
retrieve(key_type const& key, T& data); retrieve(key_type const& key, T& data);
mutex_type&
peekMutex();
std::vector<key_type> std::vector<key_type>
getKeys() const; getKeys() const;

View File

@@ -668,6 +668,29 @@ TaggedCache<
return true; return true;
} }
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
inline auto
TaggedCache<
Key,
T,
IsKeyCache,
SharedWeakUnionPointer,
SharedPointerType,
Hash,
KeyEqual,
Mutex>::peekMutex() -> mutex_type&
{
return m_mutex;
}
template < template <
class Key, class Key,
class T, class T,

View File

@@ -1,138 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_LEDGER_INDEX_MAP_H_INCLUDED
#define RIPPLE_APP_LEDGER_INDEX_MAP_H_INCLUDED
#include <algorithm>
#include <mutex>
#include <unordered_map>
namespace ripple {
template <class Key, class Mapped>
class LedgerIndexMap
{
public:
LedgerIndexMap() = default;
explicit LedgerIndexMap(std::size_t reserve_capacity)
{
data_.reserve(reserve_capacity);
}
LedgerIndexMap(LedgerIndexMap const&) = delete;
LedgerIndexMap&
operator=(LedgerIndexMap const&) = delete;
LedgerIndexMap(LedgerIndexMap&&) = delete;
LedgerIndexMap&
operator=(LedgerIndexMap&&) = delete;
Mapped&
operator[](Key const& k)
{
std::lock_guard lock(mutex_);
return data_[k];
}
Mapped&
operator[](Key&& k)
{
std::lock_guard lock(mutex_);
return data_[std::move(k)];
}
[[nodiscard]] Mapped*
get(Key const& k)
{
std::lock_guard lock(mutex_);
auto it = data_.find(k);
return it == data_.end() ? nullptr : &it->second;
}
[[nodiscard]] Mapped const*
get(Key const& k) const
{
std::lock_guard lock(mutex_);
auto it = data_.find(k);
return it == data_.end() ? nullptr : &it->second;
}
template <class... Args>
Mapped&
put(Key const& k, Args&&... args)
{
std::lock_guard lock(mutex_);
auto [it, inserted] = data_.try_emplace(k, std::forward<Args>(args)...);
if (!inserted)
it->second = Mapped(std::forward<Args>(args)...);
return it->second;
}
bool
contains(Key const& k) const
{
std::lock_guard lock(mutex_);
return data_.find(k) != data_.end();
}
std::size_t
size() const noexcept
{
std::lock_guard lock(mutex_);
return data_.size();
}
bool
empty() const noexcept
{
std::lock_guard lock(mutex_);
return data_.empty();
}
void
reserve(std::size_t n)
{
std::lock_guard lock(mutex_);
data_.reserve(n);
}
void
rehash(std::size_t n)
{
std::lock_guard lock(mutex_);
data_.rehash(n);
}
std::size_t
eraseBefore(Key const& cutoff)
{
std::lock_guard lock(mutex_);
auto const before = data_.size();
std::erase_if(data_, [&](auto const& kv) { return kv.first < cutoff; });
return before - data_.size();
}
private:
std::unordered_map<Key, Mapped> data_;
mutable std::mutex mutex_;
};
} // namespace ripple
#endif // RIPPLE_APP_LEDGER_INDEX_MAP_H_INCLUDED

View File

@@ -88,10 +88,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
// Iterate the state and print all NFTokenPages. // Iterate the state and print all NFTokenPages.
if (!jrr.isMember(jss::result) || if (!jrr.isMember(jss::result) ||
@@ -413,10 +411,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
Json::Value& state = jrr[jss::result][jss::state]; Json::Value& state = jrr[jss::result][jss::state];
@@ -460,10 +456,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
Json::Value& state = jrr[jss::result][jss::state]; Json::Value& state = jrr[jss::result][jss::state];
@@ -1235,10 +1229,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
Json::Value& state = jrr[jss::result][jss::state]; Json::Value& state = jrr[jss::result][jss::state];

View File

@@ -47,10 +47,8 @@ class NFTokenDir_test : public beast::unit_test::suite
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
// Iterate the state and print all NFTokenPages. // Iterate the state and print all NFTokenPages.
if (!jrr.isMember(jss::result) || if (!jrr.isMember(jss::result) ||

View File

@@ -592,10 +592,8 @@ private:
jvParams[field] = value; jvParams[field] = value;
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
jvParams[jss::type] = jss::oracle; jvParams[jss::type] = jss::oracle;
Json::Value jrr = env.rpc( Json::Value jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams));
"ledger_data",
boost::lexical_cast<std::string>(jvParams));
BEAST_EXPECT(jrr[jss::result][jss::state].size() == 2); BEAST_EXPECT(jrr[jss::result][jss::state].size() == 2);
}; };
verifyLedgerData(jss::ledger_index, index); verifyLedgerData(jss::ledger_index, index);

View File

@@ -3081,16 +3081,23 @@ public:
env.fund(XRP(1000000), alice); env.fund(XRP(1000000), alice);
env.close(); env.close();
auto const withQueue = Json::Value withQueue;
R"({ "account": ")" + alice.human() + R"(", "queue": true })"; withQueue[jss::account] = alice.human();
auto const withoutQueue = R"({ "account": ")" + alice.human() + R"("})"; withQueue[jss::queue] = true;
auto const prevLedgerWithQueue = R"({ "account": ")" + alice.human() +
R"(", "queue": true, "ledger_index": 3 })"; Json::Value withoutQueue;
withoutQueue[jss::account] = alice.human();
Json::Value prevLedgerWithQueue;
prevLedgerWithQueue[jss::account] = alice.human();
prevLedgerWithQueue[jss::queue] = true;
prevLedgerWithQueue[jss::ledger_index] = 3;
BEAST_EXPECT(env.current()->info().seq > 3); BEAST_EXPECT(env.current()->info().seq > 3);
{ {
// account_info without the "queue" argument. // account_info without the "queue" argument.
auto const info = env.rpc("json", "account_info", withoutQueue); auto const info =
env.rpc("json", "account_info", to_string(withoutQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3098,7 +3105,8 @@ public:
} }
{ {
// account_info with the "queue" argument. // account_info with the "queue" argument.
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3120,7 +3128,8 @@ public:
checkMetrics(*this, env, 0, 6, 4, 3); checkMetrics(*this, env, 0, 6, 4, 3);
{ {
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3149,7 +3158,8 @@ public:
checkMetrics(*this, env, 4, 6, 4, 3); checkMetrics(*this, env, 4, 6, 4, 3);
{ {
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3212,7 +3222,8 @@ public:
checkMetrics(*this, env, 1, 8, 5, 4); checkMetrics(*this, env, 1, 8, 5, 4);
{ {
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3276,7 +3287,8 @@ public:
checkMetrics(*this, env, 1, 8, 5, 4); checkMetrics(*this, env, 1, 8, 5, 4);
{ {
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -3344,7 +3356,7 @@ public:
{ {
auto const info = auto const info =
env.rpc("json", "account_info", prevLedgerWithQueue); env.rpc("json", "account_info", to_string(prevLedgerWithQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
RPC::contains_error(info[jss::result])); RPC::contains_error(info[jss::result]));
@@ -3356,7 +3368,8 @@ public:
checkMetrics(*this, env, 0, 10, 0, 5); checkMetrics(*this, env, 0, 10, 0, 5);
{ {
auto const info = env.rpc("json", "account_info", withQueue); auto const info =
env.rpc("json", "account_info", to_string(withQueue));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));

View File

@@ -411,7 +411,7 @@ Env::sign_and_submit(JTx const& jt, Json::Value params)
if (params.isNull()) if (params.isNull())
{ {
// Use the command line interface // Use the command line interface
auto const jv = boost::lexical_cast<std::string>(jt.jv); auto const jv = to_string(jt.jv);
jr = rpc("submit", passphrase, jv); jr = rpc("submit", passphrase, jv);
} }
else else

View File

@@ -43,9 +43,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
params[jss::account] = Account{"bob"}.human(); params[jss::account] = Account{"bob"}.human();
params[jss::ledger_hash] = 1; params[jss::ledger_hash] = 1;
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString"); BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString");
} }
@@ -107,9 +105,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
params[jss::account] = params[jss::account] =
"llIIOO"; // these are invalid in bitcoin alphabet "llIIOO"; // these are invalid in bitcoin alphabet
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error] == "actMalformed");
BEAST_EXPECT(result[jss::error_message] == "Account malformed."); BEAST_EXPECT(result[jss::error_message] == "Account malformed.");
} }
@@ -119,9 +115,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
Json::Value params; Json::Value params;
params[jss::account] = "Bob"; params[jss::account] = "Bob";
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error] == "actMalformed");
BEAST_EXPECT(result[jss::error_message] == "Account malformed."); BEAST_EXPECT(result[jss::error_message] == "Account malformed.");
} }
@@ -130,9 +124,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
Json::Value params; Json::Value params;
params[jss::account] = Account{"bob"}.human(); params[jss::account] = Account{"bob"}.human();
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "actNotFound"); BEAST_EXPECT(result[jss::error] == "actNotFound");
BEAST_EXPECT(result[jss::error_message] == "Account not found."); BEAST_EXPECT(result[jss::error_message] == "Account not found.");
} }
@@ -161,9 +153,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
Json::Value params; Json::Value params;
params[jss::account] = alice.human(); params[jss::account] = alice.human();
auto result = env.rpc( auto result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
auto arrayCheck = auto arrayCheck =
[&result]( [&result](
@@ -189,9 +179,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
// send_currencies should be populated now // send_currencies should be populated now
result = env.rpc( result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies));
BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies));
@@ -203,9 +191,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
BEAST_EXPECT( BEAST_EXPECT(
l[jss::freeze].asBool() == (l[jss::currency] == "USD")); l[jss::freeze].asBool() == (l[jss::currency] == "USD"));
result = env.rpc( result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies));
BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies));
// clear the freeze // clear the freeze
@@ -215,9 +201,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
env(pay(gw, alice, gw["USA"](50))); env(pay(gw, alice, gw["USA"](50)));
// USA should now be missing from receive_currencies // USA should now be missing from receive_currencies
result = env.rpc( result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
decltype(gwCurrencies) gwCurrenciesNoUSA( decltype(gwCurrencies) gwCurrenciesNoUSA(
gwCurrencies.begin() + 1, gwCurrencies.end()); gwCurrencies.begin() + 1, gwCurrencies.end());
BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrenciesNoUSA)); BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrenciesNoUSA));
@@ -228,9 +212,7 @@ class AccountCurrencies_test : public beast::unit_test::suite
env(trust(gw, alice["USA"](100))); env(trust(gw, alice["USA"](100)));
env(pay(alice, gw, alice["USA"](200))); env(pay(alice, gw, alice["USA"](200)));
result = env.rpc( result = env.rpc(
"json", "json", "account_currencies", to_string(params))[jss::result];
"account_currencies",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies));
BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrenciesNoUSA)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrenciesNoUSA));
} }

View File

@@ -58,10 +58,10 @@ public:
{ {
// account_info with an account that's not in the ledger. // account_info with an account that's not in the ledger.
Account const bogie{"bogie"}; Account const bogie{"bogie"};
auto const info = env.rpc( Json::Value params;
"json", params[jss::account] = bogie.human();
"account_info", auto const info =
R"({ "account": ")" + bogie.human() + R"("})"); env.rpc("json", "account_info", to_string(params));
BEAST_EXPECT( BEAST_EXPECT(
info[jss::result][jss::error_code] == rpcACT_NOT_FOUND); info[jss::result][jss::error_code] == rpcACT_NOT_FOUND);
BEAST_EXPECT( BEAST_EXPECT(
@@ -128,16 +128,18 @@ public:
Account const alice{"alice"}; Account const alice{"alice"};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
auto const withoutSigners = Json::Value withoutSigners;
std::string("{ ") + "\"account\": \"" + alice.human() + "\"}"; withoutSigners[jss::account] = alice.human();
auto const withSigners = std::string("{ ") + "\"account\": \"" + Json::Value withSigners;
alice.human() + "\", " + "\"signer_lists\": true }"; withSigners[jss::account] = alice.human();
withSigners[jss::signer_lists] = true;
// Alice has no SignerList yet. // Alice has no SignerList yet.
{ {
// account_info without the "signer_lists" argument. // account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners); auto const info =
env.rpc("json", "account_info", to_string(withoutSigners));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -146,7 +148,8 @@ public:
} }
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -164,7 +167,8 @@ public:
env(smallSigners); env(smallSigners);
{ {
// account_info without the "signer_lists" argument. // account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners); auto const info =
env.rpc("json", "account_info", to_string(withoutSigners));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -173,7 +177,8 @@ public:
} }
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -216,7 +221,8 @@ public:
env(bigSigners); env(bigSigners);
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT( BEAST_EXPECT(
info.isMember(jss::result) && info.isMember(jss::result) &&
info[jss::result].isMember(jss::account_data)); info[jss::result].isMember(jss::account_data));
@@ -250,12 +256,14 @@ public:
Account const alice{"alice"}; Account const alice{"alice"};
env.fund(XRP(1000), alice); env.fund(XRP(1000), alice);
auto const withoutSigners = std::string("{ ") + Json::Value withoutSigners;
"\"api_version\": 2, \"account\": \"" + alice.human() + "\"}"; withoutSigners[jss::api_version] = 2;
withoutSigners[jss::account] = alice.human();
auto const withSigners = std::string("{ ") + Json::Value withSigners;
"\"api_version\": 2, \"account\": \"" + alice.human() + "\", " + withSigners[jss::api_version] = 2;
"\"signer_lists\": true }"; withSigners[jss::account] = alice.human();
withSigners[jss::signer_lists] = true;
auto const withSignersAsString = std::string("{ ") + auto const withSignersAsString = std::string("{ ") +
"\"api_version\": 2, \"account\": \"" + alice.human() + "\", " + "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
@@ -264,13 +272,15 @@ public:
// Alice has no SignerList yet. // Alice has no SignerList yet.
{ {
// account_info without the "signer_lists" argument. // account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners); auto const info =
env.rpc("json", "account_info", to_string(withoutSigners));
BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(info.isMember(jss::result));
BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists)); BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
} }
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(info.isMember(jss::result));
auto const& data = info[jss::result]; auto const& data = info[jss::result];
BEAST_EXPECT(data.isMember(jss::signer_lists)); BEAST_EXPECT(data.isMember(jss::signer_lists));
@@ -286,13 +296,15 @@ public:
env(smallSigners); env(smallSigners);
{ {
// account_info without the "signer_lists" argument. // account_info without the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withoutSigners); auto const info =
env.rpc("json", "account_info", to_string(withoutSigners));
BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(info.isMember(jss::result));
BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists)); BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
} }
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(info.isMember(jss::result));
auto const& data = info[jss::result]; auto const& data = info[jss::result];
BEAST_EXPECT(data.isMember(jss::signer_lists)); BEAST_EXPECT(data.isMember(jss::signer_lists));
@@ -340,7 +352,8 @@ public:
env(bigSigners); env(bigSigners);
{ {
// account_info with the "signer_lists" argument. // account_info with the "signer_lists" argument.
auto const info = env.rpc("json", "account_info", withSigners); auto const info =
env.rpc("json", "account_info", to_string(withSigners));
BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(info.isMember(jss::result));
auto const& data = info[jss::result]; auto const& data = info[jss::result];
BEAST_EXPECT(data.isMember(jss::signer_lists)); BEAST_EXPECT(data.isMember(jss::signer_lists));
@@ -567,10 +580,10 @@ public:
auto getAccountFlag = [&env]( auto getAccountFlag = [&env](
std::string_view fName, std::string_view fName,
Account const& account) { Account const& account) {
auto const info = env.rpc( Json::Value params;
"json", params[jss::account] = account.human();
"account_info", auto const info =
R"({"account" : ")" + account.human() + R"("})"); env.rpc("json", "account_info", to_string(params));
std::optional<bool> res; std::optional<bool> res;
if (info[jss::result][jss::status] == "success" && if (info[jss::result][jss::status] == "success" &&

File diff suppressed because it is too large Load Diff

View File

@@ -309,10 +309,8 @@ class Feature_test : public beast::unit_test::suite
params[jss::feature] = params[jss::feature] =
"1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD" "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD"
"EF"; "EF";
auto const result = env.rpc( auto const result =
"json", env.rpc("json", "feature", to_string(params))[jss::result];
"feature",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECTS( BEAST_EXPECTS(
result[jss::error] == "badFeature", result.toStyledString()); result[jss::error] == "badFeature", result.toStyledString());
BEAST_EXPECT( BEAST_EXPECT(
@@ -326,10 +324,8 @@ class Feature_test : public beast::unit_test::suite
"A7"; "A7";
// invalid param // invalid param
params[jss::vetoed] = true; params[jss::vetoed] = true;
auto const result = env.rpc( auto const result =
"json", env.rpc("json", "feature", to_string(params))[jss::result];
"feature",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECTS( BEAST_EXPECTS(
result[jss::error] == "noPermission", result[jss::error] == "noPermission",
result[jss::error].asString()); result[jss::error].asString());
@@ -344,10 +340,8 @@ class Feature_test : public beast::unit_test::suite
"37"; "37";
Json::Value params; Json::Value params;
params[jss::feature] = feature; params[jss::feature] = feature;
auto const result = env.rpc( auto const result =
"json", env.rpc("json", "feature", to_string(params))[jss::result];
"feature",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result.isMember(feature)); BEAST_EXPECT(result.isMember(feature));
auto const amendmentResult = result[feature]; auto const amendmentResult = result[feature];
BEAST_EXPECT(amendmentResult[jss::enabled].asBool() == false); BEAST_EXPECT(amendmentResult[jss::enabled].asBool() == false);

View File

@@ -63,9 +63,7 @@ public:
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
{ {
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT( BEAST_EXPECT(
jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].isIntegral() &&
jrr[jss::ledger_current_index].asInt() > 0); jrr[jss::ledger_current_index].asInt() > 0);
@@ -78,9 +76,7 @@ public:
{ {
jvParams[jss::limit] = max_limit + delta; jvParams[jss::limit] = max_limit + delta;
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(checkArraySize( BEAST_EXPECT(checkArraySize(
jrr[jss::state], jrr[jss::state],
(delta > 0 && !asAdmin) ? max_limit : max_limit + delta)); (delta > 0 && !asAdmin) ? max_limit : max_limit + delta));
@@ -109,10 +105,8 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = true; jvParams[jss::binary] = true;
auto const jrr = env.rpc( auto const jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT( BEAST_EXPECT(
jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].isIntegral() &&
jrr[jss::ledger_current_index].asInt() > 0); jrr[jss::ledger_current_index].asInt() > 0);
@@ -137,9 +131,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::limit] = "0"; // NOT an integer jvParams[jss::limit] = "0"; // NOT an integer
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT( BEAST_EXPECT(
@@ -152,9 +144,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::marker] = "NOT_A_MARKER"; jvParams[jss::marker] = "NOT_A_MARKER";
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT( BEAST_EXPECT(
@@ -167,9 +157,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::marker] = 1; jvParams[jss::marker] = 1;
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT( BEAST_EXPECT(
@@ -182,9 +170,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_index] = 10u; jvParams[jss::ledger_index] = 10u;
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
@@ -213,27 +199,20 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false; jvParams[jss::binary] = false;
auto jrr = env.rpc( auto jrr =
"json", env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
auto const total_count = jrr[jss::state].size(); auto const total_count = jrr[jss::state].size();
// now make request with a limit and loop until we get all // now make request with a limit and loop until we get all
jvParams[jss::limit] = 5; jvParams[jss::limit] = 5;
jrr = env.rpc( jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
"json",
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(checkMarker(jrr)); BEAST_EXPECT(checkMarker(jrr));
auto running_total = jrr[jss::state].size(); auto running_total = jrr[jss::state].size();
while (jrr.isMember(jss::marker)) while (jrr.isMember(jss::marker))
{ {
jvParams[jss::marker] = jrr[jss::marker]; jvParams[jss::marker] = jrr[jss::marker];
jrr = env.rpc( jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
running_total += jrr[jss::state].size(); running_total += jrr[jss::state].size();
} }
BEAST_EXPECT(running_total == total_count); BEAST_EXPECT(running_total == total_count);
@@ -253,9 +232,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_index] = "closed"; jvParams[jss::ledger_index] = "closed";
auto jrr = env.rpc( auto jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
if (BEAST_EXPECT(jrr.isMember(jss::ledger))) if (BEAST_EXPECT(jrr.isMember(jss::ledger)))
BEAST_EXPECT( BEAST_EXPECT(
jrr[jss::ledger][jss::ledger_hash] == jrr[jss::ledger][jss::ledger_hash] ==
@@ -267,9 +244,7 @@ public:
jvParams[jss::ledger_index] = "closed"; jvParams[jss::ledger_index] = "closed";
jvParams[jss::binary] = true; jvParams[jss::binary] = true;
auto jrr = env.rpc( auto jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
if (BEAST_EXPECT(jrr.isMember(jss::ledger))) if (BEAST_EXPECT(jrr.isMember(jss::ledger)))
{ {
auto data = auto data =
@@ -288,9 +263,7 @@ public:
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::binary] = true; jvParams[jss::binary] = true;
auto jrr = env.rpc( auto jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(!jrr[jss::ledger].isMember(jss::ledger_data)); BEAST_EXPECT(!jrr[jss::ledger].isMember(jss::ledger_data));
} }
@@ -319,9 +292,7 @@ public:
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::type] = type; jvParams[jss::type] = type;
return env.rpc( return env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
}; };
// Assert that state is an empty array. // Assert that state is an empty array.
@@ -500,9 +471,7 @@ public:
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jvParams[jss::type] = "misspelling"; jvParams[jss::type] = "misspelling";
auto const jrr = env.rpc( auto const jrr = env.rpc(
"json", "json", "ledger_data", to_string(jvParams))[jss::result];
"ledger_data",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember("error")); BEAST_EXPECT(jrr.isMember("error"));
BEAST_EXPECT(jrr["error"] == "invalidParams"); BEAST_EXPECT(jrr["error"] == "invalidParams");
BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'."); BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'.");

View File

@@ -287,56 +287,39 @@ class LedgerRPC_test : public beast::unit_test::suite
// access via the legacy ledger field, keyword index values // access via the legacy ledger field, keyword index values
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger] = "closed"; jvParams[jss::ledger] = "closed";
auto jrr = env.rpc( auto jrr =
"json", env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5");
jvParams[jss::ledger] = "validated"; jvParams[jss::ledger] = "validated";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5");
jvParams[jss::ledger] = "current"; jvParams[jss::ledger] = "current";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "6"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "6");
// ask for a bad ledger keyword // ask for a bad ledger keyword
jvParams[jss::ledger] = "invalid"; jvParams[jss::ledger] = "invalid";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed");
// numeric index // numeric index
jvParams[jss::ledger] = 4; jvParams[jss::ledger] = 4;
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "4"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "4");
// numeric index - out of range // numeric index - out of range
jvParams[jss::ledger] = 20; jvParams[jss::ledger] = 20;
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
} }
@@ -348,29 +331,21 @@ class LedgerRPC_test : public beast::unit_test::suite
// access via the ledger_hash field // access via the ledger_hash field
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_hash] = hash3; jvParams[jss::ledger_hash] = hash3;
auto jrr = env.rpc( auto jrr =
"json", env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "3"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "3");
// extra leading hex chars in hash are not allowed // extra leading hex chars in hash are not allowed
jvParams[jss::ledger_hash] = "DEADBEEF" + hash3; jvParams[jss::ledger_hash] = "DEADBEEF" + hash3;
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed");
// request with non-string ledger_hash // request with non-string ledger_hash
jvParams[jss::ledger_hash] = 2; jvParams[jss::ledger_hash] = 2;
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashNotString"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashNotString");
@@ -378,10 +353,7 @@ class LedgerRPC_test : public beast::unit_test::suite
jvParams[jss::ledger_hash] = jvParams[jss::ledger_hash] =
"2E81FC6EC0DD943197EGC7E3FBE9AE30" "2E81FC6EC0DD943197EGC7E3FBE9AE30"
"7F2775F2F7485BB37307984C3C0F2340"; "7F2775F2F7485BB37307984C3C0F2340";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed");
@@ -389,10 +361,7 @@ class LedgerRPC_test : public beast::unit_test::suite
jvParams[jss::ledger_hash] = jvParams[jss::ledger_hash] =
"8C3EEDB3124D92E49E75D81A8826A2E6" "8C3EEDB3124D92E49E75D81A8826A2E6"
"5A75FD71FC3FD6F36FEB803C5F1D812D"; "5A75FD71FC3FD6F36FEB803C5F1D812D";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
} }
@@ -401,39 +370,28 @@ class LedgerRPC_test : public beast::unit_test::suite
// access via the ledger_index field, keyword index values // access via the ledger_index field, keyword index values
Json::Value jvParams; Json::Value jvParams;
jvParams[jss::ledger_index] = "closed"; jvParams[jss::ledger_index] = "closed";
auto jrr = env.rpc( auto jrr =
"json", env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5");
BEAST_EXPECT(jrr.isMember(jss::ledger_index)); BEAST_EXPECT(jrr.isMember(jss::ledger_index));
jvParams[jss::ledger_index] = "validated"; jvParams[jss::ledger_index] = "validated";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5");
jvParams[jss::ledger_index] = "current"; jvParams[jss::ledger_index] = "current";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "6"); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "6");
BEAST_EXPECT(jrr.isMember(jss::ledger_current_index)); BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
// ask for a bad ledger keyword // ask for a bad ledger keyword
jvParams[jss::ledger_index] = "invalid"; jvParams[jss::ledger_index] = "invalid";
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed");
@@ -441,10 +399,8 @@ class LedgerRPC_test : public beast::unit_test::suite
for (auto i : {1, 2, 3, 4, 5, 6}) for (auto i : {1, 2, 3, 4, 5, 6})
{ {
jvParams[jss::ledger_index] = i; jvParams[jss::ledger_index] = i;
jrr = env.rpc( jrr =
"json", env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger));
if (i < 6) if (i < 6)
BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
@@ -454,10 +410,7 @@ class LedgerRPC_test : public beast::unit_test::suite
// numeric index - out of range // numeric index - out of range
jvParams[jss::ledger_index] = 7; jvParams[jss::ledger_index] = 7;
jrr = env.rpc( jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result];
"json",
"ledger",
boost::lexical_cast<std::string>(jvParams))[jss::result];
BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
} }

View File

@@ -59,9 +59,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
Json::Value params; Json::Value params;
params[jss::account] = alice.human(); params[jss::account] = alice.human();
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_message] == "Missing field 'role'."); BEAST_EXPECT(result[jss::error_message] == "Missing field 'role'.");
} }
@@ -92,9 +90,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::account] = alice.human(); params[jss::account] = alice.human();
params[jss::role] = "not_a_role"; params[jss::role] = "not_a_role";
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_message] == "Invalid field 'role'."); BEAST_EXPECT(result[jss::error_message] == "Invalid field 'role'.");
} }
@@ -105,9 +101,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::role] = "user"; params[jss::role] = "user";
params[jss::limit] = -1; params[jss::limit] = -1;
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT( BEAST_EXPECT(
result[jss::error_message] == result[jss::error_message] ==
@@ -120,9 +114,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::role] = "user"; params[jss::role] = "user";
params[jss::ledger_hash] = 1; params[jss::ledger_hash] = 1;
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error] == "invalidParams");
BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString"); BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString");
} }
@@ -133,9 +125,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::role] = "user"; params[jss::role] = "user";
params[jss::ledger] = "current"; params[jss::ledger] = "current";
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "actNotFound"); BEAST_EXPECT(result[jss::error] == "actNotFound");
BEAST_EXPECT(result[jss::error_message] == "Account not found."); BEAST_EXPECT(result[jss::error_message] == "Account not found.");
} }
@@ -147,9 +137,7 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::role] = "user"; params[jss::role] = "user";
params[jss::ledger] = "current"; params[jss::ledger] = "current";
auto const result = env.rpc( auto const result = env.rpc(
"json", "json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error] == "actMalformed");
BEAST_EXPECT(result[jss::error_message] == "Account malformed."); BEAST_EXPECT(result[jss::error_message] == "Account malformed.");
} }
@@ -184,10 +172,8 @@ class NoRippleCheck_test : public beast::unit_test::suite
params[jss::account] = alice.human(); params[jss::account] = alice.human();
params[jss::role] = (user ? "user" : "gateway"); params[jss::role] = (user ? "user" : "gateway");
params[jss::ledger] = "current"; params[jss::ledger] = "current";
auto result = env.rpc( auto result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
auto const pa = result["problems"]; auto const pa = result["problems"];
if (!BEAST_EXPECT(pa.isArray())) if (!BEAST_EXPECT(pa.isArray()))
@@ -221,10 +207,8 @@ class NoRippleCheck_test : public beast::unit_test::suite
// now make a second request asking for the relevant transactions this // now make a second request asking for the relevant transactions this
// time. // time.
params[jss::transactions] = true; params[jss::transactions] = true;
result = env.rpc( result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
if (!BEAST_EXPECT(result[jss::transactions].isArray())) if (!BEAST_EXPECT(result[jss::transactions].isArray()))
return; return;
@@ -343,43 +327,33 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite
params[jss::account] = alice.human(); params[jss::account] = alice.human();
params[jss::role] = "user"; params[jss::role] = "user";
params[jss::ledger] = "current"; params[jss::ledger] = "current";
auto result = env.rpc( auto result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result["problems"].size() == 301); BEAST_EXPECT(result["problems"].size() == 301);
// one below minimum // one below minimum
params[jss::limit] = 9; params[jss::limit] = 9;
result = env.rpc( result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result["problems"].size() == (admin ? 10 : 11)); BEAST_EXPECT(result["problems"].size() == (admin ? 10 : 11));
// at minimum // at minimum
params[jss::limit] = 10; params[jss::limit] = 10;
result = env.rpc( result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result["problems"].size() == 11); BEAST_EXPECT(result["problems"].size() == 11);
// at max // at max
params[jss::limit] = 400; params[jss::limit] = 400;
result = env.rpc( result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result["problems"].size() == 401); BEAST_EXPECT(result["problems"].size() == 401);
// at max+1 // at max+1
params[jss::limit] = 401; params[jss::limit] = 401;
result = env.rpc( result =
"json", env.rpc("json", "noripple_check", to_string(params))[jss::result];
"noripple_check",
boost::lexical_cast<std::string>(params))[jss::result];
BEAST_EXPECT(result["problems"].size() == (admin ? 402 : 401)); BEAST_EXPECT(result["problems"].size() == (admin ? 402 : 401));
} }

View File

@@ -258,15 +258,13 @@ class TransactionEntry_test : public beast::unit_test::suite
Account A2{"A2"}; Account A2{"A2"};
env.fund(XRP(10000), A1); env.fund(XRP(10000), A1);
auto fund_1_tx = auto fund_1_tx = to_string(env.tx()->getTransactionID());
boost::lexical_cast<std::string>(env.tx()->getTransactionID());
BEAST_EXPECT( BEAST_EXPECT(
fund_1_tx == fund_1_tx ==
"F4E9DF90D829A9E8B423FF68C34413E240D8D8BB0EFD080DF08114ED398E2506"); "F4E9DF90D829A9E8B423FF68C34413E240D8D8BB0EFD080DF08114ED398E2506");
env.fund(XRP(10000), A2); env.fund(XRP(10000), A2);
auto fund_2_tx = auto fund_2_tx = to_string(env.tx()->getTransactionID());
boost::lexical_cast<std::string>(env.tx()->getTransactionID());
BEAST_EXPECT( BEAST_EXPECT(
fund_2_tx == fund_2_tx ==
"6853CD8226A05068C951CB1F54889FF4E40C5B440DC1C5BA38F114C4E0B1E705"); "6853CD8226A05068C951CB1F54889FF4E40C5B440DC1C5BA38F114C4E0B1E705");
@@ -308,15 +306,13 @@ class TransactionEntry_test : public beast::unit_test::suite
// the trust tx is actually a payment since the trust method // the trust tx is actually a payment since the trust method
// refunds fees with a payment after TrustSet..so just ignore the type // refunds fees with a payment after TrustSet..so just ignore the type
// in the check below // in the check below
auto trust_tx = auto trust_tx = to_string(env.tx()->getTransactionID());
boost::lexical_cast<std::string>(env.tx()->getTransactionID());
BEAST_EXPECT( BEAST_EXPECT(
trust_tx == trust_tx ==
"C992D97D88FF444A1AB0C06B27557EC54B7F7DA28254778E60238BEA88E0C101"); "C992D97D88FF444A1AB0C06B27557EC54B7F7DA28254778E60238BEA88E0C101");
env(pay(A2, A1, A2["USD"](5))); env(pay(A2, A1, A2["USD"](5)));
auto pay_tx = auto pay_tx = to_string(env.tx()->getTransactionID());
boost::lexical_cast<std::string>(env.tx()->getTransactionID());
env.close(); env.close();
BEAST_EXPECT( BEAST_EXPECT(
pay_tx == pay_tx ==
@@ -362,8 +358,7 @@ class TransactionEntry_test : public beast::unit_test::suite
"2000-01-01T00:00:20Z"); "2000-01-01T00:00:20Z");
env(offer(A2, XRP(100), A2["USD"](1))); env(offer(A2, XRP(100), A2["USD"](1)));
auto offer_tx = auto offer_tx = to_string(env.tx()->getTransactionID());
boost::lexical_cast<std::string>(env.tx()->getTransactionID());
BEAST_EXPECT( BEAST_EXPECT(
offer_tx == offer_tx ==
"5FCC1A27A7664F82A0CC4BE5766FBBB7C560D52B93AA7B550CD33B27AEC7EFFB"); "5FCC1A27A7664F82A0CC4BE5766FBBB7C560D52B93AA7B550CD33B27AEC7EFFB");

View File

@@ -14,5 +14,3 @@ xrpl_add_test(crypto)
target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test) target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test)
xrpl_add_test(net) xrpl_add_test(net)
target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test) target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test)
xrpl_add_test(ledger)
target_link_libraries(xrpl.test.ledger PRIVATE xrpl.imports.test)

View File

@@ -1,210 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <xrpl/ledger/LedgerIndexMap.h>
#include <doctest/doctest.h>
#include <cstdint>
#include <string>
#include <vector>
using namespace ripple;
TEST_SUITE_BEGIN("LedgerIndexMap");
using TestMap = LedgerIndexMap<int, std::string>;
TEST_CASE("Default empty")
{
TestMap m;
CHECK(m.size() == 0);
CHECK(m.empty());
CHECK(m.get(42) == nullptr);
CHECK_FALSE(m.contains(42));
}
TEST_CASE("Operator bracket inserts default")
{
TestMap m;
auto& v = m[10];
CHECK(m.size() == 1);
CHECK(m.contains(10));
CHECK(v.empty());
}
TEST_CASE("Operator bracket, rvalue key")
{
TestMap m;
int k = 7;
auto& v1 = m[std::move(k)];
v1 = "seven";
CHECK(m.size() == 1);
auto* got = m.get(7);
REQUIRE(got != nullptr);
CHECK(*got == "seven");
}
TEST_CASE("Insert through put")
{
TestMap m;
auto& v = m.put(20, "twenty");
CHECK(v == "twenty");
auto* got = m.get(20);
REQUIRE(got != nullptr);
CHECK(*got == "twenty");
CHECK(m.size() == 1);
}
TEST_CASE("Overwrite existing key with put")
{
TestMap m;
m.put(5, "five");
CHECK(m.size() == 1);
m.put(5, "FIVE");
CHECK(m.size() == 1);
auto* got = m.get(5);
REQUIRE(got != nullptr);
CHECK(*got == "FIVE");
}
TEST_CASE("Once found, one not found")
{
TestMap m;
m.put(1, "one");
CHECK(m.get(1) != nullptr);
CHECK(m.get(2) == nullptr);
}
TEST_CASE("Try eraseBefore - nothing to do")
{
TestMap m;
m.put(10, "a");
m.put(11, "b");
m.put(12, "c");
CHECK(m.eraseBefore(10) == 0);
CHECK(m.size() == 3);
CHECK(m.contains(10));
CHECK(m.contains(11));
CHECK(m.contains(12));
}
TEST_CASE("eraseBefore - removes several entries")
{
TestMap m;
m.put(10, "a");
m.put(11, "b");
m.put(12, "c");
m.put(13, "d");
CHECK(m.eraseBefore(12) == 2);
CHECK_FALSE(m.contains(10));
CHECK_FALSE(m.contains(11));
CHECK(m.contains(12));
CHECK(m.contains(13));
CHECK(m.size() == 2);
}
TEST_CASE("eraseBefore - removes all entries")
{
TestMap m;
m.put(1, "x");
m.put(2, "y");
CHECK(m.eraseBefore(1000) == 2);
CHECK(m.size() == 0);
CHECK(m.empty());
}
TEST_CASE("eraseBefore - same call, second time nothing to do")
{
TestMap m;
m.put(10, "a");
m.put(11, "b");
m.put(12, "c");
CHECK(m.eraseBefore(12) == 2);
CHECK(m.contains(12));
CHECK(m.eraseBefore(12) == 0);
CHECK(m.size() == 1);
}
TEST_CASE("eraseBefore - single entry removed")
{
TestMap m;
m.put(10, "v1");
m.put(10, "v2");
m.put(10, "v3");
CHECK(m.size() == 1);
CHECK(m.eraseBefore(11) == 1);
CHECK(m.size() == 0);
}
TEST_CASE("eraseBefore - outlier still removed in one call")
{
TestMap m;
m.put(10, "a");
m.put(12, "c");
m.put(11, "b"); // out-of-order insert
CHECK(m.eraseBefore(12) == 2); // removes 10 and 11
CHECK_FALSE(m.contains(10));
CHECK_FALSE(m.contains(11));
CHECK(m.contains(12));
CHECK(m.size() == 1);
}
TEST_CASE("eraseBefore - erase in two steps (one first, then some more)")
{
TestMap m;
for (int k : {10, 11, 12, 13})
m.put(k, std::to_string(k));
CHECK(m.eraseBefore(11) == 1);
CHECK_FALSE(m.contains(10));
CHECK(m.size() == 3);
CHECK(m.eraseBefore(13) == 2);
CHECK_FALSE(m.contains(11));
CHECK_FALSE(m.contains(12));
CHECK(m.contains(13));
CHECK(m.size() == 1);
}
TEST_CASE("rehash does not lose entries")
{
TestMap m;
for (int k = 0; k < 16; ++k)
m.put(k, "v" + std::to_string(k));
m.reserve(64);
m.rehash(32);
for (int k = 0; k < 16; ++k)
{
auto* v = m.get(k);
REQUIRE(v != nullptr);
CHECK(*v == "v" + std::to_string(k));
}
CHECK(m.eraseBefore(8) == 8);
for (int k = 0; k < 8; ++k)
CHECK_FALSE(m.contains(k));
for (int k = 8; k < 16; ++k)
CHECK(m.contains(k));
}
TEST_SUITE_END();

View File

@@ -1,2 +0,0 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

View File

@@ -27,6 +27,8 @@
namespace ripple { namespace ripple {
// FIXME: Need to clean up ledgers by index at some point
LedgerHistory::LedgerHistory( LedgerHistory::LedgerHistory(
beast::insight::Collector::ptr const& collector, beast::insight::Collector::ptr const& collector,
Application& app) Application& app)
@@ -45,7 +47,6 @@ LedgerHistory::LedgerHistory(
std::chrono::minutes{5}, std::chrono::minutes{5},
stopwatch(), stopwatch(),
app_.journal("TaggedCache")) app_.journal("TaggedCache"))
, mLedgersByIndex(512)
, j_(app.journal("LedgerHistory")) , j_(app.journal("LedgerHistory"))
{ {
} }
@@ -62,6 +63,8 @@ LedgerHistory::insert(
ledger->stateMap().getHash().isNonZero(), ledger->stateMap().getHash().isNonZero(),
"ripple::LedgerHistory::insert : nonzero hash"); "ripple::LedgerHistory::insert : nonzero hash");
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
bool const alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache( bool const alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache(
ledger->info().hash, ledger); ledger->info().hash, ledger);
if (validated) if (validated)
@@ -73,19 +76,26 @@ LedgerHistory::insert(
LedgerHash LedgerHash
LedgerHistory::getLedgerHash(LedgerIndex index) LedgerHistory::getLedgerHash(LedgerIndex index)
{ {
if (auto p = mLedgersByIndex.get(index)) std::unique_lock sl(m_ledgers_by_hash.peekMutex());
return *p; if (auto it = mLedgersByIndex.find(index); it != mLedgersByIndex.end())
return it->second;
return {}; return {};
} }
std::shared_ptr<Ledger const> std::shared_ptr<Ledger const>
LedgerHistory::getLedgerBySeq(LedgerIndex index) LedgerHistory::getLedgerBySeq(LedgerIndex index)
{ {
if (auto p = mLedgersByIndex.get(index))
{ {
uint256 const hash = *p; std::unique_lock sl(m_ledgers_by_hash.peekMutex());
auto it = mLedgersByIndex.find(index);
if (it != mLedgersByIndex.end())
{
uint256 hash = it->second;
sl.unlock();
return getLedgerByHash(hash); return getLedgerByHash(hash);
} }
}
std::shared_ptr<Ledger const> ret = loadByIndex(index, app_); std::shared_ptr<Ledger const> ret = loadByIndex(index, app_);
@@ -98,6 +108,8 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index)
{ {
// Add this ledger to the local tracking by index // Add this ledger to the local tracking by index
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
XRPL_ASSERT( XRPL_ASSERT(
ret->isImmutable(), ret->isImmutable(),
"ripple::LedgerHistory::getLedgerBySeq : immutable result ledger"); "ripple::LedgerHistory::getLedgerBySeq : immutable result ledger");
@@ -446,6 +458,8 @@ LedgerHistory::builtLedger(
XRPL_ASSERT( XRPL_ASSERT(
!hash.isZero(), "ripple::LedgerHistory::builtLedger : nonzero hash"); !hash.isZero(), "ripple::LedgerHistory::builtLedger : nonzero hash");
std::unique_lock sl(m_consensus_validated.peekMutex());
auto entry = std::make_shared<cv_entry>(); auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry); m_consensus_validated.canonicalize_replace_client(index, entry);
@@ -486,6 +500,8 @@ LedgerHistory::validatedLedger(
!hash.isZero(), !hash.isZero(),
"ripple::LedgerHistory::validatedLedger : nonzero hash"); "ripple::LedgerHistory::validatedLedger : nonzero hash");
std::unique_lock sl(m_consensus_validated.peekMutex());
auto entry = std::make_shared<cv_entry>(); auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry); m_consensus_validated.canonicalize_replace_client(index, entry);
@@ -519,38 +535,26 @@ LedgerHistory::validatedLedger(
bool bool
LedgerHistory::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash) LedgerHistory::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
{ {
if (auto cur = mLedgersByIndex.get(ledgerIndex)) std::unique_lock sl(m_ledgers_by_hash.peekMutex());
auto it = mLedgersByIndex.find(ledgerIndex);
if ((it != mLedgersByIndex.end()) && (it->second != ledgerHash))
{ {
if (*cur != ledgerHash) it->second = ledgerHash;
{
mLedgersByIndex.put(ledgerIndex, ledgerHash);
return false; return false;
} }
}
return true; return true;
} }
void void
LedgerHistory::clearLedgerCachePrior(LedgerIndex seq) LedgerHistory::clearLedgerCachePrior(LedgerIndex seq)
{ {
std::size_t hashesCleared = 0;
for (LedgerHash it : m_ledgers_by_hash.getKeys()) for (LedgerHash it : m_ledgers_by_hash.getKeys())
{ {
auto const ledger = getLedgerByHash(it); auto const ledger = getLedgerByHash(it);
if (!ledger || ledger->info().seq < seq) if (!ledger || ledger->info().seq < seq)
{
m_ledgers_by_hash.del(it, false); m_ledgers_by_hash.del(it, false);
++hashesCleared;
} }
}
JLOG(j_.debug()) << "LedgersByHash: cleared " << hashesCleared
<< " entries before seq " << seq << " (total now "
<< m_ledgers_by_hash.size() << ")";
std::size_t const indexesCleared = mLedgersByIndex.eraseBefore(seq);
JLOG(j_.debug()) << "LedgerIndexMap: cleared " << indexesCleared
<< " index entries before seq " << seq << " (total now "
<< mLedgersByIndex.size() << ")";
} }
} // namespace ripple } // namespace ripple

View File

@@ -24,7 +24,6 @@
#include <xrpld/app/main/Application.h> #include <xrpld/app/main/Application.h>
#include <xrpl/beast/insight/Collector.h> #include <xrpl/beast/insight/Collector.h>
#include <xrpl/ledger/LedgerIndexMap.h>
#include <xrpl/protocol/RippleLedgerHash.h> #include <xrpl/protocol/RippleLedgerHash.h>
#include <optional> #include <optional>
@@ -150,8 +149,7 @@ private:
ConsensusValidated m_consensus_validated; ConsensusValidated m_consensus_validated;
// Maps ledger indexes to the corresponding hash. // Maps ledger indexes to the corresponding hash.
ripple::LedgerIndexMap<LedgerIndex, LedgerHash> std::map<LedgerIndex, LedgerHash> mLedgersByIndex; // validated ledgers
mLedgersByIndex; // validated ledgers
beast::Journal j_; beast::Journal j_;
}; };

View File

@@ -600,8 +600,8 @@ ConnectAttempt::processResponse()
JLOG(journal_.info()) << "Cluster name: " << *member; JLOG(journal_.info()) << "Cluster name: " << *member;
} }
auto const result = auto const result = overlay_.peerFinder().activate(
overlay_.peerFinder().activate(slot_, publicKey, !member->empty()); slot_, publicKey, member.has_value());
if (result != PeerFinder::Result::success) if (result != PeerFinder::Result::success)
{ {
std::stringstream ss; std::stringstream ss;

View File

@@ -72,39 +72,23 @@ getAutofillSequence(Json::Value const& tx_json, RPC::JsonContext& context)
} }
static std::optional<Json::Value> static std::optional<Json::Value>
autofillTx(Json::Value& tx_json, RPC::JsonContext& context) autofillSignature(Json::Value& sigObject)
{ {
if (!tx_json.isMember(jss::Fee)) if (!sigObject.isMember(jss::SigningPubKey))
{
// autofill Fee
// Must happen after all the other autofills happen
// Error handling/messaging works better that way
auto feeOrError = RPC::getCurrentNetworkFee(
context.role,
context.app.config(),
context.app.getFeeTrack(),
context.app.getTxQ(),
context.app,
tx_json);
if (feeOrError.isMember(jss::error))
return feeOrError;
tx_json[jss::Fee] = feeOrError;
}
if (!tx_json.isMember(jss::SigningPubKey))
{ {
// autofill SigningPubKey // autofill SigningPubKey
tx_json[jss::SigningPubKey] = ""; sigObject[jss::SigningPubKey] = "";
} }
if (tx_json.isMember(jss::Signers)) if (sigObject.isMember(jss::Signers))
{ {
if (!tx_json[jss::Signers].isArray()) if (!sigObject[jss::Signers].isArray())
return RPC::invalid_field_error("tx.Signers"); return RPC::invalid_field_error("tx.Signers");
// check multisigned signers // check multisigned signers
for (unsigned index = 0; index < tx_json[jss::Signers].size(); index++) for (unsigned index = 0; index < sigObject[jss::Signers].size();
index++)
{ {
auto& signer = tx_json[jss::Signers][index]; auto& signer = sigObject[jss::Signers][index];
if (!signer.isObject() || !signer.isMember(jss::Signer) || if (!signer.isObject() || !signer.isMember(jss::Signer) ||
!signer[jss::Signer].isObject()) !signer[jss::Signer].isObject())
return RPC::invalid_field_error( return RPC::invalid_field_error(
@@ -129,16 +113,41 @@ autofillTx(Json::Value& tx_json, RPC::JsonContext& context)
} }
} }
if (!tx_json.isMember(jss::TxnSignature)) if (!sigObject.isMember(jss::TxnSignature))
{ {
// autofill TxnSignature // autofill TxnSignature
tx_json[jss::TxnSignature] = ""; sigObject[jss::TxnSignature] = "";
} }
else if (tx_json[jss::TxnSignature] != "") else if (sigObject[jss::TxnSignature] != "")
{ {
// Transaction must not be signed // Transaction must not be signed
return rpcError(rpcTX_SIGNED); return rpcError(rpcTX_SIGNED);
} }
return std::nullopt;
}
static std::optional<Json::Value>
autofillTx(Json::Value& tx_json, RPC::JsonContext& context)
{
if (!tx_json.isMember(jss::Fee))
{
// autofill Fee
// Must happen after all the other autofills happen
// Error handling/messaging works better that way
auto feeOrError = RPC::getCurrentNetworkFee(
context.role,
context.app.config(),
context.app.getFeeTrack(),
context.app.getTxQ(),
context.app,
tx_json);
if (feeOrError.isMember(jss::error))
return feeOrError;
tx_json[jss::Fee] = feeOrError;
}
if (auto error = autofillSignature(tx_json))
return *error;
if (!tx_json.isMember(jss::Sequence)) if (!tx_json.isMember(jss::Sequence))
{ {