mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-02 16:26:37 +00:00
Merge branch 'dev' into cli-definitions-output
This commit is contained in:
2
.github/workflows/clang-format.yml
vendored
2
.github/workflows/clang-format.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-format-${CLANG_VERSION}
|
||||
- name: Format first-party sources
|
||||
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -not -path "src/magic/magic_enum.h" -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
- name: Check for differences
|
||||
id: assert
|
||||
run: |
|
||||
|
||||
@@ -18,6 +18,10 @@ jobs:
|
||||
generator: bash ./hook/generate_sfcodes.sh
|
||||
- target: hook/tts.h
|
||||
generator: ./hook/generate_tts.sh
|
||||
- target: hook/ls_flags.h
|
||||
generator: ./hook/generate_lsflags.sh
|
||||
- target: hook/tx_flags.h
|
||||
generator: ./hook/generate_txflags.sh
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
CLANG_VERSION: 18
|
||||
|
||||
@@ -122,6 +122,7 @@ endif()
|
||||
find_package(nudb REQUIRED)
|
||||
find_package(date REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
find_package(magic_enum REQUIRED)
|
||||
|
||||
include(deps/WasmEdge)
|
||||
if(TARGET nudb::core)
|
||||
|
||||
@@ -380,6 +380,7 @@ function(setup_target_for_coverage_gcovr)
|
||||
${GCOVR_PATH}
|
||||
--gcov-executable ${GCOV_TOOL}
|
||||
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
|
||||
--gcov-ignore-parse-errors=suspicious_hits.warn_once_per_file
|
||||
-r ${BASEDIR}
|
||||
${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS}
|
||||
|
||||
@@ -54,6 +54,7 @@ add_library(xrpl.imports.main INTERFACE)
|
||||
target_link_libraries(xrpl.imports.main
|
||||
INTERFACE
|
||||
LibArchive::LibArchive
|
||||
magic_enum::magic_enum
|
||||
OpenSSL::Crypto
|
||||
Ripple::boost
|
||||
wasmedge::wasmedge
|
||||
|
||||
@@ -29,6 +29,7 @@ class Xrpl(ConanFile):
|
||||
'date/3.0.3',
|
||||
'grpc/1.50.1',
|
||||
'libarchive/3.7.6',
|
||||
'magic_enum/0.9.5',
|
||||
'nudb/2.0.8',
|
||||
'openssl/3.6.0',
|
||||
'soci/4.0.3@xahaud/stable',
|
||||
|
||||
82
hook/generate_lsflags.sh
Executable file
82
hook/generate_lsflags.sh
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd)
|
||||
|
||||
RIPPLED_ROOT="$SCRIPT_DIR/../include/xrpl"
|
||||
LEDGER_FORMATS="$RIPPLED_ROOT/protocol/LedgerFormats.h"
|
||||
|
||||
echo '// Generated using generate_lsflags.sh'
|
||||
echo ''
|
||||
echo '#ifndef HOOKLSFLAGS_INCLUDED'
|
||||
echo '#define HOOKLSFLAGS_INCLUDED 1'
|
||||
echo ''
|
||||
awk '
|
||||
function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
|
||||
function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s }
|
||||
function trim(s) { return rtrim(ltrim(s)) }
|
||||
|
||||
function flush_group() {
|
||||
if (entry_count > 0 && group != "") {
|
||||
printf "enum %s {\n", group
|
||||
for (i = 1; i <= entry_count; i++) {
|
||||
printf " %s,\n", entries[i]
|
||||
}
|
||||
printf "};\n"
|
||||
}
|
||||
delete entries
|
||||
entry_count = 0
|
||||
}
|
||||
|
||||
/enum LedgerSpecificFlags \{/ { inside = 1; next }
|
||||
inside && /^\};/ { inside = 0; flush_group(); next }
|
||||
!inside { next }
|
||||
|
||||
# Group header comments: // ltFOO or // remarks
|
||||
/^[[:space:]]*\/\/[[:space:]]*(lt[A-Z_]+|remarks)[[:space:]]*$/ {
|
||||
flush_group()
|
||||
line = $0
|
||||
sub(/.*\/\/[[:space:]]*/, "", line)
|
||||
group = trim(line)
|
||||
next
|
||||
}
|
||||
|
||||
# Skip pure comment lines (not group headers)
|
||||
/^[[:space:]]*\/\// { next }
|
||||
|
||||
# Skip blank lines
|
||||
/^[[:space:]]*$/ { next }
|
||||
|
||||
# Accumulate flag lines (handle multi-line values)
|
||||
{
|
||||
line = $0
|
||||
# Strip inline comments
|
||||
sub(/\/\/.*/, "", line)
|
||||
line = trim(line)
|
||||
if (line == "") next
|
||||
|
||||
if (pending != "") {
|
||||
pending = pending " " line
|
||||
} else {
|
||||
pending = line
|
||||
}
|
||||
|
||||
# If line ends with comma, the entry is complete
|
||||
if (pending ~ /,$/) {
|
||||
# Remove trailing comma
|
||||
sub(/,$/, "", pending)
|
||||
entries[++entry_count] = pending
|
||||
pending = ""
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
inside = 0
|
||||
group = ""
|
||||
pending = ""
|
||||
entry_count = 0
|
||||
}
|
||||
' "$LEDGER_FORMATS"
|
||||
echo ''
|
||||
echo '#endif // HOOKLSFLAGS_INCLUDED'
|
||||
25
hook/generate_txflags.sh
Executable file
25
hook/generate_txflags.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd)
|
||||
|
||||
RIPPLED_ROOT="$SCRIPT_DIR/../include/xrpl"
|
||||
TX_FLAGS="$RIPPLED_ROOT/protocol/TxFlags.h"
|
||||
|
||||
echo '// Generated using generate_txflags.sh'
|
||||
echo '#include "ls_flags.h"'
|
||||
echo '#include <stdint.h>'
|
||||
echo ''
|
||||
cat "$TX_FLAGS" |
|
||||
awk '
|
||||
/^[[:space:]]*enum / {
|
||||
if (count > 0) print ""
|
||||
inside = 1
|
||||
count++
|
||||
}
|
||||
inside {
|
||||
print
|
||||
if (/};/) inside = 0
|
||||
}
|
||||
'
|
||||
@@ -49,4 +49,7 @@
|
||||
#include "macro.h"
|
||||
#include "tts.h"
|
||||
|
||||
#include "ls_flags.h"
|
||||
#include "tx_flags.h"
|
||||
|
||||
#endif
|
||||
|
||||
75
hook/ls_flags.h
Normal file
75
hook/ls_flags.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Generated using generate_lsflags.sh
|
||||
|
||||
#ifndef HOOKLSFLAGS_INCLUDED
|
||||
#define HOOKLSFLAGS_INCLUDED 1
|
||||
|
||||
enum ltACCOUNT_ROOT {
|
||||
lsfPasswordSpent = 0x00010000,
|
||||
lsfRequireDestTag = 0x00020000,
|
||||
lsfRequireAuth = 0x00040000,
|
||||
lsfDisallowXRP = 0x00080000,
|
||||
lsfDisableMaster = 0x00100000,
|
||||
lsfNoFreeze = 0x00200000,
|
||||
lsfGlobalFreeze = 0x00400000,
|
||||
lsfDefaultRipple = 0x00800000,
|
||||
lsfDepositAuth = 0x01000000,
|
||||
lsfTshCollect = 0x02000000,
|
||||
lsfDisallowIncomingNFTokenOffer = 0x04000000,
|
||||
lsfDisallowIncomingCheck = 0x08000000,
|
||||
lsfDisallowIncomingPayChan = 0x10000000,
|
||||
lsfDisallowIncomingTrustline = 0x20000000,
|
||||
lsfURITokenIssuer = 0x40000000,
|
||||
lsfDisallowIncomingRemit = 0x80000000,
|
||||
lsfAllowTrustLineClawback = 0x00001000,
|
||||
};
|
||||
enum ltOFFER {
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000,
|
||||
};
|
||||
enum ltRIPPLE_STATE {
|
||||
lsfLowReserve = 0x00010000,
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
lsfLowNoRipple = 0x00100000,
|
||||
lsfHighNoRipple = 0x00200000,
|
||||
lsfLowFreeze = 0x00400000,
|
||||
lsfHighFreeze = 0x00800000,
|
||||
lsfLowDeepFreeze = 0x02000000,
|
||||
lsfHighDeepFreeze = 0x04000000,
|
||||
lsfAMMNode = 0x01000000,
|
||||
};
|
||||
enum ltSIGNER_LIST {
|
||||
lsfOneOwnerCount = 0x00010000,
|
||||
};
|
||||
enum ltDIR_NODE {
|
||||
lsfNFTokenBuyOffers = 0x00000001,
|
||||
lsfNFTokenSellOffers = 0x00000002,
|
||||
lsfEmittedDir = 0x00000004,
|
||||
};
|
||||
enum ltNFTOKEN_OFFER {
|
||||
lsfSellNFToken = 0x00000001,
|
||||
};
|
||||
enum ltURI_TOKEN {
|
||||
lsfBurnable = 0x00000001,
|
||||
};
|
||||
enum remarks {
|
||||
lsfImmutable = 1,
|
||||
};
|
||||
enum ltMPTOKEN_ISSUANCE {
|
||||
lsfMPTLocked = 0x00000001,
|
||||
lsfMPTCanLock = 0x00000002,
|
||||
lsfMPTRequireAuth = 0x00000004,
|
||||
lsfMPTCanEscrow = 0x00000008,
|
||||
lsfMPTCanTrade = 0x00000010,
|
||||
lsfMPTCanTransfer = 0x00000020,
|
||||
lsfMPTCanClawback = 0x00000040,
|
||||
};
|
||||
enum ltMPTOKEN {
|
||||
lsfMPTAuthorized = 0x00000002,
|
||||
};
|
||||
enum ltCREDENTIAL {
|
||||
lsfAccepted = 0x00010000,
|
||||
};
|
||||
|
||||
#endif // HOOKLSFLAGS_INCLUDED
|
||||
@@ -274,7 +274,6 @@
|
||||
#define sfDisabledValidator ((14U << 16U) + 19U)
|
||||
#define sfEmittedTxn ((14U << 16U) + 20U)
|
||||
#define sfHookExecution ((14U << 16U) + 21U)
|
||||
#define sfHookDefinition ((14U << 16U) + 22U)
|
||||
#define sfHookParameter ((14U << 16U) + 23U)
|
||||
#define sfHookGrant ((14U << 16U) + 24U)
|
||||
#define sfVoteEntry ((14U << 16U) + 25U)
|
||||
|
||||
117
hook/tx_flags.h
Normal file
117
hook/tx_flags.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// Generated using generate_txflags.sh
|
||||
#include "ls_flags.h"
|
||||
#include <stdint.h>
|
||||
|
||||
enum UniversalFlags : uint32_t {
|
||||
tfFullyCanonicalSig = 0x80000000,
|
||||
};
|
||||
|
||||
enum AccountSetFlags : uint32_t {
|
||||
tfRequireDestTag = 0x00010000,
|
||||
tfOptionalDestTag = 0x00020000,
|
||||
tfRequireAuth = 0x00040000,
|
||||
tfOptionalAuth = 0x00080000,
|
||||
tfDisallowXRP = 0x00100000,
|
||||
tfAllowXRP = 0x00200000,
|
||||
};
|
||||
|
||||
enum AccountFlags : uint32_t {
|
||||
asfRequireDest = 1,
|
||||
asfRequireAuth = 2,
|
||||
asfDisallowXRP = 3,
|
||||
asfDisableMaster = 4,
|
||||
asfAccountTxnID = 5,
|
||||
asfNoFreeze = 6,
|
||||
asfGlobalFreeze = 7,
|
||||
asfDefaultRipple = 8,
|
||||
asfDepositAuth = 9,
|
||||
asfAuthorizedNFTokenMinter = 10,
|
||||
asfTshCollect = 11,
|
||||
asfDisallowIncomingNFTokenOffer = 12,
|
||||
asfDisallowIncomingCheck = 13,
|
||||
asfDisallowIncomingPayChan = 14,
|
||||
asfDisallowIncomingTrustline = 15,
|
||||
asfDisallowIncomingRemit = 16,
|
||||
asfAllowTrustLineClawback = 17,
|
||||
};
|
||||
|
||||
enum OfferCreateFlags : uint32_t {
|
||||
tfPassive = 0x00010000,
|
||||
tfImmediateOrCancel = 0x00020000,
|
||||
tfFillOrKill = 0x00040000,
|
||||
tfSell = 0x00080000,
|
||||
};
|
||||
|
||||
enum PaymentFlags : uint32_t {
|
||||
tfNoRippleDirect = 0x00010000,
|
||||
tfPartialPayment = 0x00020000,
|
||||
tfLimitQuality = 0x00040000,
|
||||
};
|
||||
|
||||
enum TrustSetFlags : uint32_t {
|
||||
tfSetfAuth = 0x00010000,
|
||||
tfSetNoRipple = 0x00020000,
|
||||
tfClearNoRipple = 0x00040000,
|
||||
tfSetFreeze = 0x00100000,
|
||||
tfClearFreeze = 0x00200000,
|
||||
tfSetDeepFreeze = 0x00400000,
|
||||
tfClearDeepFreeze = 0x00800000
|
||||
};
|
||||
|
||||
enum EnableAmendmentFlags : uint32_t {
|
||||
tfGotMajority = 0x00010000,
|
||||
tfLostMajority = 0x00020000,
|
||||
tfTestSuite = 0x80000000,
|
||||
};
|
||||
|
||||
enum PaymentChannelClaimFlags : uint32_t {
|
||||
tfRenew = 0x00010000,
|
||||
tfClose = 0x00020000,
|
||||
};
|
||||
|
||||
enum NFTokenMintFlags : uint32_t {
|
||||
tfBurnable = 0x00000001,
|
||||
tfOnlyXRP = 0x00000002,
|
||||
tfTrustLine = 0x00000004,
|
||||
tfTransferable = 0x00000008,
|
||||
tfMutable = 0x00000010,
|
||||
tfStrongTSH = 0x00008000,
|
||||
};
|
||||
|
||||
enum MPTokenIssuanceCreateFlags : uint32_t {
|
||||
tfMPTCanLock = lsfMPTCanLock,
|
||||
tfMPTRequireAuth = lsfMPTRequireAuth,
|
||||
tfMPTCanEscrow = lsfMPTCanEscrow,
|
||||
tfMPTCanTrade = lsfMPTCanTrade,
|
||||
tfMPTCanTransfer = lsfMPTCanTransfer,
|
||||
tfMPTCanClawback = lsfMPTCanClawback,
|
||||
};
|
||||
|
||||
enum MPTokenAuthorizeFlags : uint32_t {
|
||||
tfMPTUnauthorize = 0x00000001,
|
||||
};
|
||||
|
||||
enum MPTokenIssuanceSetFlags : uint32_t {
|
||||
tfMPTLock = 0x00000001,
|
||||
tfMPTUnlock = 0x00000002,
|
||||
};
|
||||
|
||||
enum NFTokenCreateOfferFlags : uint32_t {
|
||||
tfSellNFToken = 0x00000001,
|
||||
};
|
||||
|
||||
enum ClaimRewardFlags : uint32_t {
|
||||
tfOptOut = 0x00000001,
|
||||
};
|
||||
|
||||
enum CronSetFlags : uint32_t {
|
||||
tfCronUnset = 0x00000001,
|
||||
};
|
||||
|
||||
enum AMMClawbackFlags : uint32_t {
|
||||
tfClawTwoAssets = 0x00000001,
|
||||
};
|
||||
|
||||
enum BridgeModifyFlags : uint32_t {
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
};
|
||||
@@ -80,7 +80,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 = 114;
|
||||
static constexpr std::size_t numFeatures = 115;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
|
||||
@@ -132,7 +132,7 @@ constexpr std::uint32_t tfTrustSetMask =
|
||||
tfClearFreeze | tfSetDeepFreeze | tfClearDeepFreeze);
|
||||
|
||||
// EnableAmendment flags:
|
||||
enum EnableAmendmentFlags : std::uint32_t {
|
||||
enum EnableAmendmentFlags : uint32_t {
|
||||
tfGotMajority = 0x00010000,
|
||||
tfLostMajority = 0x00020000,
|
||||
tfTestSuite = 0x80000000,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FIX (IOULockedBalanceInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ImportIssuer, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -367,7 +367,7 @@ UNTYPED_SFIELD(sfMajority, OBJECT, 18)
|
||||
UNTYPED_SFIELD(sfDisabledValidator, OBJECT, 19)
|
||||
UNTYPED_SFIELD(sfEmittedTxn, OBJECT, 20)
|
||||
UNTYPED_SFIELD(sfHookExecution, OBJECT, 21)
|
||||
UNTYPED_SFIELD(sfHookDefinition, OBJECT, 22)
|
||||
// 22 unused
|
||||
UNTYPED_SFIELD(sfHookParameter, OBJECT, 23)
|
||||
UNTYPED_SFIELD(sfHookGrant, OBJECT, 24)
|
||||
UNTYPED_SFIELD(sfVoteEntry, OBJECT, 25)
|
||||
|
||||
@@ -87,19 +87,6 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfEmittedTxnID, soeREQUIRED},
|
||||
{sfEmitNonce, soeOPTIONAL}});
|
||||
|
||||
add(sfHookDefinition.jsonName,
|
||||
sfHookDefinition.getCode(),
|
||||
{{sfCreateCode, soeREQUIRED},
|
||||
{sfHookNamespace, soeREQUIRED},
|
||||
{sfHookParameters, soeREQUIRED},
|
||||
{sfHookOn, soeOPTIONAL},
|
||||
{sfHookOnIncoming, soeOPTIONAL},
|
||||
{sfHookOnOutgoing, soeOPTIONAL},
|
||||
{sfHookCanEmit, soeOPTIONAL},
|
||||
{sfHookApiVersion, soeREQUIRED},
|
||||
{sfFlags, soeREQUIRED},
|
||||
{sfFee, soeREQUIRED}});
|
||||
|
||||
add(sfHook.jsonName,
|
||||
sfHook.getCode(),
|
||||
{{sfHookHash, soeOPTIONAL},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,8 @@
|
||||
#include <test/jtx.h>
|
||||
#include <test/jtx/envconfig.h>
|
||||
#include <xrpld/app/paths/AccountCurrencies.h>
|
||||
#include <xrpld/app/paths/Pathfinder.h>
|
||||
#include <xrpld/app/paths/RippleLineCache.h>
|
||||
#include <xrpld/core/JobQueue.h>
|
||||
#include <xrpld/rpc/Context.h>
|
||||
#include <xrpld/rpc/RPCHandler.h>
|
||||
@@ -573,6 +575,164 @@ public:
|
||||
BEAST_EXPECT(equal(sa, Account("alice")["USD"](5)));
|
||||
}
|
||||
|
||||
Json::Value
|
||||
six_path_append_request_result()
|
||||
{
|
||||
using namespace jtx;
|
||||
Env env = pathTestEnv();
|
||||
|
||||
Account A1{"A1"};
|
||||
Account A2{"A2"};
|
||||
Account G1{"G1"};
|
||||
Account G2{"G2"};
|
||||
Account M1{"M1"};
|
||||
Account M2{"M2"};
|
||||
Account M3{"M3"};
|
||||
Account M4{"M4"};
|
||||
Account M5{"M5"};
|
||||
Account M6{"M6"};
|
||||
Account MM{"MM"};
|
||||
|
||||
env.fund(XRP(1000), A1, A2, G1, G2, M1, M2, M3, M4, M5, M6, MM);
|
||||
env.close();
|
||||
|
||||
env.trust(G1["HKD"](2000), A1);
|
||||
env.trust(G2["HKD"](2000), A2);
|
||||
|
||||
env.trust(G1["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
|
||||
env.trust(G2["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
|
||||
env.close();
|
||||
|
||||
env(pay(G1, A1, G1["HKD"](1000)));
|
||||
|
||||
env(pay(G1, M1, G1["HKD"](10)));
|
||||
env(pay(G1, M2, G1["HKD"](10)));
|
||||
env(pay(G1, M3, G1["HKD"](10)));
|
||||
env(pay(G1, M4, G1["HKD"](10)));
|
||||
env(pay(G1, M5, G1["HKD"](10)));
|
||||
env(pay(G1, M6, G1["HKD"](10)));
|
||||
env(pay(G1, MM, G1["HKD"](1000)));
|
||||
|
||||
env(pay(G2, M1, G2["HKD"](10)));
|
||||
env(pay(G2, M2, G2["HKD"](10)));
|
||||
env(pay(G2, M3, G2["HKD"](10)));
|
||||
env(pay(G2, M4, G2["HKD"](10)));
|
||||
env(pay(G2, M5, G2["HKD"](10)));
|
||||
env(pay(G2, M6, G2["HKD"](10)));
|
||||
env(pay(G2, MM, G2["HKD"](1000)));
|
||||
env.close();
|
||||
|
||||
env(offer(MM, G1["HKD"](1000), G2["HKD"](100)));
|
||||
env.close();
|
||||
|
||||
return find_paths_request(
|
||||
env, A1, A2, A2["HKD"](60), std::nullopt, G1["HKD"].currency);
|
||||
}
|
||||
|
||||
void
|
||||
pathfind_paths_computed_never_exceeds_six()
|
||||
{
|
||||
testcase("pathfind paths_computed never exceeds six");
|
||||
|
||||
auto const result = six_path_append_request_result();
|
||||
BEAST_EXPECT(result.isMember(jss::alternatives));
|
||||
if (!result.isMember(jss::alternatives))
|
||||
return;
|
||||
|
||||
BEAST_EXPECT(result[jss::alternatives].isArray());
|
||||
if (!result[jss::alternatives].isArray())
|
||||
return;
|
||||
|
||||
bool sawPathsComputed = false;
|
||||
for (auto const& alt : result[jss::alternatives])
|
||||
{
|
||||
if (!alt.isMember(jss::paths_computed))
|
||||
continue;
|
||||
sawPathsComputed = true;
|
||||
BEAST_EXPECT(alt[jss::paths_computed].isArray());
|
||||
if (alt[jss::paths_computed].isArray())
|
||||
BEAST_EXPECT(alt[jss::paths_computed].size() <= 6);
|
||||
}
|
||||
BEAST_EXPECT(sawPathsComputed);
|
||||
}
|
||||
|
||||
void
|
||||
pathfind_can_return_six_paths_with_append()
|
||||
{
|
||||
testcase("pathfind can return six paths with append");
|
||||
using namespace jtx;
|
||||
Env env = pathTestEnv();
|
||||
|
||||
Account A1{"A1"};
|
||||
Account A2{"A2"};
|
||||
Account G1{"G1"};
|
||||
Account G2{"G2"};
|
||||
Account M1{"M1"};
|
||||
Account M2{"M2"};
|
||||
Account M3{"M3"};
|
||||
Account M4{"M4"};
|
||||
Account M5{"M5"};
|
||||
Account M6{"M6"};
|
||||
Account MM{"MM"};
|
||||
|
||||
env.fund(XRP(1000), A1, A2, G1, G2, M1, M2, M3, M4, M5, M6, MM);
|
||||
env.close();
|
||||
|
||||
env.trust(G1["HKD"](2000), A1);
|
||||
env.trust(G2["HKD"](2000), A2);
|
||||
|
||||
env.trust(G1["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
|
||||
env.trust(G2["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
|
||||
env.close();
|
||||
|
||||
env(pay(G1, A1, G1["HKD"](1000)));
|
||||
|
||||
env(pay(G1, M1, G1["HKD"](10)));
|
||||
env(pay(G1, M2, G1["HKD"](10)));
|
||||
env(pay(G1, M3, G1["HKD"](10)));
|
||||
env(pay(G1, M4, G1["HKD"](10)));
|
||||
env(pay(G1, M5, G1["HKD"](10)));
|
||||
env(pay(G1, M6, G1["HKD"](10)));
|
||||
env(pay(G1, MM, G1["HKD"](1000)));
|
||||
|
||||
env(pay(G2, M1, G2["HKD"](10)));
|
||||
env(pay(G2, M2, G2["HKD"](10)));
|
||||
env(pay(G2, M3, G2["HKD"](10)));
|
||||
env(pay(G2, M4, G2["HKD"](10)));
|
||||
env(pay(G2, M5, G2["HKD"](10)));
|
||||
env(pay(G2, M6, G2["HKD"](10)));
|
||||
env(pay(G2, MM, G2["HKD"](1000)));
|
||||
env.close();
|
||||
|
||||
env(offer(MM, G1["HKD"](1000), G2["HKD"](100)));
|
||||
env.close();
|
||||
|
||||
auto cache = std::make_shared<RippleLineCache>(
|
||||
env.current(), env.app().journal("RippleLineCache"));
|
||||
Pathfinder pf(
|
||||
cache,
|
||||
A1.id(),
|
||||
A2.id(),
|
||||
G1["HKD"].currency,
|
||||
std::nullopt,
|
||||
A2["HKD"](60),
|
||||
std::nullopt,
|
||||
env.app());
|
||||
|
||||
BEAST_EXPECT(pf.findPaths(7));
|
||||
pf.computePathRanks(5);
|
||||
|
||||
STPath fullLiquidityPath;
|
||||
auto bestPaths =
|
||||
pf.getBestPaths(5, fullLiquidityPath, STPathSet{}, A1.id());
|
||||
BEAST_EXPECT(bestPaths.size() == 5);
|
||||
BEAST_EXPECT(!fullLiquidityPath.empty());
|
||||
|
||||
if (!fullLiquidityPath.empty())
|
||||
bestPaths.push_back(fullLiquidityPath);
|
||||
BEAST_EXPECT(bestPaths.size() == 6);
|
||||
}
|
||||
|
||||
void
|
||||
issues_path_negative_issue()
|
||||
{
|
||||
@@ -1381,6 +1541,8 @@ public:
|
||||
path_find_04();
|
||||
path_find_05();
|
||||
path_find_06();
|
||||
pathfind_paths_computed_never_exceeds_six();
|
||||
pathfind_can_return_six_paths_with_append();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <regex>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -137,7 +136,9 @@ class Invariants_test : public beast::unit_test::suite
|
||||
if (sink.messages().str().find(m) == std::string::npos)
|
||||
{
|
||||
// uncomment if you want to log the invariant failure
|
||||
// message log << " --> " << m << std::endl;
|
||||
// message
|
||||
// log << sink.messages().str() << std::endl;
|
||||
// log << " --> " << m << std::endl;
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -1233,6 +1234,42 @@ class Invariants_test : public beast::unit_test::suite
|
||||
{tecINVARIANT_FAILED, tecINVARIANT_FAILED});
|
||||
}
|
||||
|
||||
void
|
||||
testLockedBalance()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
testcase << "ValidLockedBalance";
|
||||
|
||||
doInvariantCheck(
|
||||
{{"Invariant failed: IOU locked balance is greater than balance"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
IOU const USD{A2["USD"]};
|
||||
auto const sle =
|
||||
std::make_shared<SLE>(keylet::line(A1, A2, USD.currency));
|
||||
sle->setFieldAmount(sfHighLimit, A1["USD"](100));
|
||||
sle->setFieldAmount(sfLowLimit, A2["USD"](100));
|
||||
sle->setFieldAmount(sfBalance, USD(100));
|
||||
sle->setFieldAmount(sfLockedBalance, USD(101));
|
||||
ac.view().insert(sle);
|
||||
return true;
|
||||
});
|
||||
|
||||
doInvariantCheck(
|
||||
{{"Invariant failed: IOU locked balance is greater than balance"}},
|
||||
[&](Account const& A1, Account const& A2, ApplyContext& ac) {
|
||||
IOU const USD{A2["USD"]};
|
||||
auto const sle =
|
||||
std::make_shared<SLE>(keylet::line(A1, A2, USD.currency));
|
||||
sle->setFieldAmount(sfHighLimit, A1["USD"](100));
|
||||
sle->setFieldAmount(sfLowLimit, A2["USD"](100));
|
||||
sle->setFieldAmount(sfBalance, USD(-100));
|
||||
sle->setFieldAmount(sfLockedBalance, USD(-101));
|
||||
ac.view().insert(sle);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
@@ -1251,6 +1288,7 @@ public:
|
||||
testValidNewAccountRoot();
|
||||
testNFTokenPageInvariants();
|
||||
testPermissionedDomainInvariants();
|
||||
testLockedBalance();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ class Hooks_test : public beast::unit_test::suite
|
||||
sfHookAccount,
|
||||
sfEmittedTxn,
|
||||
sfHook,
|
||||
sfHookDefinition,
|
||||
sfHookParameter,
|
||||
sfHookGrant,
|
||||
sfEmitDetails,
|
||||
|
||||
@@ -170,7 +170,7 @@ private:
|
||||
std::chrono::steady_clock::time_point quick_reply_;
|
||||
std::chrono::steady_clock::time_point full_reply_;
|
||||
|
||||
static unsigned int const max_paths_ = 4;
|
||||
static unsigned int const max_paths_ = 5;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -1324,11 +1324,13 @@ Pathfinder::initPathTable()
|
||||
|
||||
fillPaths(
|
||||
pt_nonXRP_to_XRP,
|
||||
{{1, "sxd"}, // gateway buys XRP
|
||||
{2, "saxd"}, // source -> gateway -> book(XRP) -> dest
|
||||
{{1, "sxd"}, // gateway buys XRP
|
||||
{2, "saxd"}, // source -> gateway -> book(XRP) -> dest
|
||||
{5, "sabxd"}, // source -> gateway -> book -> book(XRP) -> dest
|
||||
{6, "saaxd"},
|
||||
{7, "sbxd"},
|
||||
{8, "sabxd"},
|
||||
{8,
|
||||
"sabbxd"}, // source -> gateway -> book -> book -> book(XRP) -> dest
|
||||
{9, "sabaxd"}});
|
||||
|
||||
// non-XRP to non-XRP (same currency)
|
||||
|
||||
@@ -1982,4 +1982,44 @@ ValidAMM::finalize(
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ValidLockedBalance::visitEntry(
|
||||
bool,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)
|
||||
{
|
||||
if (after && after->getType() == ltRIPPLE_STATE &&
|
||||
after->isFieldPresent(sfLockedBalance))
|
||||
{
|
||||
iouIOULockedBalanceAfter_ = (*after)[sfLockedBalance];
|
||||
iouIOUBalanceAfter_ = (*after)[sfBalance];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ValidLockedBalance::finalize(
|
||||
STTx const& tx,
|
||||
TER const result,
|
||||
XRPAmount const,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
if (!view.rules().enabled(fixIOULockedBalanceInvariant))
|
||||
return true;
|
||||
|
||||
if (iouIOULockedBalanceAfter_)
|
||||
{
|
||||
if ((!iouIOULockedBalanceAfter_->negative() &&
|
||||
*iouIOULockedBalanceAfter_ > *iouIOUBalanceAfter_) ||
|
||||
(iouIOULockedBalanceAfter_->negative() &&
|
||||
*iouIOULockedBalanceAfter_ < *iouIOUBalanceAfter_))
|
||||
{
|
||||
JLOG(j.fatal()) << "Invariant failed: IOU locked balance is "
|
||||
"greater than balance";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace ripple
|
||||
|
||||
@@ -680,6 +680,30 @@ private:
|
||||
beast::Journal const&) const;
|
||||
};
|
||||
|
||||
class ValidLockedBalance
|
||||
{
|
||||
std::optional<STAmount> iouIOULockedBalanceAfter_;
|
||||
std::optional<STAmount> iouIOUBalanceAfter_;
|
||||
|
||||
public:
|
||||
ValidLockedBalance()
|
||||
{
|
||||
}
|
||||
void
|
||||
visitEntry(
|
||||
bool,
|
||||
std::shared_ptr<SLE const> const&,
|
||||
std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(
|
||||
STTx const&,
|
||||
TER const,
|
||||
XRPAmount const,
|
||||
ReadView const&,
|
||||
beast::Journal const&);
|
||||
};
|
||||
|
||||
// additional invariant checks can be declared above and then added to this
|
||||
// tuple
|
||||
using InvariantChecks = std::tuple<
|
||||
@@ -700,7 +724,8 @@ using InvariantChecks = std::tuple<
|
||||
ValidClawback,
|
||||
ValidMPTIssuance,
|
||||
ValidPermissionedDomain,
|
||||
ValidAMM>;
|
||||
ValidAMM,
|
||||
ValidLockedBalance>;
|
||||
|
||||
/**
|
||||
* @brief get a tuple of all invariant checks
|
||||
|
||||
@@ -425,7 +425,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj)
|
||||
JLOG(ctx.j.trace())
|
||||
<< "HookSet(" << hook::log::NAMESPACE_MISSING << ")["
|
||||
<< HS_ACC()
|
||||
<< "]: Malformed transaction: SetHook sfHookDefinition "
|
||||
<< "]: Malformed transaction: SetHook ltHookDefinition "
|
||||
"must contain sfHookNamespace.";
|
||||
return false;
|
||||
}
|
||||
@@ -2001,7 +2001,7 @@ SetHook::setHook()
|
||||
// sfHookHash, sfHookNamespace, sfHookOn, sfHookOnOutgoing,
|
||||
// sfHookOnIncoming, sfHookCanEmit sfHookApiVersion, sfFlags: free
|
||||
|
||||
// sfHookDefinition is not reserved because it is an unowned object,
|
||||
// ltHookDefinition is not reserved because it is an unowned object,
|
||||
// rather the uploader is billed via fee according to the following:
|
||||
// sfCreateCode: 5000 drops per byte
|
||||
// sfHookParameters: 5000 drops per byte
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <magic/magic_enum.h>
|
||||
#include <magic_enum.hpp>
|
||||
#include <sstream>
|
||||
|
||||
#define MAGIC_ENUM(x, _min, _max) \
|
||||
|
||||
Reference in New Issue
Block a user