diff --git a/.github/actions/dependencies/action.yml b/.github/actions/dependencies/action.yml index 17dbc49c45d..d9687ff121e 100644 --- a/.github/actions/dependencies/action.yml +++ b/.github/actions/dependencies/action.yml @@ -16,16 +16,25 @@ runs: conan export external/snappy snappy/1.1.10@ conan export external/rocksdb rocksdb/6.29.5@ conan export external/soci soci/4.0.3@ - - name: try to authenticate to ripple Conan remote - id: remote + - name: add Ripple Conan remote shell: bash run: | + conan remote list + conan remote remove ripple || true # Do not quote the URL. An empty string will be accepted (with # a non-fatal warning), but a missing argument will not. conan remote add ripple ${{ env.CONAN_URL }} --insert 0 - echo outcome=$(conan user --remote ripple ${{ env.CONAN_USERNAME }} \ - --password ${{ env.CONAN_TOKEN }} >&2 && echo success || \ - echo failure) | tee ${GITHUB_OUTPUT} + - name: try to authenticate to Ripple Conan remote + id: remote + shell: bash + run: | + # `conan user` implicitly uses the environment variables + # CONAN_LOGIN_USERNAME_ and CONAN_PASSWORD_. + # https://docs.conan.io/1/reference/commands/misc/user.html#using-environment-variables + # https://docs.conan.io/1/reference/env_vars.html#conan-login-username-conan-login-username-remote-name + # https://docs.conan.io/1/reference/env_vars.html#conan-password-conan-password-remote-name + echo outcome=$(conan user --remote ripple --password >&2 \ + && echo success || echo failure) | tee ${GITHUB_OUTPUT} - name: list missing binaries id: binaries shell: bash diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 802748e84f0..8c915ec00ff 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -8,7 +8,7 @@ jobs: env: CLANG_VERSION: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install clang-format run: | codename=$( lsb_release --codename --short ) @@ -30,7 +30,7 @@ jobs: git diff --exit-code | tee "clang-format.patch" - name: Upload patch if: failure() && steps.assert.outcome == 'failure' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 continue-on-error: true with: name: clang-format.patch diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 6607ae59d42..10a1465192a 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -13,11 +13,10 @@ jobs: runs-on: ubuntu-latest permissions: contents: write - container: - image: docker://rippleci/rippled-ci-builder:2944b78d22db + container: rippleci/rippled-build-ubuntu:aaf5e3e steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: check environment run: | echo ${PATH} | tr ':' '\n' diff --git a/.github/workflows/levelization.yml b/.github/workflows/levelization.yml index 3128513f667..285e810ba9a 100644 --- a/.github/workflows/levelization.yml +++ b/.github/workflows/levelization.yml @@ -8,7 +8,7 @@ jobs: env: CLANG_VERSION: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check levelization run: Builds/levelization/levelization.sh - name: Check for differences @@ -18,7 +18,7 @@ jobs: git diff --exit-code | tee "levelization.patch" - name: Upload patch if: failure() && steps.assert.outcome == 'failure' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 continue-on-error: true with: name: levelization.patch diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 3462939c987..566fae55c44 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -22,28 +22,32 @@ jobs: NUM_PROCESSORS: 12 steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: install Conan + run: | + brew install conan@1 + echo '/opt/homebrew/opt/conan@1/bin' >> $GITHUB_PATH - name: install Ninja if: matrix.generator == 'Ninja' run: brew install ninja - name: check environment run: | + env | sort echo ${PATH} | tr ':' '\n' python --version conan --version cmake --version - env | sort - name: configure Conan run : | - conan profile get env.CXXFLAGS default || true + conan profile new default --detect || true + conan profile update settings.compiler.cppstd=20 default conan profile update 'conf.tools.build:cxxflags+=["-DBOOST_ASIO_DISABLE_CONCEPTS"]' default - conan remote remove ripple - name: build dependencies uses: ./.github/actions/dependencies env: CONAN_URL: http://18.143.149.228:8081/artifactory/api/conan/conan-non-prod - CONAN_USERNAME: ${{ secrets.CONAN_USERNAME }} - CONAN_TOKEN: ${{ secrets.CONAN_TOKEN }} + CONAN_LOGIN_USERNAME_RIPPLE: ${{ secrets.CONAN_USERNAME }} + CONAN_PASSWORD_RIPPLE: ${{ secrets.CONAN_TOKEN }} with: configuration: ${{ matrix.configuration }} - name: build diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 97edbeb17f3..e213599fc14 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -54,7 +54,7 @@ jobs: build_dir: .build steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: check environment run: | echo ${PATH} | tr ':' '\n' @@ -78,8 +78,8 @@ jobs: uses: ./.github/actions/dependencies env: CONAN_URL: http://18.143.149.228:8081/artifactory/api/conan/conan-non-prod - CONAN_USERNAME: ${{ secrets.CONAN_USERNAME }} - CONAN_TOKEN: ${{ secrets.CONAN_TOKEN }} + CONAN_LOGIN_USERNAME_RIPPLE: ${{ secrets.CONAN_USERNAME }} + CONAN_PASSWORD_RIPPLE: ${{ secrets.CONAN_TOKEN }} with: configuration: ${{ matrix.configuration }} - name: upload archive @@ -121,13 +121,12 @@ jobs: tar -xzf conan.tar -C ~/.conan - name: check environment run: | + env | sort echo ${PATH} | tr ':' '\n' conan --version cmake --version - env | sort - ls ~/.conan - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: dependencies uses: ./.github/actions/dependencies env: @@ -178,7 +177,7 @@ jobs: env | sort ls ~/.conan - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: dependencies uses: ./.github/actions/dependencies env: @@ -210,7 +209,7 @@ jobs: - name: upload coverage report uses: wandalen/wretry.action@v1.3.0 with: - action: codecov/codecov-action@v3 + action: codecov/codecov-action@v4 with: | files: coverage.xml fail_ci_if_error: true diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 60419944ed6..6aa2bbe706b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -27,9 +27,9 @@ jobs: build_dir: .build steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: choose Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: learn Python cache directory @@ -39,7 +39,7 @@ jobs: python -m pip install --upgrade pip echo "dir=$(pip cache dir)" | tee ${GITHUB_OUTPUT} - name: restore Python cache directory - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pip-cache.outputs.dir }} key: ${{ runner.os }}-${{ hashFiles('.github/workflows/windows.yml') }} @@ -47,22 +47,23 @@ jobs: run: pip install wheel 'conan<2' - name: check environment run: | + dir env: $env:PATH -split ';' python --version conan --version cmake --version - dir env: - name: configure Conan shell: bash run: | conan profile new default --detect + conan profile update settings.compiler.cppstd=20 default conan profile update settings.compiler.runtime=MT${{ matrix.configuration == 'Debug' && 'd' || '' }} default - name: build dependencies uses: ./.github/actions/dependencies env: CONAN_URL: http://18.143.149.228:8081/artifactory/api/conan/conan-non-prod - CONAN_USERNAME: ${{ secrets.CONAN_USERNAME }} - CONAN_TOKEN: ${{ secrets.CONAN_TOKEN }} + CONAN_LOGIN_USERNAME_RIPPLE: ${{ secrets.CONAN_USERNAME }} + CONAN_PASSWORD_RIPPLE: ${{ secrets.CONAN_TOKEN }} with: configuration: ${{ matrix.configuration }} - name: build diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index b9451e1cfbf..f826c428135 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -26,7 +26,6 @@ target_sources (xrpl_core PRIVATE src/ripple/beast/clock/basic_seconds_clock.cpp src/ripple/beast/core/CurrentThreadName.cpp src/ripple/beast/core/SemanticVersion.cpp - src/ripple/beast/hash/impl/xxhash.cpp src/ripple/beast/insight/impl/Collector.cpp src/ripple/beast/insight/impl/Groups.cpp src/ripple/beast/insight/impl/Hook.cpp @@ -89,6 +88,7 @@ target_sources (xrpl_core PRIVATE src/ripple/protocol/impl/PublicKey.cpp src/ripple/protocol/impl/Quality.cpp src/ripple/protocol/impl/QualityFunction.cpp + src/ripple/protocol/impl/RPCErr.cpp src/ripple/protocol/impl/Rate2.cpp src/ripple/protocol/impl/Rules.cpp src/ripple/protocol/impl/SField.cpp @@ -153,60 +153,61 @@ target_link_libraries (xrpl_core secp256k1::secp256k1 ed25519::ed25519 date::date - Ripple::opts) + Ripple::opts + xxHash::xxhash) #[=================================[ main/core headers installation #]=================================] install ( FILES - src/ripple/basics/algorithm.h src/ripple/basics/Archive.h - src/ripple/basics/base64.h - src/ripple/basics/base_uint.h src/ripple/basics/BasicConfig.h src/ripple/basics/Blob.h src/ripple/basics/Buffer.h src/ripple/basics/ByteUtilities.h - src/ripple/basics/chrono.h - src/ripple/basics/comparators.h src/ripple/basics/CompressionAlgorithms.h - src/ripple/basics/contract.h src/ripple/basics/CountedObject.h src/ripple/basics/DecayingSample.h src/ripple/basics/Expected.h src/ripple/basics/FeeUnits.h src/ripple/basics/FileUtilities.h - src/ripple/basics/hardened_hash.h src/ripple/basics/IOUAmount.h - src/ripple/basics/join.h src/ripple/basics/KeyCache.h src/ripple/basics/LocalValue.h src/ripple/basics/Log.h - src/ripple/basics/make_SSLContext.h src/ripple/basics/MathUtilities.h - src/ripple/basics/mulDiv.h src/ripple/basics/Number.h - src/ripple/basics/partitioned_unordered_map.h src/ripple/basics/PerfLog.h - src/ripple/basics/random.h - src/ripple/basics/RangeSet.h src/ripple/basics/README.md - src/ripple/basics/ResolverAsio.h + src/ripple/basics/RangeSet.h src/ripple/basics/Resolver.h - src/ripple/basics/safe_cast.h - src/ripple/basics/scope.h + src/ripple/basics/ResolverAsio.h src/ripple/basics/SHAMapHash.h src/ripple/basics/Slice.h - src/ripple/basics/spinlock.h - src/ripple/basics/strHex.h src/ripple/basics/StringUtilities.h src/ripple/basics/TaggedCache.h - src/ripple/basics/tagged_integer.h src/ripple/basics/ThreadSafetyAnalysis.h src/ripple/basics/ToString.h src/ripple/basics/UnorderedContainers.h src/ripple/basics/UptimeClock.h src/ripple/basics/XRPAmount.h + src/ripple/basics/algorithm.h + src/ripple/basics/base64.h + src/ripple/basics/base_uint.h + src/ripple/basics/chrono.h + src/ripple/basics/comparators.h + src/ripple/basics/contract.h + src/ripple/basics/hardened_hash.h + src/ripple/basics/join.h + src/ripple/basics/make_SSLContext.h + src/ripple/basics/mulDiv.h + src/ripple/basics/partitioned_unordered_map.h + src/ripple/basics/random.h + src/ripple/basics/safe_cast.h + src/ripple/basics/scope.h + src/ripple/basics/spinlock.h + src/ripple/basics/strHex.h + src/ripple/basics/tagged_integer.h DESTINATION include/ripple/basics) install ( FILES @@ -217,7 +218,6 @@ install ( install ( FILES src/ripple/json/JsonPropertyStream.h - src/ripple/json/MultivarJson.h src/ripple/json/Object.h src/ripple/json/Output.h src/ripple/json/Writer.h @@ -231,16 +231,12 @@ install ( FILES src/ripple/json/impl/json_assert.h DESTINATION include/ripple/json/impl) - -install ( - FILES - src/ripple/net/RPCErr.h - DESTINATION include/ripple/net) install ( FILES src/ripple/protocol/AccountID.h src/ripple/protocol/AMMCore.h src/ripple/protocol/AmountConversions.h + src/ripple/protocol/ApiVersion.h src/ripple/protocol/Book.h src/ripple/protocol/BuildInfo.h src/ripple/protocol/ErrorCodes.h @@ -251,94 +247,112 @@ install ( src/ripple/protocol/InnerObjectFormats.h src/ripple/protocol/Issue.h src/ripple/protocol/json_get_or_throw.h - src/ripple/protocol/KeyType.h src/ripple/protocol/Keylet.h + src/ripple/protocol/KeyType.h src/ripple/protocol/KnownFormats.h src/ripple/protocol/LedgerFormats.h src/ripple/protocol/LedgerHeader.h + src/ripple/protocol/MultiApiJson.h src/ripple/protocol/NFTSyntheticSerializer.h src/ripple/protocol/NFTokenID.h src/ripple/protocol/NFTokenOfferID.h + src/ripple/protocol/NFTSyntheticSerializer.h src/ripple/protocol/Protocol.h src/ripple/protocol/PublicKey.h src/ripple/protocol/Quality.h src/ripple/protocol/QualityFunction.h src/ripple/protocol/Rate.h + src/ripple/protocol/RPCErr.h src/ripple/protocol/Rules.h + src/ripple/protocol/SecretKey.h + src/ripple/protocol/Seed.h + src/ripple/protocol/SeqProxy.h + src/ripple/protocol/Serializer.h src/ripple/protocol/SField.h + src/ripple/protocol/Sign.h src/ripple/protocol/SOTemplate.h src/ripple/protocol/STAccount.h src/ripple/protocol/STAmount.h - src/ripple/protocol/STCurrency.h - src/ripple/protocol/STIssue.h src/ripple/protocol/STArray.h src/ripple/protocol/STBase.h src/ripple/protocol/STBitString.h src/ripple/protocol/STBlob.h + src/ripple/protocol/STCurrency.h src/ripple/protocol/STExchange.h src/ripple/protocol/STInteger.h + src/ripple/protocol/STIssue.h src/ripple/protocol/STLedgerEntry.h src/ripple/protocol/STObject.h src/ripple/protocol/STParsedJSON.h src/ripple/protocol/STPathSet.h src/ripple/protocol/STTx.h - src/ripple/protocol/XChainAttestations.h - src/ripple/protocol/STXChainBridge.h src/ripple/protocol/STValidation.h src/ripple/protocol/STVector256.h - src/ripple/protocol/SecretKey.h - src/ripple/protocol/Seed.h - src/ripple/protocol/SeqProxy.h - src/ripple/protocol/Serializer.h - src/ripple/protocol/Sign.h + src/ripple/protocol/STXChainBridge.h src/ripple/protocol/SystemParameters.h src/ripple/protocol/TER.h src/ripple/protocol/TxFlags.h src/ripple/protocol/TxFormats.h src/ripple/protocol/TxMeta.h src/ripple/protocol/UintTypes.h + src/ripple/protocol/XChainAttestations.h src/ripple/protocol/digest.h src/ripple/protocol/jss.h - src/ripple/protocol/serialize.h src/ripple/protocol/nft.h src/ripple/protocol/nftPageMask.h + src/ripple/protocol/serialize.h src/ripple/protocol/tokens.h DESTINATION include/ripple/protocol) install ( FILES + src/ripple/protocol/impl/STVar.h src/ripple/protocol/impl/b58_utils.h - src/ripple/protocol/impl/STVar.h src/ripple/protocol/impl/secp256k1.h src/ripple/protocol/impl/token_errors.h DESTINATION include/ripple/protocol/impl) install ( - FILES - src/ripple/resource/Fees.h - src/ripple/resource/Charge.h - DESTINATION include/ripple/resource) + FILES + src/ripple/resource/Charge.h + src/ripple/resource/Consumer.h + src/ripple/resource/Disposition.h + src/ripple/resource/Fees.h + src/ripple/resource/Gossip.h + src/ripple/resource/ResourceManager.h + src/ripple/resource/Types.h + DESTINATION include/ripple/resource) +install ( + FILES + src/ripple/resource/impl/Entry.h + src/ripple/resource/impl/Import.h + src/ripple/resource/impl/Key.h + src/ripple/resource/impl/Kind.h + src/ripple/resource/impl/Logic.h + src/ripple/resource/impl/Tuning.h + DESTINATION include/ripple/resource/impl) install ( FILES + src/ripple/server/Handoff.h src/ripple/server/Port.h src/ripple/server/Server.h src/ripple/server/Session.h src/ripple/server/SimpleWriter.h src/ripple/server/Writer.h src/ripple/server/WSSession.h - src/ripple/server/Handoff.h DESTINATION include/ripple/server) install ( FILES - src/ripple/server/impl/ServerImpl.h - src/ripple/server/impl/io_list.h - src/ripple/server/impl/Door.h - src/ripple/server/impl/PlainHTTPPeer.h - src/ripple/server/impl/PlainWSPeer.h src/ripple/server/impl/BaseHTTPPeer.h - src/ripple/server/impl/BaseWSPeer.h src/ripple/server/impl/BasePeer.h + src/ripple/server/impl/BaseWSPeer.h + src/ripple/server/impl/Door.h + src/ripple/server/impl/JSONRPCUtil.h src/ripple/server/impl/LowestLayer.h + src/ripple/server/impl/PlainHTTPPeer.h + src/ripple/server/impl/PlainWSPeer.h + src/ripple/server/impl/ServerImpl.h src/ripple/server/impl/SSLHTTPPeer.h src/ripple/server/impl/SSLWSPeer.h + src/ripple/server/impl/io_list.h DESTINATION include/ripple/server/impl) #[===================================[ beast/legacy headers installation @@ -362,16 +376,13 @@ install ( src/ripple/beast/hash/uhash.h src/ripple/beast/hash/xxhasher.h DESTINATION include/ripple/beast/hash) -install ( - FILES src/ripple/beast/hash/impl/xxhash.h - DESTINATION include/ripple/beast/hash/impl) install ( FILES - src/ripple/beast/net/IPAddress.h - src/ripple/beast/net/IPAddressConversion.h - src/ripple/beast/net/IPAddressV4.h - src/ripple/beast/net/IPAddressV6.h - src/ripple/beast/net/IPEndpoint.h + src/ripple/beast/net/IPAddress.h + src/ripple/beast/net/IPAddressConversion.h + src/ripple/beast/net/IPAddressV4.h + src/ripple/beast/net/IPAddressV6.h + src/ripple/beast/net/IPEndpoint.h DESTINATION include/ripple/beast/net) install ( FILES @@ -385,15 +396,14 @@ install ( src/ripple/beast/unit_test/amount.hpp src/ripple/beast/unit_test/dstream.hpp src/ripple/beast/unit_test/global_suites.hpp - src/ripple/beast/unit_test/main.cpp src/ripple/beast/unit_test/match.hpp src/ripple/beast/unit_test/recorder.hpp src/ripple/beast/unit_test/reporter.hpp src/ripple/beast/unit_test/results.hpp src/ripple/beast/unit_test/runner.hpp - src/ripple/beast/unit_test/suite.hpp src/ripple/beast/unit_test/suite_info.hpp src/ripple/beast/unit_test/suite_list.hpp + src/ripple/beast/unit_test/suite.hpp src/ripple/beast/unit_test/thread.hpp DESTINATION include/ripple/beast/unit_test) install ( @@ -404,34 +414,10 @@ install ( FILES src/ripple/beast/utility/Journal.h src/ripple/beast/utility/PropertyStream.h + src/ripple/beast/utility/WrappedSink.h src/ripple/beast/utility/Zero.h src/ripple/beast/utility/rngfill.h - src/ripple/beast/utility/WrappedSink.h DESTINATION include/ripple/beast/utility) -# WARNING!! -- horrible levelization ahead -# (these files should be isolated or moved...but -# unfortunately unit_test.h above creates this dependency) -if (tests) - install ( - FILES - src/ripple/beast/unit_test/amount.hpp - src/ripple/beast/unit_test/dstream.hpp - src/ripple/beast/unit_test/global_suites.hpp - src/ripple/beast/unit_test/match.hpp - src/ripple/beast/unit_test/recorder.hpp - src/ripple/beast/unit_test/reporter.hpp - src/ripple/beast/unit_test/results.hpp - src/ripple/beast/unit_test/runner.hpp - src/ripple/beast/unit_test/suite.hpp - src/ripple/beast/unit_test/suite_info.hpp - src/ripple/beast/unit_test/suite_list.hpp - src/ripple/beast/unit_test/thread.hpp - DESTINATION include/ripple/beast/extras/unit_test) - install ( - FILES - src/ripple/beast/unit_test/detail/const_container.hpp - DESTINATION include/ripple/beast/unit_test/detail) -endif () #tests #[===================================================================[ rippled executable #]===================================================================] @@ -644,7 +630,6 @@ target_sources (rippled PRIVATE src/ripple/net/impl/HTTPStream.cpp src/ripple/net/impl/InfoSub.cpp src/ripple/net/impl/RPCCall.cpp - src/ripple/net/impl/RPCErr.cpp src/ripple/net/impl/RPCSub.cpp src/ripple/net/impl/RegisterSSLCerts.cpp #[===============================[ @@ -961,7 +946,6 @@ if (tests) src/test/json/Output_test.cpp src/test/json/Writer_test.cpp src/test/json/json_value_test.cpp - src/test/json/MultivarJson_test.cpp #[===============================[ test sources: subdir: jtx @@ -1059,11 +1043,13 @@ if (tests) test sources: subdir: protocol #]===============================] + src/test/protocol/ApiVersion_test.cpp src/test/protocol/BuildInfo_test.cpp src/test/protocol/InnerObjectFormats_test.cpp src/test/protocol/Issue_test.cpp src/test/protocol/Hooks_test.cpp src/test/protocol/Memo_test.cpp + src/test/protocol/MultiApiJson_test.cpp src/test/protocol/PublicKey_test.cpp src/test/protocol/Quality_test.cpp src/test/protocol/STAccount_test.cpp diff --git a/Builds/levelization/results/ordering.txt b/Builds/levelization/results/ordering.txt index c03e5ca5316..ed54065d03e 100644 --- a/Builds/levelization/results/ordering.txt +++ b/Builds/levelization/results/ordering.txt @@ -132,7 +132,6 @@ test.csf > ripple.json test.csf > ripple.protocol test.json > ripple.beast test.json > ripple.json -test.json > ripple.rpc test.json > test.jtx test.jtx > ripple.app test.jtx > ripple.basics diff --git a/CMakeLists.txt b/CMakeLists.txt index d324008ac40..efe0ebf31ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ endif() find_package(nudb REQUIRED) find_package(date REQUIRED) +find_package(xxHash REQUIRED) target_link_libraries(ripple_libs INTERFACE ed25519::ed25519 diff --git a/cfg/rippled-example.cfg b/cfg/rippled-example.cfg index 79de9b23041..2ba2afa727d 100644 --- a/cfg/rippled-example.cfg +++ b/cfg/rippled-example.cfg @@ -416,7 +416,6 @@ # # The default list of entries is: # - r.ripple.com 51235 -# - zaphod.alloy.ee 51235 # - sahyadri.isrdc.in 51235 # # Examples: diff --git a/cfg/rippled-reporting.cfg b/cfg/rippled-reporting.cfg index 6ef10df5bf8..290bcc5418a 100644 --- a/cfg/rippled-reporting.cfg +++ b/cfg/rippled-reporting.cfg @@ -388,7 +388,6 @@ # # The default list of entries is: # - r.ripple.com 51235 -# - zaphod.alloy.ee 51235 # - sahyadri.isrdc.in 51235 # # Examples: diff --git a/conanfile.py b/conanfile.py index d9e2a0ae7c4..d1d24a4876a 100644 --- a/conanfile.py +++ b/conanfile.py @@ -36,6 +36,7 @@ class Xrpl(ConanFile): 'soci/4.0.3', 'sqlite3/3.42.0', 'zlib/1.2.13', + 'xxhash/0.8.2', ] default_options = { @@ -86,6 +87,7 @@ class Xrpl(ConanFile): 'soci:shared': False, 'soci:with_sqlite3': True, 'soci:with_boost': True, + 'xxhash:shared': False, } def set_version(self): @@ -159,4 +161,5 @@ def package_info(self): 'openssl::crypto', 'date::date', 'grpc::grpc++', + 'xxHash::xxhash', ] diff --git a/src/ripple/app/ledger/BookListeners.cpp b/src/ripple/app/ledger/BookListeners.cpp index bbc0058bc76..3c7e013e1dd 100644 --- a/src/ripple/app/ledger/BookListeners.cpp +++ b/src/ripple/app/ledger/BookListeners.cpp @@ -54,8 +54,9 @@ BookListeners::publish( // Only publish jvObj if this is the first occurence if (havePublished.emplace(p->getSeq()).second) { - p->send( - jvObj.select(apiVersionSelector(p->getApiVersion())), true); + jvObj.visit( + p->getApiVersion(), // + [&](Json::Value const& jv) { p->send(jv, true); }); } ++it; } diff --git a/src/ripple/app/ledger/BookListeners.h b/src/ripple/app/ledger/BookListeners.h index 748378a12b1..605cf6dc6af 100644 --- a/src/ripple/app/ledger/BookListeners.h +++ b/src/ripple/app/ledger/BookListeners.h @@ -20,8 +20,8 @@ #ifndef RIPPLE_APP_LEDGER_BOOKLISTENERS_H_INCLUDED #define RIPPLE_APP_LEDGER_BOOKLISTENERS_H_INCLUDED -#include #include +#include #include #include diff --git a/src/ripple/app/ledger/OrderBookDB.h b/src/ripple/app/ledger/OrderBookDB.h index b072bafb0c3..45705a61572 100644 --- a/src/ripple/app/ledger/OrderBookDB.h +++ b/src/ripple/app/ledger/OrderBookDB.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include diff --git a/src/ripple/app/ledger/impl/LedgerToJson.cpp b/src/ripple/app/ledger/impl/LedgerToJson.cpp index 9cef4e65b56..1310dd13a65 100644 --- a/src/ripple/app/ledger/impl/LedgerToJson.cpp +++ b/src/ripple/app/ledger/impl/LedgerToJson.cpp @@ -168,9 +168,7 @@ fillJsonTx( if (validated) { auto const seq = fill.ledger.seq(); - txJson[jss::ledger_index] = (fill.context->apiVersion > 1) - ? Json::Value(seq) - : Json::Value(std::to_string(seq)); + txJson[jss::ledger_index] = seq; if (fill.closeTime) txJson[jss::close_time_iso] = to_string_iso(*fill.closeTime); } diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 73912089f80..cd85bc9e4e1 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -52,15 +52,15 @@ #include #include #include -#include #include -#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -68,7 +68,6 @@ #include #include #include -#include #include #include @@ -2213,11 +2212,11 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) // NOTE Use MultiApiJson to publish two slightly different JSON objects // for consumers supporting different API versions MultiApiJson multiObj{jvObj}; - visit( - multiObj, // - [](Json::Value& jvTx, unsigned int apiVersion) { + multiObj.visit( + RPC::apiVersion<1>, // + [](Json::Value& jvTx) { // Type conversion for older API versions to string - if (jvTx.isMember(jss::ledger_index) && apiVersion < 2) + if (jvTx.isMember(jss::ledger_index)) { jvTx[jss::ledger_index] = std::to_string(jvTx[jss::ledger_index].asUInt()); @@ -2229,9 +2228,9 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) { if (auto p = i->second.lock()) { - p->send( - multiObj.select(apiVersionSelector(p->getApiVersion())), - true); + multiObj.visit( + p->getApiVersion(), // + [&](Json::Value const& jv) { p->send(jv, true); }); ++i; } else @@ -2769,8 +2768,9 @@ NetworkOPsImp::pubProposedTransaction( if (p) { - p->send( - jvObj.select(apiVersionSelector(p->getApiVersion())), true); + jvObj.visit( + p->getApiVersion(), // + [&](Json::Value const& jv) { p->send(jv, true); }); ++it; } else @@ -3167,13 +3167,14 @@ NetworkOPsImp::transJson( std::string const hash = to_string(transaction->getTransactionID()); MultiApiJson multiObj{jvObj}; - visit( - multiObj, // - [&](Json::Value& jvTx, unsigned int apiVersion) { + forAllApiVersions( + multiObj.visit(), // + [&]( + Json::Value& jvTx, std::integral_constant) { RPC::insertDeliverMax( - jvTx[jss::transaction], transaction->getTxnType(), apiVersion); + jvTx[jss::transaction], transaction->getTxnType(), Version); - if (apiVersion > 1) + if constexpr (Version > 1) { jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction); jvTx[jss::hash] = hash; @@ -3210,8 +3211,9 @@ NetworkOPsImp::pubValidatedTransaction( if (p) { - p->send( - jvObj.select(apiVersionSelector(p->getApiVersion())), true); + jvObj.visit( + p->getApiVersion(), // + [&](Json::Value const& jv) { p->send(jv, true); }); ++it; } else @@ -3226,8 +3228,9 @@ NetworkOPsImp::pubValidatedTransaction( if (p) { - p->send( - jvObj.select(apiVersionSelector(p->getApiVersion())), true); + jvObj.visit( + p->getApiVersion(), // + [&](Json::Value const& jv) { p->send(jv, true); }); ++it; } else @@ -3347,9 +3350,9 @@ NetworkOPsImp::pubAccountTransaction( for (InfoSub::ref isrListener : notify) { - isrListener->send( - jvObj.select(apiVersionSelector(isrListener->getApiVersion())), - true); + jvObj.visit( + isrListener->getApiVersion(), // + [&](Json::Value const& jv) { isrListener->send(jv, true); }); } if (last) @@ -3366,9 +3369,9 @@ NetworkOPsImp::pubAccountTransaction( jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++); - info.sink_->send( - jvObj.select(apiVersionSelector(info.sink_->getApiVersion())), - true); + jvObj.visit( + info.sink_->getApiVersion(), // + [&](Json::Value const& jv) { info.sink_->send(jv, true); }); } } } @@ -3426,9 +3429,9 @@ NetworkOPsImp::pubProposedAccountTransaction( MultiApiJson jvObj = transJson(tx, result, false, ledger, std::nullopt); for (InfoSub::ref isrListener : notify) - isrListener->send( - jvObj.select(apiVersionSelector(isrListener->getApiVersion())), - true); + jvObj.visit( + isrListener->getApiVersion(), // + [&](Json::Value const& jv) { isrListener->send(jv, true); }); assert( jvObj.isMember(jss::account_history_tx_stream) == @@ -3439,9 +3442,9 @@ NetworkOPsImp::pubProposedAccountTransaction( if (index->forwardTxIndex_ == 0 && !index->haveHistorical_) jvObj.set(jss::account_history_tx_first, true); jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++); - info.sink_->send( - jvObj.select(apiVersionSelector(info.sink_->getApiVersion())), - true); + jvObj.visit( + info.sink_->getApiVersion(), // + [&](Json::Value const& jv) { info.sink_->send(jv, true); }); } } } @@ -3647,9 +3650,9 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) bool unsubscribe) -> bool { if (auto sptr = subInfo.sinkWptr_.lock()) { - sptr->send( - jvObj.select(apiVersionSelector(sptr->getApiVersion())), - true); + jvObj.visit( + sptr->getApiVersion(), // + [&](Json::Value const& jv) { sptr->send(jv, true); }); if (unsubscribe) unsubAccountHistory(sptr, accountId, false); diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index f2aa363f934..948c6698ad1 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -28,8 +28,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/ripple/app/paths/PathRequests.cpp b/src/ripple/app/paths/PathRequests.cpp index ac051e5f0c5..700cf137209 100644 --- a/src/ripple/app/paths/PathRequests.cpp +++ b/src/ripple/app/paths/PathRequests.cpp @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/app/rdb/backend/detail/impl/Node.cpp b/src/ripple/app/rdb/backend/detail/impl/Node.cpp index 8948360a3ad..0905d6121ae 100644 --- a/src/ripple/app/rdb/backend/detail/impl/Node.cpp +++ b/src/ripple/app/rdb/backend/detail/impl/Node.cpp @@ -1125,7 +1125,7 @@ accountTxPage( { sql = boost::str( boost::format( - prefix + (R"(AccountTransactions.LedgerSeq BETWEEN '%u' AND '%u' + prefix + (R"(AccountTransactions.LedgerSeq BETWEEN %u AND %u ORDER BY AccountTransactions.LedgerSeq %s, AccountTransactions.TxnSeq %s LIMIT %u;)")) % @@ -1148,12 +1148,14 @@ accountTxPage( FROM AccountTransactions, Transactions WHERE (AccountTransactions.TransID = Transactions.TransID AND AccountTransactions.Account = '%s' AND - AccountTransactions.LedgerSeq BETWEEN '%u' AND '%u') - OR + AccountTransactions.LedgerSeq BETWEEN %u AND %u) + UNION + SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,Status,RawTxn,TxnMeta + FROM AccountTransactions, Transactions WHERE (AccountTransactions.TransID = Transactions.TransID AND AccountTransactions.Account = '%s' AND - AccountTransactions.LedgerSeq = '%u' AND - AccountTransactions.TxnSeq %s '%u') + AccountTransactions.LedgerSeq = %u AND + AccountTransactions.TxnSeq %s %u) ORDER BY AccountTransactions.LedgerSeq %s, AccountTransactions.TxnSeq %s LIMIT %u; diff --git a/src/ripple/app/tx/impl/DID.cpp b/src/ripple/app/tx/impl/DID.cpp index c92162c8306..1cad8992ad9 100644 --- a/src/ripple/app/tx/impl/DID.cpp +++ b/src/ripple/app/tx/impl/DID.cpp @@ -161,6 +161,13 @@ DIDSet::doApply() set(sfURI); set(sfDIDDocument); set(sfData); + if (ctx_.view().rules().enabled(fixEmptyDID) && + !sleDID->isFieldPresent(sfURI) && + !sleDID->isFieldPresent(sfDIDDocument) && + !sleDID->isFieldPresent(sfData)) + { + return tecEMPTY_DID; + } return addSLE(ctx_, sleDID, account_); } diff --git a/src/ripple/beast/hash/impl/xxhash.cpp b/src/ripple/beast/hash/impl/xxhash.cpp deleted file mode 100644 index 4a6c85db815..00000000000 --- a/src/ripple/beast/hash/impl/xxhash.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/* -xxHash - Fast Hash algorithm -Copyright (C) 2012-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- xxHash source repository : http://code.google.com/p/xxhash/ -- public discussion board : https://groups.google.com/forum/#!forum/lz4c -*/ - -#include - -#include - -//************************************** -// Tuning parameters -//************************************** -// Unaligned memory access is automatically enabled for "common" CPU, such as -// x86. For others CPU, the compiler will be more cautious, and insert extra -// code to ensure aligned access is respected. If you know your target CPU -// supports unaligned memory access, you want to force this option manually to -// improve performance. You can also enable this parameter if you know your -// input data will always be aligned (boundaries of 4, for U32). -#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64) -#define XXH_USE_UNALIGNED_ACCESS 1 -#endif - -// XXH_ACCEPT_NULL_INPUT_POINTER : -// If the input pointer is a null pointer, xxHash default behavior is to trigger -// a memory access error, since it is a bad pointer. When this option is -// enabled, xxHash output for null input pointers will be the same as a -// null-length input. This option has a very small performance cost (only -// measurable on small inputs). By default, this option is disabled. To enable -// it, uncomment below define : #define XXH_ACCEPT_NULL_INPUT_POINTER 1 - -// XXH_FORCE_NATIVE_FORMAT : -// By default, xxHash library provides endian-independant Hash values, based on -// little-endian convention. Results are therefore identical for little-endian -// and big-endian CPU. This comes at a performance cost for big-endian CPU, -// since some swapping is required to emulate little-endian format. Should -// endian-independance be of no importance for your application, you may set the -// #define below to 1. It will improve speed for Big-endian CPU. This option has -// no impact on Little_Endian CPU. -#define XXH_FORCE_NATIVE_FORMAT 0 - -//************************************** -// Compiler Specific Options -//************************************** -// Disable some Visual warning messages -#ifdef _MSC_VER // Visual Studio -#pragma warning( \ - disable : 4127) // disable: C4127: conditional expression is constant -#endif - -#ifdef _MSC_VER // Visual Studio -#define FORCE_INLINE static __forceinline -#else -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#endif - -//************************************** -// Includes & Memory related functions -//************************************** -// #include "xxhash.h" -// Modify the local functions below should you wish to use some other memory -// routines for malloc(), free() -#include -static void* -XXH_malloc(size_t s) -{ - return malloc(s); -} -static void -XXH_free(void* p) -{ - free(p); -} -// for memcpy() -#include -static void* -XXH_memcpy(void* dest, const void* src, size_t size) -{ - return memcpy(dest, src, size); -} - -//************************************** -// Basic Types -//************************************** -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 -#include -typedef uint8_t BYTE; -typedef uint16_t U16; -typedef uint32_t U32; -typedef int32_t S32; -typedef uint64_t U64; -#else -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; -#endif - -#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS) -#define _PACKED __attribute__((packed)) -#else -#define _PACKED -#endif - -#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) -#ifdef __IBMC__ -#pragma pack(1) -#else -#pragma pack(push, 1) -#endif -#endif - -namespace beast { -namespace detail { - -typedef struct _U32_S -{ - U32 v; -} _PACKED U32_S; -typedef struct _U64_S -{ - U64 v; -} _PACKED U64_S; - -#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) -#pragma pack(pop) -#endif - -#define A32(x) (((U32_S*)(x))->v) -#define A64(x) (((U64_S*)(x))->v) - -//*************************************** -// Compiler-specific Functions and Macros -//*************************************** -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -// Note : although _rotl exists for minGW (GCC under windows), performance seems -// poor -#if defined(_MSC_VER) -#define XXH_rotl32(x, r) _rotl(x, r) -#define XXH_rotl64(x, r) _rotl64(x, r) -#else -#define XXH_rotl32(x, r) ((x << r) | (x >> (32 - r))) -#define XXH_rotl64(x, r) ((x << r) | (x >> (64 - r))) -#endif - -#if defined(_MSC_VER) // Visual Studio -#define XXH_swap32 _byteswap_ulong -#define XXH_swap64 _byteswap_uint64 -#elif GCC_VERSION >= 403 -#define XXH_swap32 __builtin_bswap32 -#define XXH_swap64 __builtin_bswap64 -#else -static inline U32 -XXH_swap32(U32 x) -{ - return ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | - ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff); -} -static inline U64 -XXH_swap64(U64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - -//************************************** -// Constants -//************************************** -#define PRIME32_1 2654435761U -#define PRIME32_2 2246822519U -#define PRIME32_3 3266489917U -#define PRIME32_4 668265263U -#define PRIME32_5 374761393U - -#define PRIME64_1 11400714785074694791ULL -#define PRIME64_2 14029467366897019727ULL -#define PRIME64_3 1609587929392839161ULL -#define PRIME64_4 9650029242287828579ULL -#define PRIME64_5 2870177450012600261ULL - -//************************************** -// Architecture Macros -//************************************** -typedef enum { XXH_bigEndian = 0, XXH_littleEndian = 1 } XXH_endianess; -#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN - // externally, for example using a compiler - // switch -static const int one = 1; -#define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one)) -#endif - -//************************************** -// Macros -//************************************** -#define XXH_STATIC_ASSERT(c) \ - { \ - enum { XXH_static_assert = 1 / (!!(c)) }; \ - } // use only *after* variable declarations - -//**************************** -// Memory reads -//**************************** -typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; - -FORCE_INLINE U32 -XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align == XXH_unaligned) - return endian == XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); - else - return endian == XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr); -} - -FORCE_INLINE U32 -XXH_readLE32(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -FORCE_INLINE U64 -XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align == XXH_unaligned) - { - // Use memcpy to avoid unaligned UB - U64 tmp_aligned; - std::memcpy(&tmp_aligned, ptr, sizeof(U64)); - return endian == XXH_littleEndian ? tmp_aligned - : XXH_swap64(tmp_aligned); - } - else - return endian == XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr); -} - -FORCE_INLINE U64 -XXH_readLE64(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -//**************************** -// Simple Hash Functions -//**************************** -FORCE_INLINE U32 -XXH32_endian_align( - const void* input, - size_t len, - U32 seed, - XXH_endianess endian, - XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U32 h32; -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p == NULL) - { - len = 0; - bEnd = p = (const BYTE*)(size_t)16; - } -#endif - - if (len >= 16) - { - const BYTE* const limit = bEnd - 16; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do - { - v1 += XXH_get32bits(p) * PRIME32_2; - v1 = XXH_rotl32(v1, 13); - v1 *= PRIME32_1; - p += 4; - v2 += XXH_get32bits(p) * PRIME32_2; - v2 = XXH_rotl32(v2, 13); - v2 *= PRIME32_1; - p += 4; - v3 += XXH_get32bits(p) * PRIME32_2; - v3 = XXH_rotl32(v3, 13); - v3 *= PRIME32_1; - p += 4; - v4 += XXH_get32bits(p) * PRIME32_2; - v4 = XXH_rotl32(v4, 13); - v4 *= PRIME32_1; - p += 4; - } while (p <= limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + - XXH_rotl32(v4, 18); - } - else - { - h32 = seed + PRIME32_5; - } - - h32 += (U32)len; - - while (p + 4 <= bEnd) - { - h32 += XXH_get32bits(p) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p += 4; - } - - while (p < bEnd) - { - h32 += (*p) * PRIME32_5; - h32 = XXH_rotl32(h32, 11) * PRIME32_1; - p++; - } - - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - -unsigned int -XXH32(const void* input, size_t len, unsigned seed) -{ -#if 0 - // Simple version, good for code maintenance, but unfortunately slow for small inputs - XXH32_state_t state; - XXH32_reset(&state, seed); - XXH32_update(&state, input, len); - return XXH32_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - -#if !defined(XXH_USE_UNALIGNED_ACCESS) - if ((((size_t)input) & 3) == - 0) // Input is aligned, let's leverage the speed advantage - { - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align( - input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align( - input, len, seed, XXH_bigEndian, XXH_aligned); - } -#endif - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align( - input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align( - input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -FORCE_INLINE U64 -XXH64_endian_align( - const void* input, - size_t len, - U64 seed, - XXH_endianess endian, - XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U64 h64; -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p == NULL) - { - len = 0; - bEnd = p = (const BYTE*)(size_t)32; - } -#endif - - if (len >= 32) - { - const BYTE* const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do - { - v1 += XXH_get64bits(p) * PRIME64_2; - p += 8; - v1 = XXH_rotl64(v1, 31); - v1 *= PRIME64_1; - v2 += XXH_get64bits(p) * PRIME64_2; - p += 8; - v2 = XXH_rotl64(v2, 31); - v2 *= PRIME64_1; - v3 += XXH_get64bits(p) * PRIME64_2; - p += 8; - v3 = XXH_rotl64(v3, 31); - v3 *= PRIME64_1; - v4 += XXH_get64bits(p) * PRIME64_2; - p += 8; - v4 = XXH_rotl64(v4, 31); - v4 *= PRIME64_1; - } while (p <= limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + - XXH_rotl64(v4, 18); - - v1 *= PRIME64_2; - v1 = XXH_rotl64(v1, 31); - v1 *= PRIME64_1; - h64 ^= v1; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v2 *= PRIME64_2; - v2 = XXH_rotl64(v2, 31); - v2 *= PRIME64_1; - h64 ^= v2; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v3 *= PRIME64_2; - v3 = XXH_rotl64(v3, 31); - v3 *= PRIME64_1; - h64 ^= v3; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v4 *= PRIME64_2; - v4 = XXH_rotl64(v4, 31); - v4 *= PRIME64_1; - h64 ^= v4; - h64 = h64 * PRIME64_1 + PRIME64_4; - } - else - { - h64 = seed + PRIME64_5; - } - - h64 += (U64)len; - - while (p + 8 <= bEnd) - { - U64 k1 = XXH_get64bits(p); - k1 *= PRIME64_2; - k1 = XXH_rotl64(k1, 31); - k1 *= PRIME64_1; - h64 ^= k1; - h64 = XXH_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; - p += 8; - } - - if (p + 4 <= bEnd) - { - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p += 4; - } - - while (p < bEnd) - { - h64 ^= (*p) * PRIME64_5; - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - p++; - } - - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - -unsigned long long -XXH64(const void* input, size_t len, unsigned long long seed) -{ -#if 0 - // Simple version, good for code maintenance, but unfortunately slow for small inputs - XXH64_state_t state; - XXH64_reset(&state, seed); - XXH64_update(&state, input, len); - return XXH64_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - -#if !defined(XXH_USE_UNALIGNED_ACCESS) - if ((((size_t)input) & 7) == - 0) // Input is aligned, let's leverage the speed advantage - { - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align( - input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align( - input, len, seed, XXH_bigEndian, XXH_aligned); - } -#endif - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align( - input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align( - input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -/**************************************************** - * Advanced Hash Functions - ****************************************************/ - -/*** Allocation ***/ -typedef struct -{ - U64 total_len; - U32 seed; - U32 v1; - U32 v2; - U32 v3; - U32 v4; - U32 mem32[4]; /* defined as U32 for alignment */ - U32 memsize; -} XXH_istate32_t; - -typedef struct -{ - U64 total_len; - U64 seed; - U64 v1; - U64 v2; - U64 v3; - U64 v4; - U64 mem64[4]; /* defined as U64 for alignment */ - U32 memsize; -} XXH_istate64_t; - -XXH32_state_t* -XXH32_createState(void) -{ - static_assert( - sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t), - ""); // A compilation error here means XXH32_state_t is not large - // enough - return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); -} -XXH_errorcode -XXH32_freeState(XXH32_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -}; - -XXH64_state_t* -XXH64_createState(void) -{ - static_assert( - sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t), - ""); // A compilation error here means XXH64_state_t is not large - // enough - return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); -} -XXH_errorcode -XXH64_freeState(XXH64_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -}; - -/*** Hash feed ***/ - -XXH_errorcode -XXH32_reset(XXH32_state_t* state_in, U32 seed) -{ - XXH_istate32_t* state = (XXH_istate32_t*)state_in; - state->seed = seed; - state->v1 = seed + PRIME32_1 + PRIME32_2; - state->v2 = seed + PRIME32_2; - state->v3 = seed + 0; - state->v4 = seed - PRIME32_1; - state->total_len = 0; - state->memsize = 0; - return XXH_OK; -} - -XXH_errorcode -XXH64_reset(XXH64_state_t* state_in, unsigned long long seed) -{ - XXH_istate64_t* state = (XXH_istate64_t*)state_in; - state->seed = seed; - state->v1 = seed + PRIME64_1 + PRIME64_2; - state->v2 = seed + PRIME64_2; - state->v3 = seed + 0; - state->v4 = seed - PRIME64_1; - state->total_len = 0; - state->memsize = 0; - return XXH_OK; -} - -FORCE_INLINE XXH_errorcode -XXH32_update_endian( - XXH32_state_t* state_in, - const void* input, - size_t len, - XXH_endianess endian) -{ - XXH_istate32_t* state = (XXH_istate32_t*)state_in; - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input == NULL) - return XXH_ERROR; -#endif - - state->total_len += len; - - if (state->memsize + len < 16) // fill in tmp buffer - { - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) // some data left from previous update - { - XXH_memcpy( - (BYTE*)(state->mem32) + state->memsize, input, 16 - state->memsize); - { - const U32* p32 = state->mem32; - state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; - state->v1 = XXH_rotl32(state->v1, 13); - state->v1 *= PRIME32_1; - p32++; - state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; - state->v2 = XXH_rotl32(state->v2, 13); - state->v2 *= PRIME32_1; - p32++; - state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; - state->v3 = XXH_rotl32(state->v3, 13); - state->v3 *= PRIME32_1; - p32++; - state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; - state->v4 = XXH_rotl32(state->v4, 13); - state->v4 *= PRIME32_1; - p32++; - } - p += 16 - state->memsize; - state->memsize = 0; - } - - if (p <= bEnd - 16) - { - const BYTE* const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do - { - v1 += XXH_readLE32(p, endian) * PRIME32_2; - v1 = XXH_rotl32(v1, 13); - v1 *= PRIME32_1; - p += 4; - v2 += XXH_readLE32(p, endian) * PRIME32_2; - v2 = XXH_rotl32(v2, 13); - v2 *= PRIME32_1; - p += 4; - v3 += XXH_readLE32(p, endian) * PRIME32_2; - v3 = XXH_rotl32(v3, 13); - v3 *= PRIME32_1; - p += 4; - v4 += XXH_readLE32(p, endian) * PRIME32_2; - v4 = XXH_rotl32(v4, 13); - v4 *= PRIME32_1; - p += 4; - } while (p <= limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) - { - XXH_memcpy(state->mem32, p, bEnd - p); - state->memsize = (int)(bEnd - p); - } - - return XXH_OK; -} - -XXH_errorcode -XXH32_update(XXH32_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U32 -XXH32_digest_endian(const XXH32_state_t* state_in, XXH_endianess endian) -{ - XXH_istate32_t* state = (XXH_istate32_t*)state_in; - const BYTE* p = (const BYTE*)state->mem32; - BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize; - U32 h32; - - if (state->total_len >= 16) - { - h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + - XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); - } - else - { - h32 = state->seed + PRIME32_5; - } - - h32 += (U32)state->total_len; - - while (p + 4 <= bEnd) - { - h32 += XXH_readLE32(p, endian) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p += 4; - } - - while (p < bEnd) - { - h32 += (*p) * PRIME32_5; - h32 = XXH_rotl32(h32, 11) * PRIME32_1; - p++; - } - - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - -U32 -XXH32_digest(const XXH32_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - -FORCE_INLINE XXH_errorcode -XXH64_update_endian( - XXH64_state_t* state_in, - const void* input, - size_t len, - XXH_endianess endian) -{ - XXH_istate64_t* state = (XXH_istate64_t*)state_in; - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input == NULL) - return XXH_ERROR; -#endif - - state->total_len += len; - - if (state->memsize + len < 32) // fill in tmp buffer - { - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) // some data left from previous update - { - XXH_memcpy( - ((BYTE*)state->mem64) + state->memsize, input, 32 - state->memsize); - { - const U64* p64 = state->mem64; - state->v1 += XXH_readLE64(p64, endian) * PRIME64_2; - state->v1 = XXH_rotl64(state->v1, 31); - state->v1 *= PRIME64_1; - p64++; - state->v2 += XXH_readLE64(p64, endian) * PRIME64_2; - state->v2 = XXH_rotl64(state->v2, 31); - state->v2 *= PRIME64_1; - p64++; - state->v3 += XXH_readLE64(p64, endian) * PRIME64_2; - state->v3 = XXH_rotl64(state->v3, 31); - state->v3 *= PRIME64_1; - p64++; - state->v4 += XXH_readLE64(p64, endian) * PRIME64_2; - state->v4 = XXH_rotl64(state->v4, 31); - state->v4 *= PRIME64_1; - p64++; - } - p += 32 - state->memsize; - state->memsize = 0; - } - - if (p + 32 <= bEnd) - { - const BYTE* const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do - { - v1 += XXH_readLE64(p, endian) * PRIME64_2; - v1 = XXH_rotl64(v1, 31); - v1 *= PRIME64_1; - p += 8; - v2 += XXH_readLE64(p, endian) * PRIME64_2; - v2 = XXH_rotl64(v2, 31); - v2 *= PRIME64_1; - p += 8; - v3 += XXH_readLE64(p, endian) * PRIME64_2; - v3 = XXH_rotl64(v3, 31); - v3 *= PRIME64_1; - p += 8; - v4 += XXH_readLE64(p, endian) * PRIME64_2; - v4 = XXH_rotl64(v4, 31); - v4 *= PRIME64_1; - p += 8; - } while (p <= limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) - { - XXH_memcpy(state->mem64, p, bEnd - p); - state->memsize = (int)(bEnd - p); - } - - return XXH_OK; -} - -XXH_errorcode -XXH64_update(XXH64_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U64 -XXH64_digest_endian(const XXH64_state_t* state_in, XXH_endianess endian) -{ - XXH_istate64_t* state = (XXH_istate64_t*)state_in; - const BYTE* p = (const BYTE*)state->mem64; - BYTE* bEnd = (BYTE*)state->mem64 + state->memsize; - U64 h64; - - if (state->total_len >= 32) - { - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + - XXH_rotl64(v4, 18); - - v1 *= PRIME64_2; - v1 = XXH_rotl64(v1, 31); - v1 *= PRIME64_1; - h64 ^= v1; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v2 *= PRIME64_2; - v2 = XXH_rotl64(v2, 31); - v2 *= PRIME64_1; - h64 ^= v2; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v3 *= PRIME64_2; - v3 = XXH_rotl64(v3, 31); - v3 *= PRIME64_1; - h64 ^= v3; - h64 = h64 * PRIME64_1 + PRIME64_4; - - v4 *= PRIME64_2; - v4 = XXH_rotl64(v4, 31); - v4 *= PRIME64_1; - h64 ^= v4; - h64 = h64 * PRIME64_1 + PRIME64_4; - } - else - { - h64 = state->seed + PRIME64_5; - } - - h64 += (U64)state->total_len; - - while (p + 8 <= bEnd) - { - U64 k1 = XXH_readLE64(p, endian); - k1 *= PRIME64_2; - k1 = XXH_rotl64(k1, 31); - k1 *= PRIME64_1; - h64 ^= k1; - h64 = XXH_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; - p += 8; - } - - if (p + 4 <= bEnd) - { - h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p += 4; - } - - while (p < bEnd) - { - h64 ^= (*p) * PRIME64_5; - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - p++; - } - - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - -unsigned long long -XXH64_digest(const XXH64_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - -} // namespace detail -} // namespace beast diff --git a/src/ripple/beast/hash/impl/xxhash.h b/src/ripple/beast/hash/impl/xxhash.h deleted file mode 100644 index 063838a829a..00000000000 --- a/src/ripple/beast/hash/impl/xxhash.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2014, Yann Collet. - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : http://code.google.com/p/xxhash/ -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo -@3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. -*/ - -#ifndef BEAST_HASH_XXHASH_H_INCLUDED -#define BEAST_HASH_XXHASH_H_INCLUDED - -/***************************** - Includes -*****************************/ -#include /* size_t */ - -namespace beast { -namespace detail { - -/***************************** - Type -*****************************/ -typedef enum { XXH_OK = 0, XXH_ERROR } XXH_errorcode; - -/***************************** - Simple Hash Functions -*****************************/ - -unsigned int -XXH32(const void* input, size_t length, unsigned seed); -unsigned long long -XXH64(const void* input, size_t length, unsigned long long seed); - -/* -XXH32() : - Calculate the 32-bits hash of sequence "length" bytes stored at memory -address "input". The memory between input & input+length must be valid -(allocated and read-accessible). "seed" can be used to alter the result -predictably. This function successfully passes all SMHasher tests. Speed on Core -2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s XXH64() : Calculate -the 64-bits hash of sequence of length "len" stored at memory address "input". -*/ - -/***************************** - Advanced Hash Functions -*****************************/ -typedef struct -{ - long long ll[6]; -} XXH32_state_t; -typedef struct -{ - long long ll[11]; -} XXH64_state_t; - -/* -These structures allow static allocation of XXH states. -States must then be initialized using XXHnn_reset() before first use. - -If you prefer dynamic allocation, please refer to functions below. -*/ - -XXH32_state_t* -XXH32_createState(void); -XXH_errorcode -XXH32_freeState(XXH32_state_t* statePtr); - -XXH64_state_t* -XXH64_createState(void); -XXH_errorcode -XXH64_freeState(XXH64_state_t* statePtr); - -/* -These functions create and release memory for XXH state. -States must then be initialized using XXHnn_reset() before first use. -*/ - -XXH_errorcode -XXH32_reset(XXH32_state_t* statePtr, unsigned seed); -XXH_errorcode -XXH32_update(XXH32_state_t* statePtr, const void* input, size_t length); -unsigned int -XXH32_digest(const XXH32_state_t* statePtr); - -XXH_errorcode -XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed); -XXH_errorcode -XXH64_update(XXH64_state_t* statePtr, const void* input, size_t length); -unsigned long long -XXH64_digest(const XXH64_state_t* statePtr); - -/* -These functions calculate the xxHash of an input provided in multiple smaller -packets, as opposed to an input provided as a single block. - -XXH state space must first be allocated, using either static or dynamic method -provided above. - -Start a new hash by initializing state with a seed, using XXHnn_reset(). - -Then, feed the hash state by calling XXHnn_update() as many times as necessary. -Obviously, input must be valid, meaning allocated and read accessible. -The function returns an error code, with 0 meaning OK, and any other value -meaning there is an error. - -Finally, you can produce a hash anytime, by using XXHnn_digest(). -This function returns the final nn-bits hash. -You can nonetheless continue feeding the hash state with more input, -and therefore get some new hashes, by calling again XXHnn_digest(). - -When you are done, don't forget to free XXH state space, using typically -XXHnn_freeState(). -*/ - -} // namespace detail -} // namespace beast - -#endif diff --git a/src/ripple/beast/hash/xxhasher.h b/src/ripple/beast/hash/xxhasher.h index 512c451a051..1a6fc502321 100644 --- a/src/ripple/beast/hash/xxhasher.h +++ b/src/ripple/beast/hash/xxhasher.h @@ -20,9 +20,11 @@ #ifndef BEAST_HASH_XXHASHER_H_INCLUDED #define BEAST_HASH_XXHASHER_H_INCLUDED -#include #include +#include + #include +#include #include namespace beast { @@ -33,16 +35,35 @@ class xxhasher // requires 64-bit std::size_t static_assert(sizeof(std::size_t) == 8, ""); - detail::XXH64_state_t state_; + XXH3_state_t* state_; + + static XXH3_state_t* + allocState() + { + auto ret = XXH3_createState(); + if (ret == nullptr) + throw std::bad_alloc(); + return ret; + } public: using result_type = std::size_t; static constexpr auto const endian = boost::endian::order::native; - xxhasher() noexcept + xxhasher(xxhasher const&) = delete; + xxhasher& + operator=(xxhasher const&) = delete; + + xxhasher() + { + state_ = allocState(); + XXH3_64bits_reset(state_); + } + + ~xxhasher() noexcept { - detail::XXH64_reset(&state_, 1); + XXH3_freeState(state_); } template < @@ -50,7 +71,8 @@ class xxhasher std::enable_if_t::value>* = nullptr> explicit xxhasher(Seed seed) { - detail::XXH64_reset(&state_, seed); + state_ = allocState(); + XXH3_64bits_reset_withSeed(state_, seed); } template < @@ -58,18 +80,19 @@ class xxhasher std::enable_if_t::value>* = nullptr> xxhasher(Seed seed, Seed) { - detail::XXH64_reset(&state_, seed); + state_ = allocState(); + XXH3_64bits_reset_withSeed(state_, seed); } void operator()(void const* key, std::size_t len) noexcept { - detail::XXH64_update(&state_, key, len); + XXH3_64bits_update(state_, key, len); } explicit operator std::size_t() noexcept { - return detail::XXH64_digest(&state_); + return XXH3_64bits_digest(state_); } }; diff --git a/src/ripple/json/MultivarJson.h b/src/ripple/json/MultivarJson.h deleted file mode 100644 index d946bc6c034..00000000000 --- a/src/ripple/json/MultivarJson.h +++ /dev/null @@ -1,150 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2023 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_JSON_MULTIVARJSON_H_INCLUDED -#define RIPPLE_JSON_MULTIVARJSON_H_INCLUDED - -#include - -#include -#include -#include -#include -#include -#include - -namespace ripple { -template -struct MultivarJson -{ - std::array val = {}; - constexpr static std::size_t size = Size; - - explicit MultivarJson(Json::Value const& init = {}) - { - if (init == Json::Value{}) - return; // All elements are already default-initialized - for (auto& v : val) - v = init; - } - - Json::Value const& - select(auto&& selector) const - requires std::same_as - { - auto const index = selector(); - assert(index < size); - return val[index]; - } - - void - set(const char* key, - auto const& - v) requires std::constructible_from - { - for (auto& a : this->val) - a[key] = v; - } - - // Intentionally not using class enum here, MultivarJson is scope enough - enum IsMemberResult : int { none = 0, some, all }; - - [[nodiscard]] IsMemberResult - isMember(const char* key) const - { - int count = 0; - for (auto& a : this->val) - if (a.isMember(key)) - count += 1; - - return (count == 0 ? none : (count < size ? some : all)); - } -}; - -// Wrapper for Json for all supported API versions. -using MultiApiJson = MultivarJson<3>; - -/* - -NOTE: - -If a future API version change adds another possible format, change the size of -`MultiApiJson`, and update `apiVersionSelector()` to return the appropriate -selection value for the new `apiVersion` and higher. - -The more different JSON formats we support, the more CPU cycles we need to -prepare JSON for different API versions e.g. when publishing streams to -`subscribe` clients. Hence it is desirable to keep MultiApiJson small and -instead fully deprecate and remove support for old API versions. For example, if -we removed support for API version 1 and added a different format for API -version 3, the `apiVersionSelector` would change to -`static_cast(apiVersion > 2)` - -Such hypothetical change should correspond with change in RPCHelpers.h -`apiMinimumSupportedVersion = 2;` - -*/ - -// Helper to create appropriate selector for indexing MultiApiJson by apiVersion -constexpr auto -apiVersionSelector(unsigned int apiVersion) noexcept -{ - return [apiVersion]() constexpr - { - return static_cast( - apiVersion <= 1 // - ? 0 // - : (apiVersion <= 2 // - ? 1 // - : 2)); - }; -} - -// Helper to execute a callback for every version. Want both min and max version -// provided explicitly, so user will know to do update `size` when they change -template < - unsigned int minVer, - unsigned int maxVer, - std::size_t size, - typename Fn> - requires // - (maxVer >= minVer) && // - (size == maxVer + 1 - minVer) && // - (apiVersionSelector(minVer)() == 0) && // - (apiVersionSelector(maxVer)() + 1 == size) && // - requires(Json::Value& json, Fn fn) -{ - fn(json, static_cast(1)); -} -void -visit(MultivarJson& json, Fn fn) -{ - [&](std::index_sequence) - { - static_assert(((apiVersionSelector(minVer + offset)() >= 0) && ...)); - static_assert(((apiVersionSelector(minVer + offset)() < size) && ...)); - (fn(json.val[apiVersionSelector(minVer + offset)()], minVer + offset), - ...); - } - (std::make_index_sequence{}); -} - -} // namespace ripple - -#endif diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 4e3e6c09fc4..8537f76b703 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -30,9 +30,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp index 6b047b7ef81..1bb9a381edd 100644 --- a/src/ripple/overlay/impl/OverlayImpl.cpp +++ b/src/ripple/overlay/impl/OverlayImpl.cpp @@ -491,9 +491,6 @@ OverlayImpl::start() // Pool of servers operated by Ripple Labs Inc. - https://ripple.com bootstrapIps.push_back("r.ripple.com 51235"); - // Pool of servers operated by Alloy Networks - https://www.alloy.ee - bootstrapIps.push_back("zaphod.alloy.ee 51235"); - // Pool of servers operated by ISRDC - https://isrdc.in bootstrapIps.push_back("sahyadri.isrdc.in 51235"); } diff --git a/src/ripple/peerfinder/impl/Logic.h b/src/ripple/peerfinder/impl/Logic.h index dc325cc480d..7a2b6a7543a 100644 --- a/src/ripple/peerfinder/impl/Logic.h +++ b/src/ripple/peerfinder/impl/Logic.h @@ -273,7 +273,7 @@ class Logic std::lock_guard _(lock_); - // Check for duplicate connection + // Check for connection limit per address if (is_public(remote_endpoint)) { auto const count = @@ -287,6 +287,15 @@ class Logic } } + // Check for duplicate connection + if (slots_.find(remote_endpoint) != slots_.end()) + { + JLOG(m_journal.debug()) + << beast::leftw(18) << "Logic dropping " << remote_endpoint + << " as duplicate incoming"; + return SlotImp::ptr(); + } + // Create the slot SlotImp::ptr const slot(std::make_shared( local_endpoint, diff --git a/src/ripple/protocol/ApiVersion.h b/src/ripple/protocol/ApiVersion.h new file mode 100644 index 00000000000..1cd03b0651d --- /dev/null +++ b/src/ripple/protocol/ApiVersion.h @@ -0,0 +1,119 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2023 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED +#define RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED + +#include +#include +#include + +namespace ripple { + +/** + * API version numbers used in later API versions + * + * Requests with a version number in the range + * [apiMinimumSupportedVersion, apiMaximumSupportedVersion] + * are supported. + * + * If [beta_rpc_api] is enabled in config, the version numbers + * in the range [apiMinimumSupportedVersion, apiBetaVersion] + * are supported. + * + * Network Requests without explicit version numbers use + * apiVersionIfUnspecified. apiVersionIfUnspecified is 1, + * because all the RPC requests with a version >= 2 must + * explicitly specify the version in the requests. + * Note that apiVersionIfUnspecified will be lower than + * apiMinimumSupportedVersion when we stop supporting API + * version 1. + * + * Command line Requests use apiCommandLineVersion. + */ + +namespace RPC { + +template +constexpr static std::integral_constant apiVersion = {}; + +constexpr static auto apiInvalidVersion = apiVersion<0>; +constexpr static auto apiMinimumSupportedVersion = apiVersion<1>; +constexpr static auto apiMaximumSupportedVersion = apiVersion<2>; +constexpr static auto apiVersionIfUnspecified = apiVersion<1>; +constexpr static auto apiCommandLineVersion = + apiVersion<1>; // TODO Bump to 2 later +constexpr static auto apiBetaVersion = apiVersion<3>; +constexpr static auto apiMaximumValidVersion = apiBetaVersion; + +static_assert(apiInvalidVersion < apiMinimumSupportedVersion); +static_assert( + apiVersionIfUnspecified >= apiMinimumSupportedVersion && + apiVersionIfUnspecified <= apiMaximumSupportedVersion); +static_assert( + apiCommandLineVersion >= apiMinimumSupportedVersion && + apiCommandLineVersion <= apiMaximumSupportedVersion); +static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion); +static_assert(apiBetaVersion >= apiMaximumSupportedVersion); +static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); + +} // namespace RPC + +template + void + forApiVersions(Fn const& fn, Args&&... args) requires // + (maxVer >= minVer) && // + (minVer >= RPC::apiMinimumSupportedVersion) && // + (RPC::apiMaximumValidVersion >= maxVer) && + requires +{ + fn(std::integral_constant{}, + std::forward(args)...); + fn(std::integral_constant{}, + std::forward(args)...); +} +{ + constexpr auto size = maxVer + 1 - minVer; + [&](std::index_sequence) + { + (((void)fn( + std::integral_constant{}, + std::forward(args)...)), + ...); + } + (std::make_index_sequence{}); +} + +template +void +forAllApiVersions(Fn const& fn, Args&&... args) requires requires +{ + forApiVersions< + RPC::apiMinimumSupportedVersion, + RPC::apiMaximumValidVersion>(fn, std::forward(args)...); +} +{ + forApiVersions< + RPC::apiMinimumSupportedVersion, + RPC::apiMaximumValidVersion>(fn, std::forward(args)...); +} + +} // namespace ripple + +#endif diff --git a/src/ripple/protocol/Feature.h b/src/ripple/protocol/Feature.h index 95a13d44f0e..2f956e0dcd1 100644 --- a/src/ripple/protocol/Feature.h +++ b/src/ripple/protocol/Feature.h @@ -74,7 +74,7 @@ namespace detail { // Feature.cpp. Because it's only used to reserve storage, and determine how // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // the actual number of amendments. A LogicError on startup will verify this. -static constexpr std::size_t numFeatures = 68; +static constexpr std::size_t numFeatures = 69; /** Amendments that this server supports and the default voting behavior. Whether they are enabled depends on the Rules defined in the validated @@ -355,6 +355,7 @@ extern uint256 const fixFillOrKill; extern uint256 const fixNFTokenReserve; extern uint256 const fixInnerObjTemplate; extern uint256 const featurePriceOracle; +extern uint256 const fixEmptyDID; } // namespace ripple diff --git a/src/ripple/protocol/MultiApiJson.h b/src/ripple/protocol/MultiApiJson.h new file mode 100644 index 00000000000..b6d1843ae69 --- /dev/null +++ b/src/ripple/protocol/MultiApiJson.h @@ -0,0 +1,247 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2023 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_JSON_MULTIAPIJSON_H_INCLUDED +#define RIPPLE_JSON_MULTIAPIJSON_H_INCLUDED + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { + +namespace detail { +template +constexpr bool is_integral_constant = false; +template +constexpr bool is_integral_constant&> = true; +template +constexpr bool is_integral_constant const&> = true; + +template +concept some_integral_constant = detail::is_integral_constant; + +// This class is designed to wrap a collection of _almost_ identical Json::Value +// objects, indexed by version (i.e. there is some mapping of version to object +// index). It is used e.g. when we need to publish JSON data to users supporting +// different API versions. We allow manipulation and inspection of all objects +// at once with `isMember` and `set`, and also individual inspection and updates +// of an object selected by the user by version, using `visitor_t` nested type. +template +struct MultiApiJson +{ + static_assert(MinVer <= MaxVer); + + static constexpr auto + valid(unsigned int v) noexcept -> bool + { + return v >= MinVer && v <= MaxVer; + } + + static constexpr auto + index(unsigned int v) noexcept -> std::size_t + { + return (v < MinVer) ? 0 : static_cast(v - MinVer); + } + + constexpr static std::size_t size = MaxVer + 1 - MinVer; + std::array val = {}; + + explicit MultiApiJson(Json::Value const& init = {}) + { + if (init == Json::Value{}) + return; // All elements are already default-initialized + for (auto& v : val) + v = init; + } + + void + set(const char* key, + auto const& + v) requires std::constructible_from + { + for (auto& a : this->val) + a[key] = v; + } + + // Intentionally not using class enum here, MultivarJson is scope enough + enum IsMemberResult : int { none = 0, some, all }; + + [[nodiscard]] IsMemberResult + isMember(const char* key) const + { + int count = 0; + for (auto& a : this->val) + if (a.isMember(key)) + count += 1; + + return (count == 0 ? none : (count < size ? some : all)); + } + + static constexpr struct visitor_t final + { + // integral_constant version, extra arguments + template < + typename Json, + unsigned int Version, + typename... Args, + typename Fn> + requires std::same_as, MultiApiJson> auto + operator()( + Json& json, + std::integral_constant const version, + Fn fn, + Args&&... args) const + -> std::invoke_result_t< + Fn, + decltype(json.val[0]), + std::integral_constant, + Args&&...> + { + static_assert( + valid(Version) && index(Version) >= 0 && index(Version) < size); + return std::invoke( + fn, + json.val[index(Version)], + version, + std::forward(args)...); + } + + // integral_constant version, Json only + template + requires std::same_as, MultiApiJson> auto + operator()( + Json& json, + std::integral_constant const, + Fn fn) const -> std::invoke_result_t + { + static_assert( + valid(Version) && index(Version) >= 0 && index(Version) < size); + return std::invoke(fn, json.val[index(Version)]); + } + + // unsigned int version, extra arguments + template < + typename Json, + typename Version, + typename... Args, + typename Fn> + requires(!some_integral_constant) && + std::convertible_to&& std::same_as< + std::remove_cvref_t, + MultiApiJson> auto + operator()(Json& json, Version version, Fn fn, Args&&... args) const + -> std:: + invoke_result_t + { + assert( + valid(version) && index(version) >= 0 && index(version) < size); + return std::invoke( + fn, + json.val[index(version)], + version, + std::forward(args)...); + } + + // unsigned int version, Json only + template + requires(!some_integral_constant) && + std::convertible_to&& std:: + same_as, MultiApiJson> auto + operator()(Json& json, Version version, Fn fn) const + -> std::invoke_result_t + { + assert( + valid(version) && index(version) >= 0 && index(version) < size); + return std::invoke(fn, json.val[index(version)]); + } + } visitor = {}; + + auto + visit() + { + return [self = this](auto... args) requires requires + { + visitor( + std::declval(), + std::declval()...); + } + { + return visitor(*self, std::forward(args)...); + }; + } + + auto + visit() const + { + return [self = this](auto... args) requires requires + { + visitor( + std::declval(), + std::declval()...); + } + { + return visitor(*self, std::forward(args)...); + }; + } + + template + auto + visit(Args... args) + -> std::invoke_result_t requires( + sizeof...(args) > 0) && + requires + { + visitor(*this, std::forward(args)...); + } + { + return visitor(*this, std::forward(args)...); + } + + template + auto + visit(Args... args) const -> std:: + invoke_result_t requires( + sizeof...(args) > 0) && + requires + { + visitor(*this, std::forward(args)...); + } + { + return visitor(*this, std::forward(args)...); + } +}; + +} // namespace detail + +// Wrapper for Json for all supported API versions. +using MultiApiJson = detail:: + MultiApiJson; + +} // namespace ripple + +#endif diff --git a/src/ripple/net/RPCErr.h b/src/ripple/protocol/RPCErr.h similarity index 100% rename from src/ripple/net/RPCErr.h rename to src/ripple/protocol/RPCErr.h diff --git a/src/ripple/protocol/TER.h b/src/ripple/protocol/TER.h index 8cd5e824608..41c23a2d6a8 100644 --- a/src/ripple/protocol/TER.h +++ b/src/ripple/protocol/TER.h @@ -64,7 +64,8 @@ enum TELcodes : TERUnderlyingType { telCAN_NOT_QUEUE_FULL, telWRONG_NETWORK, telREQUIRES_NETWORK_ID, - telNETWORK_ID_MAKES_TX_NON_CANONICAL + telNETWORK_ID_MAKES_TX_NON_CANONICAL, + telENV_RPC_FAILED }; //------------------------------------------------------------------------------ diff --git a/src/ripple/protocol/impl/Feature.cpp b/src/ripple/protocol/impl/Feature.cpp index 526ef5982fc..313a34e79ed 100644 --- a/src/ripple/protocol/impl/Feature.cpp +++ b/src/ripple/protocol/impl/Feature.cpp @@ -458,10 +458,11 @@ REGISTER_FEATURE(AMM, Supported::yes, VoteBehavior::De REGISTER_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixDisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FEATURE(DID, Supported::yes, VoteBehavior::DefaultNo); -REGISTER_FIX(fixFillOrKill, Supported::yes, VoteBehavior::DefaultNo); +REGISTER_FIX (fixFillOrKill, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixNFTokenReserve, Supported::yes, VoteBehavior::DefaultNo); -REGISTER_FIX(fixInnerObjTemplate, Supported::yes, VoteBehavior::DefaultNo); +REGISTER_FIX (fixInnerObjTemplate, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FEATURE(PriceOracle, Supported::yes, VoteBehavior::DefaultNo); +REGISTER_FIX (fixEmptyDID, Supported::yes, VoteBehavior::DefaultNo); // The following amendments are obsolete, but must remain supported // because they could potentially get enabled. diff --git a/src/ripple/net/impl/RPCErr.cpp b/src/ripple/protocol/impl/RPCErr.cpp similarity index 97% rename from src/ripple/net/impl/RPCErr.cpp rename to src/ripple/protocol/impl/RPCErr.cpp index 8af2a248c2f..ec0474fe8b0 100644 --- a/src/ripple/net/impl/RPCErr.cpp +++ b/src/ripple/protocol/impl/RPCErr.cpp @@ -17,8 +17,8 @@ */ //============================================================================== -#include #include +#include namespace ripple { diff --git a/src/ripple/protocol/impl/TER.cpp b/src/ripple/protocol/impl/TER.cpp index caba034a1c4..93bc60a98ba 100644 --- a/src/ripple/protocol/impl/TER.cpp +++ b/src/ripple/protocol/impl/TER.cpp @@ -154,6 +154,7 @@ transResults() MAKE_ERROR(telWRONG_NETWORK, "Transaction specifies a Network ID that differs from that of the local node."), MAKE_ERROR(telREQUIRES_NETWORK_ID, "Transactions submitted to this node/network must include a correct NetworkID field."), MAKE_ERROR(telNETWORK_ID_MAKES_TX_NON_CANONICAL, "Transactions submitted to this node/network must NOT include a NetworkID field."), + MAKE_ERROR(telENV_RPC_FAILED, "Unit test RPC failure."), MAKE_ERROR(temMALFORMED, "Malformed transaction."), MAKE_ERROR(temBAD_AMM_TOKENS, "Malformed: Invalid LPTokens."), diff --git a/src/ripple/rpc/handlers/AMMInfo.cpp b/src/ripple/rpc/handlers/AMMInfo.cpp index c6711fa7b82..b240c8c2ae6 100644 --- a/src/ripple/rpc/handlers/AMMInfo.cpp +++ b/src/ripple/rpc/handlers/AMMInfo.cpp @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountChannels.cpp b/src/ripple/rpc/handlers/AccountChannels.cpp index 8f39bef164d..ebd89b04418 100644 --- a/src/ripple/rpc/handlers/AccountChannels.cpp +++ b/src/ripple/rpc/handlers/AccountChannels.cpp @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountCurrenciesHandler.cpp b/src/ripple/rpc/handlers/AccountCurrenciesHandler.cpp index 64956a7d0ad..45dc8b545ca 100644 --- a/src/ripple/rpc/handlers/AccountCurrenciesHandler.cpp +++ b/src/ripple/rpc/handlers/AccountCurrenciesHandler.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountLines.cpp b/src/ripple/rpc/handlers/AccountLines.cpp index f30a5d4b0a7..3bfcd225b14 100644 --- a/src/ripple/rpc/handlers/AccountLines.cpp +++ b/src/ripple/rpc/handlers/AccountLines.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountObjects.cpp b/src/ripple/rpc/handlers/AccountObjects.cpp index bbf5b6e126a..2531cd03115 100644 --- a/src/ripple/rpc/handlers/AccountObjects.cpp +++ b/src/ripple/rpc/handlers/AccountObjects.cpp @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountOffers.cpp b/src/ripple/rpc/handlers/AccountOffers.cpp index 1afd2732550..867f888e241 100644 --- a/src/ripple/rpc/handlers/AccountOffers.cpp +++ b/src/ripple/rpc/handlers/AccountOffers.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index 40395aae32f..7fe7472721f 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -28,9 +28,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/BookOffers.cpp b/src/ripple/rpc/handlers/BookOffers.cpp index e85b6029ba6..e21d7047f69 100644 --- a/src/ripple/rpc/handlers/BookOffers.cpp +++ b/src/ripple/rpc/handlers/BookOffers.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Connect.cpp b/src/ripple/rpc/handlers/Connect.cpp index ed366f64b2b..46fac457cb8 100644 --- a/src/ripple/rpc/handlers/Connect.cpp +++ b/src/ripple/rpc/handlers/Connect.cpp @@ -19,9 +19,9 @@ #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/ConsensusInfo.cpp b/src/ripple/rpc/handlers/ConsensusInfo.cpp index f6847e37afd..ee7eb10e684 100644 --- a/src/ripple/rpc/handlers/ConsensusInfo.cpp +++ b/src/ripple/rpc/handlers/ConsensusInfo.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/CrawlShards.cpp b/src/ripple/rpc/handlers/CrawlShards.cpp index 87292e57b93..41b74860c3a 100644 --- a/src/ripple/rpc/handlers/CrawlShards.cpp +++ b/src/ripple/rpc/handlers/CrawlShards.cpp @@ -19,10 +19,10 @@ #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/DepositAuthorized.cpp b/src/ripple/rpc/handlers/DepositAuthorized.cpp index a5c9c9a21fe..bb6e3b07a9a 100644 --- a/src/ripple/rpc/handlers/DepositAuthorized.cpp +++ b/src/ripple/rpc/handlers/DepositAuthorized.cpp @@ -18,9 +18,9 @@ //============================================================================== #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/DownloadShard.cpp b/src/ripple/rpc/handlers/DownloadShard.cpp index d646379d75f..eacf499df04 100644 --- a/src/ripple/rpc/handlers/DownloadShard.cpp +++ b/src/ripple/rpc/handlers/DownloadShard.cpp @@ -19,9 +19,9 @@ #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Feature1.cpp b/src/ripple/rpc/handlers/Feature1.cpp index 131a1e5d073..94a205e62f7 100644 --- a/src/ripple/rpc/handlers/Feature1.cpp +++ b/src/ripple/rpc/handlers/Feature1.cpp @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/FetchInfo.cpp b/src/ripple/rpc/handlers/FetchInfo.cpp index 13ead3d3886..79d82b646a0 100644 --- a/src/ripple/rpc/handlers/FetchInfo.cpp +++ b/src/ripple/rpc/handlers/FetchInfo.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/GatewayBalances.cpp b/src/ripple/rpc/handlers/GatewayBalances.cpp index fc6a7b49fd8..89be6290f77 100644 --- a/src/ripple/rpc/handlers/GatewayBalances.cpp +++ b/src/ripple/rpc/handlers/GatewayBalances.cpp @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/GetCounts.cpp b/src/ripple/rpc/handlers/GetCounts.cpp index cf3e7290202..131cf7d3614 100644 --- a/src/ripple/rpc/handlers/GetCounts.cpp +++ b/src/ripple/rpc/handlers/GetCounts.cpp @@ -26,10 +26,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/LedgerAccept.cpp b/src/ripple/rpc/handlers/LedgerAccept.cpp index 3a01a3950e1..14177791164 100644 --- a/src/ripple/rpc/handlers/LedgerAccept.cpp +++ b/src/ripple/rpc/handlers/LedgerAccept.cpp @@ -21,9 +21,9 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/LedgerCurrent.cpp b/src/ripple/rpc/handlers/LedgerCurrent.cpp index fa2620642ff..3539c800946 100644 --- a/src/ripple/rpc/handlers/LedgerCurrent.cpp +++ b/src/ripple/rpc/handlers/LedgerCurrent.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/ripple/rpc/handlers/LedgerEntry.cpp b/src/ripple/rpc/handlers/LedgerEntry.cpp index de106841ae6..dfbc32e606a 100644 --- a/src/ripple/rpc/handlers/LedgerEntry.cpp +++ b/src/ripple/rpc/handlers/LedgerEntry.cpp @@ -23,9 +23,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/LedgerRequest.cpp b/src/ripple/rpc/handlers/LedgerRequest.cpp index 88d26176ddc..83e7a2184f1 100644 --- a/src/ripple/rpc/handlers/LedgerRequest.cpp +++ b/src/ripple/rpc/handlers/LedgerRequest.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/LogLevel.cpp b/src/ripple/rpc/handlers/LogLevel.cpp index e847007254c..20931898d20 100644 --- a/src/ripple/rpc/handlers/LogLevel.cpp +++ b/src/ripple/rpc/handlers/LogLevel.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Manifest.cpp b/src/ripple/rpc/handlers/Manifest.cpp index daf6cc22661..22abfde8a24 100644 --- a/src/ripple/rpc/handlers/Manifest.cpp +++ b/src/ripple/rpc/handlers/Manifest.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/NFTOffers.cpp b/src/ripple/rpc/handlers/NFTOffers.cpp index 69a090e27ec..bca862d27e3 100644 --- a/src/ripple/rpc/handlers/NFTOffers.cpp +++ b/src/ripple/rpc/handlers/NFTOffers.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/NoRippleCheck.cpp b/src/ripple/rpc/handlers/NoRippleCheck.cpp index 1942372f3e3..91d69df96bd 100644 --- a/src/ripple/rpc/handlers/NoRippleCheck.cpp +++ b/src/ripple/rpc/handlers/NoRippleCheck.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/NodeToShard.cpp b/src/ripple/rpc/handlers/NodeToShard.cpp index fd48797cb2f..552900d1548 100644 --- a/src/ripple/rpc/handlers/NodeToShard.cpp +++ b/src/ripple/rpc/handlers/NodeToShard.cpp @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/OwnerInfo.cpp b/src/ripple/rpc/handlers/OwnerInfo.cpp index 2bd9f258da8..546a2e70980 100644 --- a/src/ripple/rpc/handlers/OwnerInfo.cpp +++ b/src/ripple/rpc/handlers/OwnerInfo.cpp @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/PathFind.cpp b/src/ripple/rpc/handlers/PathFind.cpp index 6c3a27302ac..9c8794b5997 100644 --- a/src/ripple/rpc/handlers/PathFind.cpp +++ b/src/ripple/rpc/handlers/PathFind.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/PayChanClaim.cpp b/src/ripple/rpc/handlers/PayChanClaim.cpp index ca3e8c63c6d..33561463f21 100644 --- a/src/ripple/rpc/handlers/PayChanClaim.cpp +++ b/src/ripple/rpc/handlers/PayChanClaim.cpp @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Peers.cpp b/src/ripple/rpc/handlers/Peers.cpp index d617da737ea..4f377da7277 100644 --- a/src/ripple/rpc/handlers/Peers.cpp +++ b/src/ripple/rpc/handlers/Peers.cpp @@ -19,10 +19,10 @@ #include #include -#include #include #include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/Random.cpp b/src/ripple/rpc/handlers/Random.cpp index 35120c48452..5362969660a 100644 --- a/src/ripple/rpc/handlers/Random.cpp +++ b/src/ripple/rpc/handlers/Random.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/Reservations.cpp b/src/ripple/rpc/handlers/Reservations.cpp index 0d4ad65ebb7..ffbfd0f98bf 100644 --- a/src/ripple/rpc/handlers/Reservations.cpp +++ b/src/ripple/rpc/handlers/Reservations.cpp @@ -18,9 +18,9 @@ //============================================================================== #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index 5e23a47bd52..19bce998494 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/ServerInfo.cpp b/src/ripple/rpc/handlers/ServerInfo.cpp index a96df1f3f13..83c73e20558 100644 --- a/src/ripple/rpc/handlers/ServerInfo.cpp +++ b/src/ripple/rpc/handlers/ServerInfo.cpp @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/ServerState.cpp b/src/ripple/rpc/handlers/ServerState.cpp index d974e7391f7..756a3953968 100644 --- a/src/ripple/rpc/handlers/ServerState.cpp +++ b/src/ripple/rpc/handlers/ServerState.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Submit.cpp b/src/ripple/rpc/handlers/Submit.cpp index b5577ecb576..a151778fbb8 100644 --- a/src/ripple/rpc/handlers/Submit.cpp +++ b/src/ripple/rpc/handlers/Submit.cpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Subscribe.cpp b/src/ripple/rpc/handlers/Subscribe.cpp index e48cfe5049a..24465a2c3a5 100644 --- a/src/ripple/rpc/handlers/Subscribe.cpp +++ b/src/ripple/rpc/handlers/Subscribe.cpp @@ -22,9 +22,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/Tx.cpp b/src/ripple/rpc/handlers/Tx.cpp index 0237fef22ac..d4c9c95a341 100644 --- a/src/ripple/rpc/handlers/Tx.cpp +++ b/src/ripple/rpc/handlers/Tx.cpp @@ -24,9 +24,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/TxHistory.cpp b/src/ripple/rpc/handlers/TxHistory.cpp index 0f3e353fcbc..8759d4af1b9 100644 --- a/src/ripple/rpc/handlers/TxHistory.cpp +++ b/src/ripple/rpc/handlers/TxHistory.cpp @@ -25,8 +25,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/UnlList.cpp b/src/ripple/rpc/handlers/UnlList.cpp index b3beca28307..0dc4dfc3776 100644 --- a/src/ripple/rpc/handlers/UnlList.cpp +++ b/src/ripple/rpc/handlers/UnlList.cpp @@ -19,8 +19,8 @@ #include #include -#include #include +#include #include #include diff --git a/src/ripple/rpc/handlers/Unsubscribe.cpp b/src/ripple/rpc/handlers/Unsubscribe.cpp index 8a606a26dca..512790f2a10 100644 --- a/src/ripple/rpc/handlers/Unsubscribe.cpp +++ b/src/ripple/rpc/handlers/Unsubscribe.cpp @@ -19,8 +19,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/ValidationCreate.cpp b/src/ripple/rpc/handlers/ValidationCreate.cpp index ae1ee33d4c6..f07cbe9cdfa 100644 --- a/src/ripple/rpc/handlers/ValidationCreate.cpp +++ b/src/ripple/rpc/handlers/ValidationCreate.cpp @@ -18,8 +18,8 @@ //============================================================================== #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/handlers/ValidatorListSites.cpp b/src/ripple/rpc/handlers/ValidatorListSites.cpp index 81972c5a2d4..4800a5e8661 100644 --- a/src/ripple/rpc/handlers/ValidatorListSites.cpp +++ b/src/ripple/rpc/handlers/ValidatorListSites.cpp @@ -19,8 +19,8 @@ #include #include -#include #include +#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/Validators.cpp b/src/ripple/rpc/handlers/Validators.cpp index bce9a311d13..39306612bdf 100644 --- a/src/ripple/rpc/handlers/Validators.cpp +++ b/src/ripple/rpc/handlers/Validators.cpp @@ -19,8 +19,8 @@ #include #include -#include #include +#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/WalletPropose.cpp b/src/ripple/rpc/handlers/WalletPropose.cpp index 624c5c83c2b..25aaa3bbb8e 100644 --- a/src/ripple/rpc/handlers/WalletPropose.cpp +++ b/src/ripple/rpc/handlers/WalletPropose.cpp @@ -18,10 +18,10 @@ //============================================================================== #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/impl/DeliveredAmount.cpp b/src/ripple/rpc/impl/DeliveredAmount.cpp index 03a36b9a15f..59316d91cf5 100644 --- a/src/ripple/rpc/impl/DeliveredAmount.cpp +++ b/src/ripple/rpc/impl/DeliveredAmount.cpp @@ -23,9 +23,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/impl/RPCHandler.cpp b/src/ripple/rpc/impl/RPCHandler.cpp index c7984f8309c..9c5aa6d465b 100644 --- a/src/ripple/rpc/impl/RPCHandler.cpp +++ b/src/ripple/rpc/impl/RPCHandler.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ripple/rpc/impl/RPCHelpers.cpp b/src/ripple/rpc/impl/RPCHelpers.cpp index 449586d7b99..58503b0bf4e 100644 --- a/src/ripple/rpc/impl/RPCHelpers.cpp +++ b/src/ripple/rpc/impl/RPCHelpers.cpp @@ -25,9 +25,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/ripple/rpc/impl/RPCHelpers.h b/src/ripple/rpc/impl/RPCHelpers.h index 8b6460cd451..e003773e50c 100644 --- a/src/ripple/rpc/impl/RPCHelpers.h +++ b/src/ripple/rpc/impl/RPCHelpers.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include #include + #include #include @@ -207,41 +209,6 @@ extern beast::SemanticVersion const firstVersion; extern beast::SemanticVersion const goodVersion; extern beast::SemanticVersion const lastVersion; -/** - * API version numbers used in later API versions - * - * Requests with a version number in the range - * [apiMinimumSupportedVersion, apiMaximumSupportedVersion] - * are supported. - * - * If [beta_rpc_api] is enabled in config, the version numbers - * in the range [apiMinimumSupportedVersion, apiBetaVersion] - * are supported. - * - * Network Requests without explicit version numbers use - * apiVersionIfUnspecified. apiVersionIfUnspecified is 1, - * because all the RPC requests with a version >= 2 must - * explicitly specify the version in the requests. - * Note that apiVersionIfUnspecified will be lower than - * apiMinimumSupportedVersion when we stop supporting API - * version 1. - * - * Command line Requests use apiMaximumSupportedVersion. - */ - -constexpr unsigned int apiInvalidVersion = 0; -constexpr unsigned int apiVersionIfUnspecified = 1; -constexpr unsigned int apiMinimumSupportedVersion = 1; -constexpr unsigned int apiMaximumSupportedVersion = 2; -constexpr unsigned int apiCommandLineVersion = 1; // TODO Bump to 2 later -constexpr unsigned int apiBetaVersion = 3; -constexpr unsigned int apiMaximumValidVersion = apiBetaVersion; - -static_assert(apiMinimumSupportedVersion >= apiVersionIfUnspecified); -static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion); -static_assert(apiBetaVersion >= apiMaximumSupportedVersion); -static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); - template void setVersion(Object& parent, unsigned int apiVersion, bool betaEnabled) @@ -256,7 +223,7 @@ setVersion(Object& parent, unsigned int apiVersion, bool betaEnabled) } else { - object[jss::first] = apiMinimumSupportedVersion; + object[jss::first] = apiMinimumSupportedVersion.value; object[jss::last] = betaEnabled ? apiBetaVersion : apiMaximumSupportedVersion; } diff --git a/src/ripple/rpc/impl/ServerHandler.cpp b/src/ripple/rpc/impl/ServerHandler.cpp index 424f2f8d001..d643bdb6331 100644 --- a/src/ripple/rpc/impl/ServerHandler.cpp +++ b/src/ripple/rpc/impl/ServerHandler.cpp @@ -31,9 +31,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -643,7 +643,7 @@ ServerHandler::processRequest( continue; } - auto apiVersion = RPC::apiVersionIfUnspecified; + unsigned apiVersion = RPC::apiVersionIfUnspecified; if (jsonRPC.isMember(jss::params) && jsonRPC[jss::params].isArray() && jsonRPC[jss::params].size() > 0 && jsonRPC[jss::params][0u].isObject()) diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index a80ae4b150e..3f4407c86e7 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -29,9 +29,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/test/app/DID_test.cpp b/src/test/app/DID_test.cpp index 3aa27978bfe..82e77a20264 100644 --- a/src/test/app/DID_test.cpp +++ b/src/test/app/DID_test.cpp @@ -31,7 +31,7 @@ namespace ripple { namespace test { // Helper function that returns the owner count of an account root. -std::uint32_t +static std::uint32_t ownerCount(test::jtx::Env const& env, test::jtx::Account const& acct) { std::uint32_t ret{0}; @@ -130,7 +130,7 @@ struct DID_test : public beast::unit_test::suite using namespace jtx; using namespace std::chrono; - Env env(*this); + Env env{*this, features}; Account const alice{"alice"}; env.fund(XRP(5000), alice); env.close(); @@ -177,6 +177,16 @@ struct DID_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); + // some empty fields, some optional fields + // pre-fix amendment + auto const fixEnabled = env.current()->rules().enabled(fixEmptyDID); + env(did::set(alice), + did::uri(""), + fixEnabled ? ter(tecEMPTY_DID) : ter(tesSUCCESS)); + env.close(); + auto const expectedOwnerReserve = fixEnabled ? 0 : 1; + BEAST_EXPECT(ownerCount(env, alice) == expectedOwnerReserve); + // Modifying a DID to become empty is checked in testSetModify } @@ -188,7 +198,7 @@ struct DID_test : public beast::unit_test::suite using namespace jtx; using namespace std::chrono; - Env env(*this); + Env env{*this, features}; Account const alice{"alice"}; env.fund(XRP(5000), alice); env.close(); @@ -219,7 +229,7 @@ struct DID_test : public beast::unit_test::suite using namespace jtx; using namespace std::chrono; - Env env(*this); + Env env{*this, features}; Account const alice{"alice"}; Account const bob{"bob"}; Account const charlie{"charlie"}; @@ -273,7 +283,7 @@ struct DID_test : public beast::unit_test::suite using namespace jtx; using namespace std::chrono; - Env env(*this); + Env env{*this, features}; Account const alice{"alice"}; env.fund(XRP(5000), alice); env.close(); @@ -390,13 +400,19 @@ struct DID_test : public beast::unit_test::suite run() override { using namespace test::jtx; - FeatureBitset const all{ - supported_amendments() | FeatureBitset{featureDID}}; + FeatureBitset const all{supported_amendments()}; + FeatureBitset const emptyDID{fixEmptyDID}; testEnabled(all); testAccountReserve(all); testSetInvalid(all); testDeleteInvalid(all); testSetModify(all); + + testEnabled(all - emptyDID); + testAccountReserve(all - emptyDID); + testSetInvalid(all - emptyDID); + testDeleteInvalid(all - emptyDID); + testSetModify(all - emptyDID); } }; diff --git a/src/test/app/MultiSign_test.cpp b/src/test/app/MultiSign_test.cpp index 433cf2f7cd8..6e918e36c79 100644 --- a/src/test/app/MultiSign_test.cpp +++ b/src/test/app/MultiSign_test.cpp @@ -247,7 +247,10 @@ class MultiSign_test : public beast::unit_test::suite // Duplicate signers should fail. aliceSeq = env.seq(alice); - env(noop(alice), msig(demon, demon), fee(3 * baseFee), ter(temINVALID)); + env(noop(alice), + msig(demon, demon), + fee(3 * baseFee), + ter(telENV_RPC_FAILED)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -358,7 +361,7 @@ class MultiSign_test : public beast::unit_test::suite msig phantoms{bogie, demon}; std::reverse(phantoms.signers.begin(), phantoms.signers.end()); std::uint32_t const aliceSeq = env.seq(alice); - env(noop(alice), phantoms, ter(temINVALID)); + env(noop(alice), phantoms, ter(telENV_RPC_FAILED)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); } @@ -1634,7 +1637,10 @@ class MultiSign_test : public beast::unit_test::suite // Duplicate signers should fail. aliceSeq = env.seq(alice); - env(noop(alice), msig(demon, demon), fee(3 * baseFee), ter(temINVALID)); + env(noop(alice), + msig(demon, demon), + fee(3 * baseFee), + ter(telENV_RPC_FAILED)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 02a13de5c21..a479e43b170 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -1088,10 +1088,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::amount] = 51110000; // test for all api versions - for (auto apiVersion = RPC::apiMinimumSupportedVersion; - apiVersion <= RPC::apiBetaVersion; - ++apiVersion) - { + forAllApiVersions([&, this](unsigned apiVersion) { testcase( "PayChan Channel_Auth RPC Api " + std::to_string(apiVersion)); args[jss::api_version] = apiVersion; @@ -1101,7 +1098,7 @@ struct PayChan_test : public beast::unit_test::suite args.toStyledString())[jss::result]; auto const error = apiVersion < 2u ? "invalidParams" : "badKeyType"; BEAST_EXPECT(rs[jss::error] == error); - } + }); } void diff --git a/src/test/app/Regression_test.cpp b/src/test/app/Regression_test.cpp index 6431f81dbd6..e2c4b355a9d 100644 --- a/src/test/app/Regression_test.cpp +++ b/src/test/app/Regression_test.cpp @@ -149,7 +149,7 @@ struct Regression_test : public beast::unit_test::suite secp256r1Sig->setFieldVL(sfSigningPubKey, *pubKeyBlob); jt.stx.reset(secp256r1Sig.release()); - env(jt, ter(temINVALID)); + env(jt, ter(telENV_RPC_FAILED)); }; Account const alice{"alice", KeyType::secp256k1}; diff --git a/src/test/app/ValidatorSite_test.cpp b/src/test/app/ValidatorSite_test.cpp index 8acd2063358..00512d157ec 100644 --- a/src/test/app/ValidatorSite_test.cpp +++ b/src/test/app/ValidatorSite_test.cpp @@ -237,7 +237,10 @@ class ValidatorSite_test : public beast::unit_test::suite std::vector uris; for (auto const& u : servers) + { + log << "Testing " << u.uri << std::endl; uris.push_back(u.uri); + } sites->load(uris); sites->start(); sites->join(); diff --git a/src/test/json/MultivarJson_test.cpp b/src/test/json/MultivarJson_test.cpp deleted file mode 100644 index 63b4f8ee394..00000000000 --- a/src/test/json/MultivarJson_test.cpp +++ /dev/null @@ -1,387 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/XRPLF/rippled/ - Copyright (c) 2023 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -#include -#include "ripple/beast/unit_test/suite.hpp" -#include "ripple/json/json_value.h" -#include -#include -#include -#include - -namespace ripple { -namespace test { - -struct MultivarJson_test : beast::unit_test::suite -{ - static auto - makeJson(const char* key, int val) - { - Json::Value obj1(Json::objectValue); - obj1[key] = val; - return obj1; - }; - - void - run() override - { - Json::Value const obj1 = makeJson("value", 1); - Json::Value const obj2 = makeJson("value", 2); - Json::Value const obj3 = makeJson("value", 3); - Json::Value const jsonNull{}; - - MultivarJson<3> subject{}; - static_assert(sizeof(subject) == sizeof(subject.val)); - static_assert(subject.size == subject.val.size()); - static_assert( - std::is_same_v>); - - BEAST_EXPECT(subject.val.size() == 3); - BEAST_EXPECT( - (subject.val == - std::array{jsonNull, jsonNull, jsonNull})); - - subject.val[0] = obj1; - subject.val[1] = obj2; - - { - testcase("default copy construction / assignment"); - - MultivarJson<3> x{subject}; - - BEAST_EXPECT(x.val.size() == subject.val.size()); - BEAST_EXPECT(x.val[0] == subject.val[0]); - BEAST_EXPECT(x.val[1] == subject.val[1]); - BEAST_EXPECT(x.val[2] == subject.val[2]); - BEAST_EXPECT(x.val == subject.val); - BEAST_EXPECT(&x.val[0] != &subject.val[0]); - BEAST_EXPECT(&x.val[1] != &subject.val[1]); - BEAST_EXPECT(&x.val[2] != &subject.val[2]); - - MultivarJson<3> y; - BEAST_EXPECT((y.val == std::array{})); - y = subject; - BEAST_EXPECT(y.val == subject.val); - BEAST_EXPECT(&y.val[0] != &subject.val[0]); - BEAST_EXPECT(&y.val[1] != &subject.val[1]); - BEAST_EXPECT(&y.val[2] != &subject.val[2]); - - y = std::move(x); - BEAST_EXPECT(y.val == subject.val); - BEAST_EXPECT(&y.val[0] != &subject.val[0]); - BEAST_EXPECT(&y.val[1] != &subject.val[1]); - BEAST_EXPECT(&y.val[2] != &subject.val[2]); - } - - { - testcase("select"); - - BEAST_EXPECT( - subject.select([]() -> std::size_t { return 0; }) == obj1); - BEAST_EXPECT( - subject.select([]() -> std::size_t { return 1; }) == obj2); - BEAST_EXPECT( - subject.select([]() -> std::size_t { return 2; }) == jsonNull); - - // Tests of requires clause - these are expected to match - static_assert([](auto&& v) { - return requires - { - v.select([]() -> std::size_t { return 0; }); - }; - }(subject)); - static_assert([](auto&& v) { - return requires - { - v.select([]() constexpr->std::size_t { return 0; }); - }; - }(subject)); - static_assert([](auto&& v) { - return requires - { - v.select([]() mutable -> std::size_t { return 0; }); - }; - }(subject)); - - // Tests of requires clause - these are expected NOT to match - static_assert([](auto&& a) { - return !requires - { - subject.select([]() -> int { return 0; }); - }; - }(subject)); - static_assert([](auto&& v) { - return !requires - { - v.select([]() -> void {}); - }; - }(subject)); - static_assert([](auto&& v) { - return !requires - { - v.select([]() -> bool { return false; }); - }; - }(subject)); - } - - { - testcase("set"); - - auto x = MultivarJson<2>{Json::objectValue}; - x.set("name1", 42); - BEAST_EXPECT(x.val[0].isMember("name1")); - BEAST_EXPECT(x.val[1].isMember("name1")); - BEAST_EXPECT(x.val[0]["name1"].isInt()); - BEAST_EXPECT(x.val[1]["name1"].isInt()); - BEAST_EXPECT(x.val[0]["name1"].asInt() == 42); - BEAST_EXPECT(x.val[1]["name1"].asInt() == 42); - - x.set("name2", "bar"); - BEAST_EXPECT(x.val[0].isMember("name2")); - BEAST_EXPECT(x.val[1].isMember("name2")); - BEAST_EXPECT(x.val[0]["name2"].isString()); - BEAST_EXPECT(x.val[1]["name2"].isString()); - BEAST_EXPECT(x.val[0]["name2"].asString() == "bar"); - BEAST_EXPECT(x.val[1]["name2"].asString() == "bar"); - - // Tests of requires clause - these are expected to match - static_assert([](auto&& v) { - return requires - { - v.set("name", Json::nullValue); - }; - }(x)); - static_assert([](auto&& v) { - return requires - { - v.set("name", "value"); - }; - }(x)); - static_assert([](auto&& v) { - return requires - { - v.set("name", true); - }; - }(x)); - static_assert([](auto&& v) { - return requires - { - v.set("name", 42); - }; - }(x)); - - // Tests of requires clause - these are expected NOT to match - struct foo_t final - { - }; - static_assert([](auto&& v) { - return !requires - { - v.set("name", foo_t{}); - }; - }(x)); - static_assert([](auto&& v) { - return !requires - { - v.set("name", std::nullopt); - }; - }(x)); - } - - { - testcase("isMember"); - - // Well defined behaviour even if we have different types of members - BEAST_EXPECT(subject.isMember("foo") == decltype(subject)::none); - - { - // All variants have element "One", none have element "Two" - MultivarJson<2> s1{}; - s1.val[0] = makeJson("One", 12); - s1.val[1] = makeJson("One", 42); - BEAST_EXPECT(s1.isMember("One") == decltype(s1)::all); - BEAST_EXPECT(s1.isMember("Two") == decltype(s1)::none); - } - - { - // Some variants have element "One" and some have "Two" - MultivarJson<2> s2{}; - s2.val[0] = makeJson("One", 12); - s2.val[1] = makeJson("Two", 42); - BEAST_EXPECT(s2.isMember("One") == decltype(s2)::some); - BEAST_EXPECT(s2.isMember("Two") == decltype(s2)::some); - } - - { - // Not all variants have element "One", because last one is null - MultivarJson<3> s3{}; - s3.val[0] = makeJson("One", 12); - s3.val[1] = makeJson("One", 42); - BEAST_EXPECT(s3.isMember("One") == decltype(s3)::some); - BEAST_EXPECT(s3.isMember("Two") == decltype(s3)::none); - } - } - - { - // NOTE It's fine to change this test when we change API versions - testcase("apiVersionSelector"); - - static_assert(MultiApiJson::size == 3); - static MultiApiJson x{obj1}; - x.val[1] = obj2; - x.val[2] = obj3; - - static_assert( - std::is_same_v); - static_assert([](auto&& v) { - return requires - { - v.select(apiVersionSelector(1)); - }; - }(x)); - - BEAST_EXPECT(x.select(apiVersionSelector(0)) == obj1); - BEAST_EXPECT(x.select(apiVersionSelector(2)) == obj2); - - static_assert(apiVersionSelector(0)() == 0); - static_assert(apiVersionSelector(1)() == 0); - static_assert(apiVersionSelector(2)() == 1); - static_assert(apiVersionSelector(3)() == 2); - static_assert(apiVersionSelector(4)() == 2); - static_assert( - apiVersionSelector( - std::numeric_limits::max())() == 2); - } - - { - // There should be no reson to change this test - testcase("apiVersionSelector invariants"); - - static_assert( - apiVersionSelector(RPC::apiMinimumSupportedVersion)() == 0); - static_assert( - apiVersionSelector(RPC::apiBetaVersion)() + 1 // - == MultiApiJson::size); - - BEAST_EXPECT(MultiApiJson::size >= 1); - } - - { - testcase("visit"); - - MultivarJson<3> s1{}; - s1.val[0] = makeJson("value", 2); - s1.val[1] = makeJson("value", 3); - s1.val[2] = makeJson("value", 5); - - int result = 1; - ripple::visit<1, 3>( - s1, [&](Json::Value& json, unsigned int i) -> void { - if (BEAST_EXPECT(json.isObject() && json.isMember("value"))) - { - auto const value = json["value"].asInt(); - BEAST_EXPECT( - (value == 2 && i == 1) || // - (value == 3 && i == 2) || // - (value == 5 && i == 3)); - result *= value; - } - }); - BEAST_EXPECT(result == 30); - - // Can use fn with constexpr functor - static_assert([](auto&& v) { - return requires - { - ripple::visit<1, 3>( - v, [](Json::Value&, unsigned int) constexpr {}); - }; - }(s1)); - - // Can use fn with deduction over all parameters - static_assert([](auto&& v) { - return requires - { - ripple::visit<1, 3>(v, [](auto&, auto) constexpr {}); - }; - }(s1)); - - // Can use fn with conversion of version parameter - static_assert([](auto&& v) { - return requires - { - ripple::visit<1, 3>(v, [](auto&, std::size_t) constexpr {}); - }; - }(s1)); - - // Cannot use fn with const parameter - static_assert([](auto&& v) { - return !requires - { - ripple::visit<1, 3>( - v, [](Json::Value const&, auto) constexpr {}); - }; - }(const_cast const&>(s1))); - - // Cannot call visit with size mismatch - static_assert([](auto&& v) { - return !requires - { - ripple::visit<1, 2>( - v, [](Json::Value&, unsigned int) constexpr {}); - }; - }(s1)); - - // Cannot call visit with version offset - static_assert([](auto&& v) { - return !requires - { - ripple::visit<0, 2>( - v, [](Json::Value&, unsigned int) constexpr {}); - }; - }(s1)); - - // Cannot call visit with size mismatch - static_assert([](auto&& v) { - return !requires - { - ripple::visit<1, 4>( - v, [](Json::Value&, unsigned int) constexpr {}); - }; - }(s1)); - - // Cannot call visit with wrong order of versions - static_assert([](auto&& v) { - return !requires - { - ripple::visit<3, 1>( - v, [](Json::Value&, unsigned int) constexpr {}); - }; - }(s1)); - } - } -}; - -BEAST_DEFINE_TESTSUITE(MultivarJson, ripple_basics, ripple); - -} // namespace test -} // namespace ripple diff --git a/src/test/jtx/Env.h b/src/test/jtx/Env.h index 74e9e057de8..72cac29040a 100644 --- a/src/test/jtx/Env.h +++ b/src/test/jtx/Env.h @@ -512,7 +512,11 @@ class Env of JTx submission. */ void - postconditions(JTx const& jt, TER ter, bool didApply); + postconditions( + JTx const& jt, + TER ter, + bool didApply, + Json::Value const& jr = Json::Value()); /** Apply funclets and submit. */ /** @{ */ @@ -754,40 +758,6 @@ Env::rpc(std::string const& cmd, Args&&... args) std::forward(args)...); } -/** - * The SingleVersionedTestCallable concept checks for a callable that takes - * an unsigned integer as its argument and returns void. - */ -template -concept SingleVersionedTestCallable = requires(T callable, unsigned int version) -{ - { - callable(version) - } - ->std::same_as; -}; - -/** - * The VersionedTestCallable concept checks if a set of callables all satisfy - * the SingleVersionedTestCallable concept. This allows forAllApiVersions to - * accept any number of functions. It executes a set of provided functions over - * a range of versions from RPC::apiMinimumSupportedVersion to - * RPC::apiBetaVersion. This is useful for running a series of tests or - * operations that need to be performed on multiple versions of an API. - */ -template -concept VersionedTestCallable = (... && SingleVersionedTestCallable); -void -forAllApiVersions(VersionedTestCallable auto... testCallable) -{ - for (auto testVersion = RPC::apiMinimumSupportedVersion; - testVersion <= RPC::apiMaximumValidVersion; - ++testVersion) - { - (..., testCallable(testVersion)); - } -} - } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/Env_test.cpp b/src/test/jtx/Env_test.cpp index 154abe44ce5..8a42b554b8e 100644 --- a/src/test/jtx/Env_test.cpp +++ b/src/test/jtx/Env_test.cpp @@ -747,8 +747,9 @@ class Env_test : public beast::unit_test::suite // Force the factor low enough to fail params[jss::fee_mult_max] = 1; params[jss::fee_div_max] = 2; - // RPC errors result in temINVALID - envs(noop(alice), fee(none), seq(none), ter(temINVALID))(params); + // RPC errors result in telENV_RPC_FAILED + envs(noop(alice), fee(none), seq(none), ter(telENV_RPC_FAILED))( + params); auto tx = env.tx(); BEAST_EXPECT(!tx); diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index e82183c0001..6496f7df1d2 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -280,7 +280,9 @@ Env::parseResult(Json::Value const& jr) jr[jss::result].isMember(jss::engine_result_code)) ter = TER::fromInt(jr[jss::result][jss::engine_result_code].asInt()); else - ter = temINVALID; + // Use an error code that is not used anywhere in the transaction engine + // to distinguish this case. + ter = telENV_RPC_FAILED; return std::make_pair(ter, isTesSuccess(ter) || isTecClaim(ter)); } @@ -288,23 +290,29 @@ void Env::submit(JTx const& jt) { bool didApply; - if (jt.stx) - { - txid_ = jt.stx->getTransactionID(); - Serializer s; - jt.stx->add(s); - auto const jr = rpc("submit", strHex(s.slice())); + auto const jr = [&]() { + if (jt.stx) + { + txid_ = jt.stx->getTransactionID(); + Serializer s; + jt.stx->add(s); + auto const jr = rpc("submit", strHex(s.slice())); - std::tie(ter_, didApply) = parseResult(jr); - } - else - { - // Parsing failed or the JTx is - // otherwise missing the stx field. - ter_ = temMALFORMED; - didApply = false; - } - return postconditions(jt, ter_, didApply); + std::tie(ter_, didApply) = parseResult(jr); + + return jr; + } + else + { + // Parsing failed or the JTx is + // otherwise missing the stx field. + ter_ = temMALFORMED; + didApply = false; + + return Json::Value(); + } + }(); + return postconditions(jt, ter_, didApply, jr); } void @@ -342,11 +350,15 @@ Env::sign_and_submit(JTx const& jt, Json::Value params) std::tie(ter_, didApply) = parseResult(jr); - return postconditions(jt, ter_, didApply); + return postconditions(jt, ter_, didApply, jr); } void -Env::postconditions(JTx const& jt, TER ter, bool didApply) +Env::postconditions( + JTx const& jt, + TER ter, + bool didApply, + Json::Value const& jr) { if (jt.ter && !test.expect( @@ -356,6 +368,8 @@ Env::postconditions(JTx const& jt, TER ter, bool didApply) transHuman(*jt.ter) + ")")) { test.log << pretty(jt.jv) << std::endl; + if (jr) + test.log << pretty(jr) << std::endl; // Don't check postconditions if // we didn't get the expected result. return; diff --git a/src/test/net/DatabaseDownloader_test.cpp b/src/test/net/DatabaseDownloader_test.cpp index d4ed2ebcedf..31c8abfd12c 100644 --- a/src/test/net/DatabaseDownloader_test.cpp +++ b/src/test/net/DatabaseDownloader_test.cpp @@ -147,6 +147,7 @@ class DatabaseDownloader_test : public beast::unit_test::suite // server to request from. Use the /textfile endpoint // to get a simple text file sent as response. auto server = createServer(env); + log << "Downloading DB from " << server->local_endpoint() << std::endl; ripple::test::detail::FileDirGuard const data{ *this, "downloads", "data", "", false, false}; @@ -225,6 +226,8 @@ class DatabaseDownloader_test : public beast::unit_test::suite auto server = createServer(env); auto host = server->local_endpoint().address().to_string(); auto port = std::to_string(server->local_endpoint().port()); + log << "Downloading DB from " << server->local_endpoint() + << std::endl; server->stop(); BEAST_EXPECT(dl->download( host, @@ -249,6 +252,8 @@ class DatabaseDownloader_test : public beast::unit_test::suite ripple::test::detail::FileDirGuard const datafile{ *this, "downloads", "data", "", false, false}; auto server = createServer(env, false); + log << "Downloading DB from " << server->local_endpoint() + << std::endl; BEAST_EXPECT(dl->download( server->local_endpoint().address().to_string(), std::to_string(server->local_endpoint().port()), @@ -272,6 +277,8 @@ class DatabaseDownloader_test : public beast::unit_test::suite ripple::test::detail::FileDirGuard const datafile{ *this, "downloads", "data", "", false, false}; auto server = createServer(env); + log << "Downloading DB from " << server->local_endpoint() + << std::endl; BEAST_EXPECT(dl->download( server->local_endpoint().address().to_string(), std::to_string(server->local_endpoint().port()), diff --git a/src/test/peerfinder/PeerFinder_test.cpp b/src/test/peerfinder/PeerFinder_test.cpp index b0750e689f3..daa316e566c 100644 --- a/src/test/peerfinder/PeerFinder_test.cpp +++ b/src/test/peerfinder/PeerFinder_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,86 @@ class PeerFinder_test : public beast::unit_test::suite BEAST_EXPECT(n <= (seconds + 59) / 60); } + void + test_duplicateOutIn() + { + testcase("duplicate out/in"); + TestStore store; + TestChecker checker; + TestStopwatch clock; + Logic logic(clock, store, checker, journal_); + logic.addFixedPeer( + "test", beast::IP::Endpoint::from_string("65.0.0.1:5")); + { + Config c; + c.autoConnect = false; + c.listeningPort = 1024; + c.ipLimit = 2; + logic.config(c); + } + + auto const list = logic.autoconnect(); + if (BEAST_EXPECT(!list.empty())) + { + BEAST_EXPECT(list.size() == 1); + auto const remote = list.front(); + auto const slot1 = logic.new_outbound_slot(remote); + if (BEAST_EXPECT(slot1 != nullptr)) + { + BEAST_EXPECT( + logic.connectedAddresses_.count(remote.address()) == 1); + auto const local = + beast::IP::Endpoint::from_string("65.0.0.2:1024"); + auto const slot2 = logic.new_inbound_slot(local, remote); + BEAST_EXPECT( + logic.connectedAddresses_.count(remote.address()) == 1); + if (!BEAST_EXPECT(slot2 == nullptr)) + logic.on_closed(slot2); + logic.on_closed(slot1); + } + } + } + + void + test_duplicateInOut() + { + testcase("duplicate in/out"); + TestStore store; + TestChecker checker; + TestStopwatch clock; + Logic logic(clock, store, checker, journal_); + logic.addFixedPeer( + "test", beast::IP::Endpoint::from_string("65.0.0.1:5")); + { + Config c; + c.autoConnect = false; + c.listeningPort = 1024; + c.ipLimit = 2; + logic.config(c); + } + + auto const list = logic.autoconnect(); + if (BEAST_EXPECT(!list.empty())) + { + BEAST_EXPECT(list.size() == 1); + auto const remote = list.front(); + auto const local = + beast::IP::Endpoint::from_string("65.0.0.2:1024"); + auto const slot1 = logic.new_inbound_slot(local, remote); + if (BEAST_EXPECT(slot1 != nullptr)) + { + BEAST_EXPECT( + logic.connectedAddresses_.count(remote.address()) == 1); + auto const slot2 = logic.new_outbound_slot(remote); + BEAST_EXPECT( + logic.connectedAddresses_.count(remote.address()) == 1); + if (!BEAST_EXPECT(slot2 == nullptr)) + logic.on_closed(slot2); + logic.on_closed(slot1); + } + } + } + void test_config() { @@ -279,6 +360,8 @@ class PeerFinder_test : public beast::unit_test::suite { test_backoff1(); test_backoff2(); + test_duplicateOutIn(); + test_duplicateInOut(); test_config(); test_invalid_config(); } diff --git a/src/test/protocol/ApiVersion_test.cpp b/src/test/protocol/ApiVersion_test.cpp new file mode 100644 index 00000000000..f4aba9e9966 --- /dev/null +++ b/src/test/protocol/ApiVersion_test.cpp @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/XRPLF/rippled/ + Copyright (c) 2023 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace ripple { +namespace test { +struct ApiVersion_test : beast::unit_test::suite +{ + void + run() override + { + { + testcase("API versions invariants"); + + static_assert( + RPC::apiMinimumSupportedVersion <= + RPC::apiMaximumSupportedVersion); + static_assert( + RPC::apiMinimumSupportedVersion <= RPC::apiMaximumValidVersion); + static_assert( + RPC::apiMaximumSupportedVersion <= RPC::apiMaximumValidVersion); + static_assert(RPC::apiBetaVersion <= RPC::apiMaximumValidVersion); + + BEAST_EXPECT(true); + } + + { + // Update when we change versions + testcase("API versions"); + + static_assert(RPC::apiMinimumSupportedVersion >= 1); + static_assert(RPC::apiMinimumSupportedVersion < 2); + static_assert(RPC::apiMaximumSupportedVersion >= 2); + static_assert(RPC::apiMaximumSupportedVersion < 3); + static_assert(RPC::apiMaximumValidVersion >= 3); + static_assert(RPC::apiMaximumValidVersion < 4); + static_assert(RPC::apiBetaVersion >= 3); + static_assert(RPC::apiBetaVersion < 4); + + BEAST_EXPECT(true); + } + } +}; + +BEAST_DEFINE_TESTSUITE(ApiVersion, protocol, ripple); + +} // namespace test +} // namespace ripple diff --git a/src/test/protocol/Memo_test.cpp b/src/test/protocol/Memo_test.cpp index b39482e42d0..89ae6dfe18a 100644 --- a/src/test/protocol/Memo_test.cpp +++ b/src/test/protocol/Memo_test.cpp @@ -56,7 +56,7 @@ class Memo_test : public beast::unit_test::suite JTx memoSize = makeJtxWithMemo(); memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] [sfMemoData.jsonName] = std::string(2020, '0'); - env(memoSize, ter(temINVALID)); + env(memoSize, ter(telENV_RPC_FAILED)); // This memo is just barely small enough. memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] @@ -72,7 +72,7 @@ class Memo_test : public beast::unit_test::suite auto& m = mi[sfCreatedNode.jsonName]; // CreatedNode in Memos m[sfMemoData.jsonName] = "3030303030"; - env(memoNonMemo, ter(temINVALID)); + env(memoNonMemo, ter(telENV_RPC_FAILED)); } { // Put an invalid field in a Memo object. @@ -80,7 +80,7 @@ class Memo_test : public beast::unit_test::suite memoExtra .jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfFlags.jsonName] = 13; - env(memoExtra, ter(temINVALID)); + env(memoExtra, ter(telENV_RPC_FAILED)); } { // Put a character that is not allowed in a URL in a MemoType field. @@ -88,7 +88,7 @@ class Memo_test : public beast::unit_test::suite memoBadChar.jv[sfMemos.jsonName][0u][sfMemo.jsonName] [sfMemoType.jsonName] = strHex(std::string_view("ONE +#include + +#include +#include +#include +#include +#include + +namespace ripple { +namespace test { + +namespace { + +// This needs to be in a namespace because of deduction guide +template +struct Overload : Ts... +{ + using Ts::operator()...; +}; +template +Overload(Ts...) -> Overload; + +} // namespace + +struct MultiApiJson_test : beast::unit_test::suite +{ + static auto + makeJson(const char* key, int val) + { + Json::Value obj1(Json::objectValue); + obj1[key] = val; + return obj1; + } + + constexpr static auto index = + [](unsigned int v) constexpr noexcept -> std::size_t + { + return v - 1; + }; + + template + constexpr static auto valid = [](unsigned int v) constexpr noexcept -> bool + { + return v > 0 && v <= size; + }; + + void + run() override + { + using ripple::detail::MultiApiJson; + + Json::Value const obj1 = makeJson("value", 1); + Json::Value const obj2 = makeJson("value", 2); + Json::Value const obj3 = makeJson("value", 3); + Json::Value const jsonNull{}; + + MultiApiJson<1, 3> subject{}; + static_assert(sizeof(subject) == sizeof(subject.val)); + static_assert(subject.size == subject.val.size()); + static_assert( + std::is_same_v>); + + BEAST_EXPECT(subject.val.size() == 3); + BEAST_EXPECT( + (subject.val == + std::array{jsonNull, jsonNull, jsonNull})); + + subject.val[0] = obj1; + subject.val[1] = obj2; + + { + testcase("forApiVersions, forAllApiVersions"); + + // Some static data for test inputs + static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, 61, + 67, 71, 73, 79, 83, 89, 97}; + static_assert(std::size(primes) > RPC::apiMaximumValidVersion); + + MultiApiJson<1, 3> s1{}; + static_assert( + s1.size == + RPC::apiMaximumValidVersion + 1 - + RPC::apiMinimumSupportedVersion); + + int productAllVersions = 1; + for (unsigned i = RPC::apiMinimumSupportedVersion; + i <= RPC::apiMaximumValidVersion; + ++i) + { + auto const index = i - RPC::apiMinimumSupportedVersion; + BEAST_EXPECT(index == s1.index(i)); + BEAST_EXPECT(s1.valid(i)); + s1.val[index] = makeJson("value", primes[i]); + productAllVersions *= primes[i]; + } + BEAST_EXPECT(!s1.valid(0)); + BEAST_EXPECT(!s1.valid(RPC::apiMaximumValidVersion + 1)); + BEAST_EXPECT( + !s1.valid(std::numeric_limits::max())); + + int result = 1; + static_assert( + RPC::apiMinimumSupportedVersion + 1 <= + RPC::apiMaximumValidVersion); + forApiVersions< + RPC::apiMinimumSupportedVersion, + RPC::apiMinimumSupportedVersion + 1>( + std::as_const(s1).visit(), + [this]( + Json::Value const& json, + unsigned int version, + int* result) { + BEAST_EXPECT( + version >= RPC::apiMinimumSupportedVersion && + version <= RPC::apiMinimumSupportedVersion + 1); + if (BEAST_EXPECT(json.isMember("value"))) + { + *result *= json["value"].asInt(); + } + }, + &result); + BEAST_EXPECT( + result == + primes[RPC::apiMinimumSupportedVersion] * + primes[RPC::apiMinimumSupportedVersion + 1]); + + // Check all the values with mutable data + forAllApiVersions( + s1.visit(), [&s1, this](Json::Value& json, auto version) { + BEAST_EXPECT(s1.val[s1.index(version)] == json); + if (BEAST_EXPECT(json.isMember("value"))) + { + BEAST_EXPECT(json["value"].asInt() == primes[version]); + } + }); + + result = 1; + forAllApiVersions( + std::as_const(s1).visit(), + [this]( + Json::Value const& json, + unsigned int version, + int* result) { + BEAST_EXPECT( + version >= RPC::apiMinimumSupportedVersion && + version <= RPC::apiMaximumValidVersion); + if (BEAST_EXPECT(json.isMember("value"))) + { + *result *= json["value"].asInt(); + } + }, + &result); + + BEAST_EXPECT(result == productAllVersions); + + // Several overloads we want to fail + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](Json::Value&, auto) {}); // missing const + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](Json::Value&) {}); // missing const + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + []() {}); // missing parameters + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto) {}, + 1); // missing parameters + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto, auto) {}, + 1); // missing parameters + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto, auto, const char*) {}, + 1); // parameter type mismatch + }; + }(std::as_const(s1))); + + // Sanity checks + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto) {}); + }; + }(s1)); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto...) {}); + }; + }(s1)); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](Json::Value const&, auto...) {}); + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](Json::Value&, auto, auto, auto...) {}, + 0, + ""); + }; + }(s1)); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + []( + Json::Value const&, + std::integral_constant, + int, + const char*) {}, + 0, + ""); + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto...) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return requires + { + forAllApiVersions( + std::forward(v).visit(), // + [](auto...) {}); + }; + }(std::move(std::as_const(s1)))); + } + + { + testcase("default copy construction / assignment"); + + MultiApiJson<1, 3> x{subject}; + + BEAST_EXPECT(x.val.size() == subject.val.size()); + BEAST_EXPECT(x.val[0] == subject.val[0]); + BEAST_EXPECT(x.val[1] == subject.val[1]); + BEAST_EXPECT(x.val[2] == subject.val[2]); + BEAST_EXPECT(x.val == subject.val); + BEAST_EXPECT(&x.val[0] != &subject.val[0]); + BEAST_EXPECT(&x.val[1] != &subject.val[1]); + BEAST_EXPECT(&x.val[2] != &subject.val[2]); + + MultiApiJson<1, 3> y; + BEAST_EXPECT((y.val == std::array{})); + y = subject; + BEAST_EXPECT(y.val == subject.val); + BEAST_EXPECT(&y.val[0] != &subject.val[0]); + BEAST_EXPECT(&y.val[1] != &subject.val[1]); + BEAST_EXPECT(&y.val[2] != &subject.val[2]); + + y = std::move(x); + BEAST_EXPECT(y.val == subject.val); + BEAST_EXPECT(&y.val[0] != &subject.val[0]); + BEAST_EXPECT(&y.val[1] != &subject.val[1]); + BEAST_EXPECT(&y.val[2] != &subject.val[2]); + } + + { + testcase("set"); + + auto x = MultiApiJson<1, 2>{Json::objectValue}; + x.set("name1", 42); + BEAST_EXPECT(x.val[0].isMember("name1")); + BEAST_EXPECT(x.val[1].isMember("name1")); + BEAST_EXPECT(x.val[0]["name1"].isInt()); + BEAST_EXPECT(x.val[1]["name1"].isInt()); + BEAST_EXPECT(x.val[0]["name1"].asInt() == 42); + BEAST_EXPECT(x.val[1]["name1"].asInt() == 42); + + x.set("name2", "bar"); + BEAST_EXPECT(x.val[0].isMember("name2")); + BEAST_EXPECT(x.val[1].isMember("name2")); + BEAST_EXPECT(x.val[0]["name2"].isString()); + BEAST_EXPECT(x.val[1]["name2"].isString()); + BEAST_EXPECT(x.val[0]["name2"].asString() == "bar"); + BEAST_EXPECT(x.val[1]["name2"].asString() == "bar"); + + // Tests of requires clause - these are expected to match + static_assert([](auto&& v) { + return requires + { + v.set("name", Json::nullValue); + }; + }(x)); + static_assert([](auto&& v) { + return requires + { + v.set("name", "value"); + }; + }(x)); + static_assert([](auto&& v) { + return requires + { + v.set("name", true); + }; + }(x)); + static_assert([](auto&& v) { + return requires + { + v.set("name", 42); + }; + }(x)); + + // Tests of requires clause - these are expected NOT to match + struct foo_t final + { + }; + static_assert([](auto&& v) { + return !requires + { + v.set("name", foo_t{}); + }; + }(x)); + static_assert([](auto&& v) { + return !requires + { + v.set("name", std::nullopt); + }; + }(x)); + } + + { + testcase("isMember"); + + // Well defined behaviour even if we have different types of members + BEAST_EXPECT(subject.isMember("foo") == decltype(subject)::none); + + { + // All variants have element "One", none have element "Two" + MultiApiJson<1, 2> s1{}; + s1.val[0] = makeJson("One", 12); + s1.val[1] = makeJson("One", 42); + BEAST_EXPECT(s1.isMember("One") == decltype(s1)::all); + BEAST_EXPECT(s1.isMember("Two") == decltype(s1)::none); + } + + { + // Some variants have element "One" and some have "Two" + MultiApiJson<1, 2> s2{}; + s2.val[0] = makeJson("One", 12); + s2.val[1] = makeJson("Two", 42); + BEAST_EXPECT(s2.isMember("One") == decltype(s2)::some); + BEAST_EXPECT(s2.isMember("Two") == decltype(s2)::some); + } + + { + // Not all variants have element "One", because last one is null + MultiApiJson<1, 3> s3{}; + s3.val[0] = makeJson("One", 12); + s3.val[1] = makeJson("One", 42); + BEAST_EXPECT(s3.isMember("One") == decltype(s3)::some); + BEAST_EXPECT(s3.isMember("Two") == decltype(s3)::none); + } + } + + { + testcase("visitor"); + + MultiApiJson<1, 3> s1{}; + s1.val[0] = makeJson("value", 2); + s1.val[1] = makeJson("value", 3); + s1.val[2] = makeJson("value", 5); + + BEAST_EXPECT(not s1.valid(0)); + BEAST_EXPECT(s1.index(0) == 0); + + BEAST_EXPECT(s1.valid(1)); + BEAST_EXPECT(s1.index(1) == 0); + + BEAST_EXPECT(not s1.valid(4)); + + // Test different overloads + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, + std::integral_constant{}, + [](Json::Value&, std::integral_constant) { + }); + }; + }(s1)); + BEAST_EXPECT( + s1.visitor( + s1, + std::integral_constant{}, + Overload{ + [](Json::Value& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 2); + + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, + std::integral_constant{}, + [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visitor( + s1, + std::integral_constant{}, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 2); + + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, + std::integral_constant{}, + [](Json::Value const&, + std::integral_constant) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), + std::integral_constant{}, + Overload{ + [](Json::Value const& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, + std::integral_constant{}, + [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), + std::integral_constant{}, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value&, unsigned) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visitor( + s1, // + 3u, + Overload{ + [](Json::Value& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, unsigned) { return 0; }, + [](auto, auto) { return 0; }}) == 5); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visitor( + s1, // + 3, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 5); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value const&, unsigned) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), // + 2u, + Overload{ + [](Json::Value const& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), // + 2, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + + // Test type conversions + BEAST_EXPECT( + s1.visitor( + s1, + std::integral_constant{}, // to unsigned + [](Json::Value& v, unsigned) { + return v["value"].asInt(); + }) == 2); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), + std::integral_constant{}, // to unsigned + [](Json::Value const& v, unsigned) { + return v["value"].asInt(); + }) == 3); + BEAST_EXPECT( + s1.visitor( + s1, // to const + std::integral_constant{}, + [](Json::Value const& v, auto) { + return v["value"].asInt(); + }) == 5); + BEAST_EXPECT( + s1.visitor( + s1, // to const + std::integral_constant{}, + [](Json::Value const& v) { return v["value"].asInt(); }) == + 5); + BEAST_EXPECT( + s1.visitor( + s1, + 3, // to long + [](Json::Value& v, long) { return v["value"].asInt(); }) == + 5); + BEAST_EXPECT( + s1.visitor( + std::as_const(s1), + 1, // to long + [](Json::Value const& v, long) { + return v["value"].asInt(); + }) == 2); + BEAST_EXPECT( + s1.visitor( + s1, // to const + 2, + [](Json::Value const& v, auto) { + return v["value"].asInt(); + }) == 3); + BEAST_EXPECT( + s1.visitor( + s1, // type deduction + 2, + [](auto& v, auto) { return v["value"].asInt(); }) == 3); + BEAST_EXPECT( + s1.visitor( + s1, // to const, type deduction + 2, + [](auto const& v, auto) { return v["value"].asInt(); }) == + 3); + BEAST_EXPECT( + s1.visitor( + s1, // type deduction + 2, + [](auto& v) { return v["value"].asInt(); }) == 3); + BEAST_EXPECT( + s1.visitor( + s1, // to const, type deduction + 2, + [](auto const& v) { return v["value"].asInt(); }) == 3); + + // Test passing of additional arguments + BEAST_EXPECT( + s1.visitor( + s1, + std::integral_constant{}, + [](Json::Value& v, auto ver, auto a1, auto a2) { + return ver * a1 * a2 * v["value"].asInt(); + }, + 5, + 7) == 2 * 5 * 7 * 3); + BEAST_EXPECT( + s1.visitor( + s1, + std::integral_constant{}, + [](Json::Value& v, auto ver, auto... args) { + return ver * (1 * ... * args) * v["value"].asInt(); + }, + 5, + 7) == 2 * 5 * 7 * 3); + + // Several overloads we want to fail + static_assert([](auto&& v) { + return !requires + { + v.visitor( + v, + 1, // + [](Json::Value&, auto) {}); // missing const + }; + }(std::as_const(s1))); + + static_assert([](auto&& v) { + return !requires + { + v.visitor( + std::move(v), // cannot bind rvalue + 1, + [](Json::Value&, auto) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return !requires + { + v.visitor( + v, + 1, // + []() {}); // missing parameter + }; + }(s1)); + + static_assert([](auto&& v) { + return !requires + { + v.visitor( + v, + 1, // + [](Json::Value&, int, int) {}); // too many parameters + }; + }(s1)); + + // Want these to be unambiguous + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](auto) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value&) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value&, auto...) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value const&) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](Json::Value const&, auto...) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](auto...) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](auto, auto...) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor(v, 1, [](auto, auto, auto...) {}); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, 1, [](auto, auto, auto...) {}, ""); + }; + }(s1)); + + static_assert([](auto&& v) { + return requires + { + v.visitor( + v, 1, [](auto, auto, auto, auto...) {}, ""); + }; + }(s1)); + } + + { + testcase("visit"); + + MultiApiJson<1, 3> s1{}; + s1.val[0] = makeJson("value", 2); + s1.val[1] = makeJson("value", 3); + s1.val[2] = makeJson("value", 5); + + // Test different overloads + static_assert([](auto&& v) { + return requires + { + v.visit( + std::integral_constant{}, + [](Json::Value&, std::integral_constant) { + }); + }; + }(s1)); + BEAST_EXPECT( + s1.visit( + std::integral_constant{}, + Overload{ + [](Json::Value& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 2); + static_assert([](auto&& v) { + return requires + { + v.visit()( + std::integral_constant{}, + [](Json::Value&, std::integral_constant) { + }); + }; + }(s1)); + BEAST_EXPECT( + s1.visit()( + std::integral_constant{}, + Overload{ + [](Json::Value& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 2); + + static_assert([](auto&& v) { + return requires + { + v.visit( + std::integral_constant{}, + [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit( + std::integral_constant{}, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 2); + static_assert([](auto&& v) { + return requires + { + v.visit()( + std::integral_constant{}, + [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit()( + std::integral_constant{}, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 2); + + static_assert([](auto&& v) { + return requires + { + v.visit( + std::integral_constant{}, + [](Json::Value const&, + std::integral_constant) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit( + std::integral_constant{}, + Overload{ + [](Json::Value const& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + static_assert([](auto&& v) { + return requires + { + v.visit()( + std::integral_constant{}, + [](Json::Value const&, + std::integral_constant) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit()( + std::integral_constant{}, + Overload{ + [](Json::Value const& v, + std::integral_constant) { + return v["value"].asInt(); + }, + [](Json::Value&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visit( + std::integral_constant{}, + [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit( + std::integral_constant{}, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + static_assert([](auto&& v) { + return requires + { + v.visit()( + std::integral_constant{}, + [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit()( + std::integral_constant{}, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visit(1, [](Json::Value&, unsigned) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit( + 3u, + Overload{ + [](Json::Value& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, unsigned) { return 0; }, + [](Json::Value&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 5); + static_assert([](auto&& v) { + return requires + { + v.visit()(1, [](Json::Value&, unsigned) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit()( + 3u, + Overload{ + [](Json::Value& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, unsigned) { return 0; }, + [](Json::Value&, auto) { return 0; }, + [](auto, auto) { return 0; }}) == 5); + + static_assert([](auto&& v) { + return requires + { + v.visit(1, [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit( + 3, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 5); + static_assert([](auto&& v) { + return requires + { + v.visit()(1, [](Json::Value&) {}); + }; + }(s1)); + BEAST_EXPECT( + s1.visit()( + 3, + Overload{ + [](Json::Value& v) { return v["value"].asInt(); }, + [](Json::Value const&) { return 0; }, + [](auto...) { return 0; }}) == 5); + + static_assert([](auto&& v) { + return requires + { + v.visit(1, [](Json::Value const&, unsigned) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit( + 2u, + Overload{ + [](Json::Value const& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](Json::Value&, unsigned) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + static_assert([](auto&& v) { + return requires + { + v.visit()(1, [](Json::Value const&, unsigned) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit()( + 2u, + Overload{ + [](Json::Value const& v, unsigned) { + return v["value"].asInt(); + }, + [](Json::Value const&, auto) { return 0; }, + [](Json::Value&, unsigned) { return 0; }, + [](auto, auto) { return 0; }}) == 3); + + static_assert([](auto&& v) { + return requires + { + v.visit(1, [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit( + 2, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + static_assert([](auto&& v) { + return requires + { + v.visit()(1, [](Json::Value const&) {}); + }; + }(std::as_const(s1))); + BEAST_EXPECT( + std::as_const(s1).visit()( + 2, + Overload{ + [](Json::Value const& v) { return v["value"].asInt(); }, + [](Json::Value&) { return 0; }, + [](auto...) { return 0; }}) == 3); + + // Rvalue MultivarJson visitor only binds to regular reference + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit(1, [](Json::Value&&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit( + 1, [](Json::Value const&&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit(1, [](Json::Value&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit( + 1, [](Json::Value const&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit()( + 1, [](Json::Value&&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit()( + 1, [](Json::Value const&&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit()( + 1, [](Json::Value&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit()( + 1, [](Json::Value const&) {}); + }; + }(std::move(s1))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit( + 1, [](Json::Value const&&) {}); + }; + }(std::move(std::as_const(s1)))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit( + 1, [](Json::Value const&) {}); + }; + }(std::move(std::as_const(s1)))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit()( + 1, [](Json::Value const&&) {}); + }; + }(std::move(std::as_const(s1)))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit()( + 1, [](Json::Value const&) {}); + }; + }(std::move(std::as_const(s1)))); + + // Missing const + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit( + 1, [](Json::Value&, auto) {}); + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit()( + 1, [](Json::Value&, auto) {}); + }; + }(std::as_const(s1))); + + // Missing parameter + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit(1, []() {}); + }; + }(s1)); + static_assert([](auto&& v) { + return !requires + { + std::forward(v).visit()(1, []() {}); + }; + }(s1)); + + // Sanity checks + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit(1, [](auto...) {}); + }; + }(std::as_const(s1))); + static_assert([](auto&& v) { + return requires + { + std::forward(v).visit()(1, [](auto...) {}); + }; + }(std::as_const(s1))); + } + } +}; + +BEAST_DEFINE_TESTSUITE(MultiApiJson, protocol, ripple); + +} // namespace test +} // namespace ripple diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index 640b774f525..6601996925e 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -734,7 +734,7 @@ class AccountTx_test : public beast::unit_test::suite void run() override { - test::jtx::forAllApiVersions( + forAllApiVersions( std::bind_front(&AccountTx_test::testParameters, this)); testContents(); testAccountDelete(); diff --git a/src/test/rpc/GatewayBalances_test.cpp b/src/test/rpc/GatewayBalances_test.cpp index 091b9f51686..4c6ec9aaf1b 100644 --- a/src/test/rpc/GatewayBalances_test.cpp +++ b/src/test/rpc/GatewayBalances_test.cpp @@ -172,10 +172,7 @@ class GatewayBalances_test : public beast::unit_test::suite qry2[jss::account] = alice.human(); qry2[jss::hotwallet] = "asdf"; - for (auto apiVersion = RPC::apiMinimumSupportedVersion; - apiVersion <= RPC::apiBetaVersion; - ++apiVersion) - { + forAllApiVersions([&, this](unsigned apiVersion) { qry2[jss::api_version] = apiVersion; auto jv = wsc->invoke("gateway_balances", qry2); expect(jv[jss::status] == "error"); @@ -184,7 +181,7 @@ class GatewayBalances_test : public beast::unit_test::suite auto const error = apiVersion < 2u ? "invalidHotWallet" : "invalidParams"; BEAST_EXPECT(response[jss::error] == error); - } + }); } void diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 2b4d8527a64..877b8ef2a02 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -2305,7 +2305,7 @@ class LedgerRPC_test : public beast::unit_test::suite testLedgerAccountsOption(); testLedgerEntryDID(); - test::jtx::forAllApiVersions(std::bind_front( + forAllApiVersions(std::bind_front( &LedgerRPC_test::testLedgerEntryInvalidParams, this)); } }; diff --git a/src/test/rpc/LedgerRequestRPC_test.cpp b/src/test/rpc/LedgerRequestRPC_test.cpp index a1f3daafb30..6c59e72c4b8 100644 --- a/src/test/rpc/LedgerRequestRPC_test.cpp +++ b/src/test/rpc/LedgerRequestRPC_test.cpp @@ -359,7 +359,7 @@ class LedgerRequestRPC_test : public beast::unit_test::suite { testLedgerRequest(); testEvolution(); - test::jtx::forAllApiVersions( + forAllApiVersions( std::bind_front(&LedgerRequestRPC_test::testBadInput, this)); testMoreThan256Closed(); testNonAdmin(); diff --git a/src/test/rpc/NoRipple_test.cpp b/src/test/rpc/NoRipple_test.cpp index 3077b06f8a3..8da80e6483c 100644 --- a/src/test/rpc/NoRipple_test.cpp +++ b/src/test/rpc/NoRipple_test.cpp @@ -284,12 +284,9 @@ class NoRipple_test : public beast::unit_test::suite testSetAndClear(); auto withFeatsTests = [this](FeatureBitset features) { - for (auto testVersion = RPC::apiMinimumSupportedVersion; - testVersion <= RPC::apiBetaVersion; - ++testVersion) - { + forAllApiVersions([&, this](unsigned testVersion) { testDefaultRipple(features, testVersion); - } + }); testNegativeBalance(features); testPairwise(features); }; diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 5f66250b103..09096ba76af 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -6219,8 +6219,7 @@ class RPCCall_test : public beast::unit_test::suite void run() override { - test::jtx::forAllApiVersions( - std::bind_front(&RPCCall_test::testRPCCall, this)); + forAllApiVersions(std::bind_front(&RPCCall_test::testRPCCall, this)); } }; diff --git a/src/test/rpc/TransactionEntry_test.cpp b/src/test/rpc/TransactionEntry_test.cpp index 90c643700c4..5eddb640cbf 100644 --- a/src/test/rpc/TransactionEntry_test.cpp +++ b/src/test/rpc/TransactionEntry_test.cpp @@ -388,7 +388,7 @@ class TransactionEntry_test : public beast::unit_test::suite run() override { testBadInput(); - test::jtx::forAllApiVersions( + forAllApiVersions( std::bind_front(&TransactionEntry_test::testRequest, this)); } }; diff --git a/src/test/rpc/Transaction_test.cpp b/src/test/rpc/Transaction_test.cpp index 9fbda07c789..ac02dd11cda 100644 --- a/src/test/rpc/Transaction_test.cpp +++ b/src/test/rpc/Transaction_test.cpp @@ -849,7 +849,7 @@ class Transaction_test : public beast::unit_test::suite run() override { using namespace test::jtx; - test::jtx::forAllApiVersions( + forAllApiVersions( std::bind_front(&Transaction_test::testBinaryRequest, this)); FeatureBitset const all{supported_amendments()}; @@ -863,7 +863,7 @@ class Transaction_test : public beast::unit_test::suite testRangeCTIDRequest(features); testCTIDValidation(features); testCTIDRPC(features); - test::jtx::forAllApiVersions( + forAllApiVersions( std::bind_front(&Transaction_test::testRequest, this, features)); } }; diff --git a/src/test/rpc/Version_test.cpp b/src/test/rpc/Version_test.cpp index 60ffd30fcf6..34e55b2be93 100644 --- a/src/test/rpc/Version_test.cpp +++ b/src/test/rpc/Version_test.cpp @@ -83,7 +83,8 @@ class Version_test : public beast::unit_test::suite "{\"api_version\": " + std::to_string( std::max( - RPC::apiMaximumSupportedVersion, RPC::apiBetaVersion) + + RPC::apiMaximumSupportedVersion.value, + RPC::apiBetaVersion.value) + 1) + "}"); BEAST_EXPECT(badVersion(re)); @@ -112,15 +113,15 @@ class Version_test : public beast::unit_test::suite Json::Value j_object = Json::Value(Json::objectValue); BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); - j_object[jss::api_version] = RPC::apiVersionIfUnspecified; + j_object[jss::api_version] = RPC::apiVersionIfUnspecified.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); - j_object[jss::api_version] = RPC::apiMinimumSupportedVersion; + j_object[jss::api_version] = RPC::apiMinimumSupportedVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiMinimumSupportedVersion); - j_object[jss::api_version] = RPC::apiMaximumSupportedVersion; + j_object[jss::api_version] = RPC::apiMaximumSupportedVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiMaximumSupportedVersion); @@ -133,14 +134,14 @@ class Version_test : public beast::unit_test::suite BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); - j_object[jss::api_version] = RPC::apiBetaVersion; + j_object[jss::api_version] = RPC::apiBetaVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, true) == RPC::apiBetaVersion); j_object[jss::api_version] = RPC::apiBetaVersion + 1; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, true) == RPC::apiInvalidVersion); - j_object[jss::api_version] = RPC::apiInvalidVersion; + j_object[jss::api_version] = RPC::apiInvalidVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); @@ -202,17 +203,17 @@ class Version_test : public beast::unit_test::suite "\"id\": 5, " "\"method\": \"version\", " "\"params\": {}}"; - auto const with_wrong_api_verion = - std::string("{ ") + + auto const with_wrong_api_verion = std::string("{ ") + "\"jsonrpc\": \"2.0\", " "\"ripplerpc\": \"2.0\", " "\"id\": 6, " "\"method\": \"version\", " "\"params\": { " "\"api_version\": " + - std::to_string( - std::max(RPC::apiMaximumSupportedVersion, RPC::apiBetaVersion) + - 1) + + std::to_string(std::max( + RPC::apiMaximumSupportedVersion.value, + RPC::apiBetaVersion.value) + + 1) + "}}"; auto re = env.rpc( "json2", @@ -275,8 +276,9 @@ class Version_test : public beast::unit_test::suite jrr[jss::version].isMember(jss::last)) return; BEAST_EXPECT( - jrr[jss::version][jss::first] == RPC::apiMinimumSupportedVersion); - BEAST_EXPECT(jrr[jss::version][jss::last] == RPC::apiBetaVersion); + jrr[jss::version][jss::first] == + RPC::apiMinimumSupportedVersion.value); + BEAST_EXPECT(jrr[jss::version][jss::last] == RPC::apiBetaVersion.value); } public: