mirror of
https://github.com/XRPLF/rippled.git
synced 2026-02-08 07:52:29 +00:00
Compare commits
9 Commits
zhang/grot
...
pratik/Rem
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
060eff0cf4 | ||
|
|
0a41305a75 | ||
|
|
d9960d5ba0 | ||
|
|
91fa6b2295 | ||
|
|
76f774e22d | ||
|
|
f4f7618173 | ||
|
|
66f16469f9 | ||
|
|
1845b1c656 | ||
|
|
e192ffe964 |
@@ -138,6 +138,7 @@ test.toplevel > test.csf
|
||||
test.toplevel > xrpl.json
|
||||
test.unit_test > xrpl.basics
|
||||
tests.libxrpl > xrpl.basics
|
||||
tests.libxrpl > xrpl.json
|
||||
tests.libxrpl > xrpl.net
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@a8d7472b450eb53a1e5228f64552e5974457a21a
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'
|
||||
|
||||
18
.github/workflows/reusable-build.yml
vendored
18
.github/workflows/reusable-build.yml
vendored
@@ -101,11 +101,27 @@ jobs:
|
||||
--parallel $(nproc) \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Put built binaries in one location
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE_DIR: ${{ runner.os == 'Windows' && inputs.build_type || '' }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
mkdir -p ./binaries/doctest/
|
||||
|
||||
cp ./${BUILD_TYPE_DIR}/rippled* ./binaries/
|
||||
if [ "${CMAKE_TARGET}" != 'coverage' ]; then
|
||||
cp ./src/tests/libxrpl/${BUILD_TYPE_DIR}/xrpl.test.* ./binaries/doctest/
|
||||
fi
|
||||
|
||||
- name: Upload rippled artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
path: ${{ inputs.build_dir }}/${{ runner.os == 'Windows' && inputs.build_type || '' }}/rippled${{ runner.os == 'Windows' && '.exe' || '' }}
|
||||
path: ${{ env.BUILD_DIR }}/binaries/
|
||||
retention-days: 3
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
23
.github/workflows/reusable-test.yml
vendored
23
.github/workflows/reusable-test.yml
vendored
@@ -33,6 +33,10 @@ jobs:
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- name: Download rippled artifact
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
@@ -62,9 +66,24 @@ jobs:
|
||||
run: |
|
||||
./rippled --version | grep libvoidstar
|
||||
|
||||
- name: Test the binary
|
||||
- name: Run the embedded tests
|
||||
if: ${{ inputs.run_tests }}
|
||||
shell: bash
|
||||
run: |
|
||||
./rippled --unittest --unittest-jobs $(nproc)
|
||||
ctest -j $(nproc) --output-on-failure
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ inputs.run_tests }}
|
||||
env:
|
||||
EXT: ${{ runner.os == 'Windows' && '.exe' || '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
for test_file in ./doctest/*${EXT}; do
|
||||
echo "Executing $test_file"
|
||||
chmod +x "$test_file"
|
||||
if [[ "${{ runner.os }}" == "Windows" && "$test_file" == "./doctest/xrpl.test.net.exe" ]]; then
|
||||
echo "Skipping $test_file on Windows"
|
||||
else
|
||||
"$test_file"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -7,7 +7,7 @@ function(xrpl_add_test name)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
|
||||
)
|
||||
add_executable(${target} EXCLUDE_FROM_ALL ${ARGN} ${sources})
|
||||
add_executable(${target} ${ARGN} ${sources})
|
||||
|
||||
isolate_headers(
|
||||
${target}
|
||||
|
||||
@@ -21,11 +21,11 @@ compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
|
||||
|
||||
[conf]
|
||||
{% if compiler == "clang" and compiler_version >= 19 %}
|
||||
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "apple-clang" and compiler_version >= 17 %}
|
||||
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "gcc" and compiler_version < 13 %}
|
||||
tools.build:cxxflags=['-Wno-restrict']
|
||||
tools.build:cxxflags+=['-Wno-restrict']
|
||||
{% endif %}
|
||||
|
||||
@@ -211,18 +211,13 @@ constexpr std::uint32_t const tfMPTokenIssuanceDestroyMask = ~tfUniversal;
|
||||
// issuer's reserve without bound.
|
||||
//
|
||||
// The fixRemoveNFTokenAutoTrustLine amendment disables minting with the
|
||||
// tfTrustLine flag as a way to prevent the attack. But until the
|
||||
// amendment passes we still need to keep the old behavior available.
|
||||
// tfTrustLine flag as a way to prevent the attack. Since the amendment
|
||||
// has passed, we don't include tfTrustLine flag in tfNFTokenMintMask anymore.
|
||||
|
||||
constexpr std::uint32_t const tfNFTokenMintMask =
|
||||
~(tfUniversal | tfBurnable | tfOnlyXRP | tfTransferable);
|
||||
|
||||
constexpr std::uint32_t const tfNFTokenMintOldMask =
|
||||
~( ~tfNFTokenMintMask | tfTrustLine);
|
||||
|
||||
// if featureDynamicNFT enabled then new flag allowing mutable URI available.
|
||||
constexpr std::uint32_t const tfNFTokenMintOldMaskWithMutable =
|
||||
~( ~tfNFTokenMintOldMask | tfMutable);
|
||||
|
||||
// if featureDynamicNFT enabled then flag allowing mutable URI available.
|
||||
constexpr std::uint32_t const tfNFTokenMintMaskWithMutable =
|
||||
~( ~tfNFTokenMintMask | tfMutable);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo
|
||||
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -86,7 +86,6 @@ XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo
|
||||
XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(ImmediateOfferKilled, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (TrustLinesToSelf, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(NonFungibleTokensV1_1, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(ExpandedSignerList, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -111,7 +110,6 @@ XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYe
|
||||
XRPL_FIX (1578, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (1623, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (1543, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (1571, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes)
|
||||
@@ -155,3 +153,5 @@ XRPL_RETIRE(fix1528)
|
||||
XRPL_RETIRE(FlowCross)
|
||||
XRPL_RETIRE(fix1513)
|
||||
XRPL_RETIRE(fix1515)
|
||||
XRPL_RETIRE(fix1543)
|
||||
XRPL_RETIRE(fixRemoveNFTokenAutoTrustLine)
|
||||
|
||||
@@ -1621,180 +1621,78 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
|
||||
IOU const gwCAD(gw["CAD"]);
|
||||
IOU const gwEUR(gw["EUR"]);
|
||||
|
||||
// The behavior of this test changes dramatically based on the
|
||||
// presence (or absence) of the fixRemoveNFTokenAutoTrustLine
|
||||
// amendment. So we test both cases here.
|
||||
for (auto const& tweakedFeatures :
|
||||
{features - fixRemoveNFTokenAutoTrustLine,
|
||||
features | fixRemoveNFTokenAutoTrustLine})
|
||||
Env env{*this, features};
|
||||
env.fund(XRP(1000), alice, becky, cheri, gw);
|
||||
env.close();
|
||||
|
||||
// Set trust lines so becky and cheri can use gw's currency.
|
||||
env(trust(becky, gwAUD(1000)));
|
||||
env(trust(cheri, gwAUD(1000)));
|
||||
env(trust(becky, gwCAD(1000)));
|
||||
env(trust(cheri, gwCAD(1000)));
|
||||
env(trust(becky, gwEUR(1000)));
|
||||
env(trust(cheri, gwEUR(1000)));
|
||||
env.close();
|
||||
env(pay(gw, becky, gwAUD(500)));
|
||||
env(pay(gw, becky, gwCAD(500)));
|
||||
env(pay(gw, becky, gwEUR(500)));
|
||||
env(pay(gw, cheri, gwAUD(500)));
|
||||
env(pay(gw, cheri, gwCAD(500)));
|
||||
env.close();
|
||||
|
||||
// An nft without flagCreateTrustLines but with a non-zero transfer
|
||||
// fee will not allow creating offers that use IOUs for payment.
|
||||
for (std::uint32_t xferFee : {0, 1})
|
||||
{
|
||||
Env env{*this, tweakedFeatures};
|
||||
env.fund(XRP(1000), alice, becky, cheri, gw);
|
||||
uint256 const nftNoAutoTrustID{
|
||||
token::getNextID(env, alice, 0u, tfTransferable, xferFee)};
|
||||
env(token::mint(alice, 0u),
|
||||
token::xferFee(xferFee),
|
||||
txflags(tfTransferable));
|
||||
env.close();
|
||||
|
||||
// Set trust lines so becky and cheri can use gw's currency.
|
||||
env(trust(becky, gwAUD(1000)));
|
||||
env(trust(cheri, gwAUD(1000)));
|
||||
env(trust(becky, gwCAD(1000)));
|
||||
env(trust(cheri, gwCAD(1000)));
|
||||
env(trust(becky, gwEUR(1000)));
|
||||
env(trust(cheri, gwEUR(1000)));
|
||||
// becky buys the nft for 1 drop.
|
||||
uint256 const beckyBuyOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
|
||||
token::owner(alice));
|
||||
env.close();
|
||||
env(pay(gw, becky, gwAUD(500)));
|
||||
env(pay(gw, becky, gwCAD(500)));
|
||||
env(pay(gw, becky, gwEUR(500)));
|
||||
env(pay(gw, cheri, gwAUD(500)));
|
||||
env(pay(gw, cheri, gwCAD(500)));
|
||||
env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
|
||||
env.close();
|
||||
|
||||
// An nft without flagCreateTrustLines but with a non-zero transfer
|
||||
// fee will not allow creating offers that use IOUs for payment.
|
||||
for (std::uint32_t xferFee : {0, 1})
|
||||
{
|
||||
uint256 const nftNoAutoTrustID{
|
||||
token::getNextID(env, alice, 0u, tfTransferable, xferFee)};
|
||||
env(token::mint(alice, 0u),
|
||||
token::xferFee(xferFee),
|
||||
txflags(tfTransferable));
|
||||
env.close();
|
||||
// becky attempts to sell the nft for AUD.
|
||||
TER const createOfferTER =
|
||||
xferFee ? TER(tecNO_LINE) : TER(tesSUCCESS);
|
||||
uint256 const beckyOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
|
||||
txflags(tfSellNFToken),
|
||||
ter(createOfferTER));
|
||||
env.close();
|
||||
|
||||
// becky buys the nft for 1 drop.
|
||||
uint256 const beckyBuyOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftNoAutoTrustID, drops(1)),
|
||||
token::owner(alice));
|
||||
env.close();
|
||||
env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
|
||||
env.close();
|
||||
// cheri offers to buy the nft for CAD.
|
||||
uint256 const cheriOfferIndex =
|
||||
keylet::nftoffer(cheri, env.seq(cheri)).key;
|
||||
env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
|
||||
token::owner(becky),
|
||||
ter(createOfferTER));
|
||||
env.close();
|
||||
|
||||
// becky attempts to sell the nft for AUD.
|
||||
TER const createOfferTER =
|
||||
xferFee ? TER(tecNO_LINE) : TER(tesSUCCESS);
|
||||
uint256 const beckyOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)),
|
||||
txflags(tfSellNFToken),
|
||||
ter(createOfferTER));
|
||||
env.close();
|
||||
|
||||
// cheri offers to buy the nft for CAD.
|
||||
uint256 const cheriOfferIndex =
|
||||
keylet::nftoffer(cheri, env.seq(cheri)).key;
|
||||
env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
|
||||
token::owner(becky),
|
||||
ter(createOfferTER));
|
||||
env.close();
|
||||
|
||||
// To keep things tidy, cancel the offers.
|
||||
env(token::cancelOffer(becky, {beckyOfferIndex}));
|
||||
env(token::cancelOffer(cheri, {cheriOfferIndex}));
|
||||
env.close();
|
||||
}
|
||||
// An nft with flagCreateTrustLines but with a non-zero transfer
|
||||
// fee allows transfers using IOUs for payment.
|
||||
{
|
||||
std::uint16_t transferFee = 10000; // 10%
|
||||
|
||||
uint256 const nftAutoTrustID{token::getNextID(
|
||||
env, alice, 0u, tfTransferable | tfTrustLine, transferFee)};
|
||||
|
||||
// If the fixRemoveNFTokenAutoTrustLine amendment is active
|
||||
// then this transaction fails.
|
||||
{
|
||||
TER const mintTER =
|
||||
tweakedFeatures[fixRemoveNFTokenAutoTrustLine]
|
||||
? static_cast<TER>(temINVALID_FLAG)
|
||||
: static_cast<TER>(tesSUCCESS);
|
||||
|
||||
env(token::mint(alice, 0u),
|
||||
token::xferFee(transferFee),
|
||||
txflags(tfTransferable | tfTrustLine),
|
||||
ter(mintTER));
|
||||
env.close();
|
||||
|
||||
// If fixRemoveNFTokenAutoTrustLine is active the rest
|
||||
// of this test falls on its face.
|
||||
if (tweakedFeatures[fixRemoveNFTokenAutoTrustLine])
|
||||
break;
|
||||
}
|
||||
// becky buys the nft for 1 drop.
|
||||
uint256 const beckyBuyOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftAutoTrustID, drops(1)),
|
||||
token::owner(alice));
|
||||
env.close();
|
||||
env(token::acceptBuyOffer(alice, beckyBuyOfferIndex));
|
||||
env.close();
|
||||
|
||||
// becky sells the nft for AUD.
|
||||
uint256 const beckySellOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)),
|
||||
txflags(tfSellNFToken));
|
||||
env.close();
|
||||
env(token::acceptSellOffer(cheri, beckySellOfferIndex));
|
||||
env.close();
|
||||
|
||||
// alice should now have a trust line for gwAUD.
|
||||
BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
|
||||
|
||||
// becky buys the nft back for CAD.
|
||||
uint256 const beckyBuyBackOfferIndex =
|
||||
keylet::nftoffer(becky, env.seq(becky)).key;
|
||||
env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)),
|
||||
token::owner(cheri));
|
||||
env.close();
|
||||
env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex));
|
||||
env.close();
|
||||
|
||||
// alice should now have a trust line for gwAUD and gwCAD.
|
||||
BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10));
|
||||
BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(5));
|
||||
}
|
||||
// Now that alice has trust lines preestablished, an nft without
|
||||
// flagCreateTrustLines will work for preestablished trust lines.
|
||||
{
|
||||
std::uint16_t transferFee = 5000; // 5%
|
||||
uint256 const nftNoAutoTrustID{token::getNextID(
|
||||
env, alice, 0u, tfTransferable, transferFee)};
|
||||
env(token::mint(alice, 0u),
|
||||
token::xferFee(transferFee),
|
||||
txflags(tfTransferable));
|
||||
env.close();
|
||||
|
||||
// alice sells the nft using AUD.
|
||||
uint256 const aliceSellOfferIndex =
|
||||
keylet::nftoffer(alice, env.seq(alice)).key;
|
||||
env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)),
|
||||
txflags(tfSellNFToken));
|
||||
env.close();
|
||||
env(token::acceptSellOffer(cheri, aliceSellOfferIndex));
|
||||
env.close();
|
||||
|
||||
// alice should now have AUD(210):
|
||||
// o 200 for this sale and
|
||||
// o 10 for the previous sale's fee.
|
||||
BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210));
|
||||
|
||||
// cheri can't sell the NFT for EUR, but can for CAD.
|
||||
env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)),
|
||||
txflags(tfSellNFToken),
|
||||
ter(tecNO_LINE));
|
||||
env.close();
|
||||
uint256 const cheriSellOfferIndex =
|
||||
keylet::nftoffer(cheri, env.seq(cheri)).key;
|
||||
env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)),
|
||||
txflags(tfSellNFToken));
|
||||
env.close();
|
||||
env(token::acceptSellOffer(becky, cheriSellOfferIndex));
|
||||
env.close();
|
||||
|
||||
// alice should now have CAD(10):
|
||||
// o 5 from this sale's fee and
|
||||
// o 5 for the previous sale's fee.
|
||||
BEAST_EXPECT(env.balance(alice, gwCAD) == gwCAD(10));
|
||||
}
|
||||
// To keep things tidy, cancel the offers.
|
||||
env(token::cancelOffer(becky, {beckyOfferIndex}));
|
||||
env(token::cancelOffer(cheri, {cheriOfferIndex}));
|
||||
env.close();
|
||||
}
|
||||
// An nft with flagCreateTrustLines but with a non-zero transfer
|
||||
// fee allows transfers using IOUs for payment.
|
||||
|
||||
std::uint16_t transferFee = 10000; // 10%
|
||||
|
||||
env(token::mint(alice, 0u),
|
||||
token::xferFee(transferFee),
|
||||
txflags(tfTransferable | tfTrustLine),
|
||||
ter(static_cast<TER>(temINVALID_FLAG)));
|
||||
env.close();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -7433,12 +7331,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
|
||||
// https://github.com/XRPLF/rippled/issues/4925
|
||||
//
|
||||
// For an NFToken with a transfer fee, the issuer must be able to
|
||||
// accept the transfer fee or else a transfer should fail. If the
|
||||
// accept the transfer fee or else a transfer should fail. If the
|
||||
// NFToken is transferred for a non-XRP asset, then the issuer must
|
||||
// have a trustline to that asset to receive the fee.
|
||||
//
|
||||
// This test looks at a situation where issuer would get a trustline
|
||||
// for the fee without the issuer's consent. Here are the steps:
|
||||
// for the fee without the issuer's consent. Here are the steps:
|
||||
// 1. Issuer has a trustline (i.e., USD)
|
||||
// 2. Issuer mints NFToken with transfer fee.
|
||||
// 3. Becky acquires the NFToken, paying with XRP.
|
||||
@@ -7456,8 +7354,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
|
||||
//
|
||||
// In both cases we remove the fixRemoveNFTokenAutoTrustLine amendment.
|
||||
// Otherwise we can't create NFTokens with tfTrustLine enabled.
|
||||
FeatureBitset const localFeatures =
|
||||
features - fixRemoveNFTokenAutoTrustLine;
|
||||
FeatureBitset const localFeatures = features;
|
||||
for (FeatureBitset feats :
|
||||
{localFeatures - fixEnforceNFTokenTrustline,
|
||||
localFeatures | fixEnforceNFTokenTrustline})
|
||||
@@ -7627,8 +7524,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
|
||||
//
|
||||
// We remove the fixRemoveNFTokenAutoTrustLine amendment. Otherwise
|
||||
// we can't create NFTokens with tfTrustLine enabled.
|
||||
FeatureBitset const localFeatures =
|
||||
features - fixRemoveNFTokenAutoTrustLine;
|
||||
FeatureBitset const localFeatures = features;
|
||||
|
||||
Env env{*this, localFeatures};
|
||||
env.fund(XRP(1000), issuer, becky, cheri);
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <test/json/TestOutputSuite.h>
|
||||
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/json/Writer.h>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class JsonWriter_test : public ripple::test::TestOutputSuite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testTrivial()
|
||||
{
|
||||
setup("trivial");
|
||||
BEAST_EXPECT(output_.empty());
|
||||
expectResult("");
|
||||
}
|
||||
|
||||
void
|
||||
testNearTrivial()
|
||||
{
|
||||
setup("near trivial");
|
||||
BEAST_EXPECT(output_.empty());
|
||||
writer_->output(0);
|
||||
expectResult("0");
|
||||
}
|
||||
|
||||
void
|
||||
testPrimitives()
|
||||
{
|
||||
setup("true");
|
||||
writer_->output(true);
|
||||
expectResult("true");
|
||||
|
||||
setup("false");
|
||||
writer_->output(false);
|
||||
expectResult("false");
|
||||
|
||||
setup("23");
|
||||
writer_->output(23);
|
||||
expectResult("23");
|
||||
|
||||
setup("23.0");
|
||||
writer_->output(23.0);
|
||||
expectResult("23.0");
|
||||
|
||||
setup("23.5");
|
||||
writer_->output(23.5);
|
||||
expectResult("23.5");
|
||||
|
||||
setup("a string");
|
||||
writer_->output("a string");
|
||||
expectResult("\"a string\"");
|
||||
|
||||
setup("nullptr");
|
||||
writer_->output(nullptr);
|
||||
expectResult("null");
|
||||
}
|
||||
|
||||
void
|
||||
testEmpty()
|
||||
{
|
||||
setup("empty array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->finish();
|
||||
expectResult("[]");
|
||||
|
||||
setup("empty object");
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->finish();
|
||||
expectResult("{}");
|
||||
}
|
||||
|
||||
void
|
||||
testEscaping()
|
||||
{
|
||||
setup("backslash");
|
||||
writer_->output("\\");
|
||||
expectResult("\"\\\\\"");
|
||||
|
||||
setup("quote");
|
||||
writer_->output("\"");
|
||||
expectResult("\"\\\"\"");
|
||||
|
||||
setup("backslash and quote");
|
||||
writer_->output("\\\"");
|
||||
expectResult("\"\\\\\\\"\"");
|
||||
|
||||
setup("escape embedded");
|
||||
writer_->output("this contains a \\ in the middle of it.");
|
||||
expectResult("\"this contains a \\\\ in the middle of it.\"");
|
||||
|
||||
setup("remaining escapes");
|
||||
writer_->output("\b\f\n\r\t");
|
||||
expectResult("\"\\b\\f\\n\\r\\t\"");
|
||||
}
|
||||
|
||||
void
|
||||
testArray()
|
||||
{
|
||||
setup("empty array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->append(12);
|
||||
writer_->finish();
|
||||
expectResult("[12]");
|
||||
}
|
||||
|
||||
void
|
||||
testLongArray()
|
||||
{
|
||||
setup("long array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->append(12);
|
||||
writer_->append(true);
|
||||
writer_->append("hello");
|
||||
writer_->finish();
|
||||
expectResult("[12,true,\"hello\"]");
|
||||
}
|
||||
|
||||
void
|
||||
testEmbeddedArraySimple()
|
||||
{
|
||||
setup("embedded array simple");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->startAppend(Writer::array);
|
||||
writer_->finish();
|
||||
writer_->finish();
|
||||
expectResult("[[]]");
|
||||
}
|
||||
|
||||
void
|
||||
testObject()
|
||||
{
|
||||
setup("object");
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->set("hello", "world");
|
||||
writer_->finish();
|
||||
|
||||
expectResult("{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
void
|
||||
testComplexObject()
|
||||
{
|
||||
setup("complex object");
|
||||
writer_->startRoot(Writer::object);
|
||||
|
||||
writer_->set("hello", "world");
|
||||
writer_->startSet(Writer::array, "array");
|
||||
|
||||
writer_->append(true);
|
||||
writer_->append(12);
|
||||
writer_->startAppend(Writer::array);
|
||||
writer_->startAppend(Writer::object);
|
||||
writer_->set("goodbye", "cruel world.");
|
||||
writer_->startSet(Writer::array, "subarray");
|
||||
writer_->append(23.5);
|
||||
writer_->finishAll();
|
||||
|
||||
expectResult(
|
||||
"{\"hello\":\"world\",\"array\":[true,12,"
|
||||
"[{\"goodbye\":\"cruel world.\","
|
||||
"\"subarray\":[23.5]}]]}");
|
||||
}
|
||||
|
||||
void
|
||||
testJson()
|
||||
{
|
||||
setup("object");
|
||||
Json::Value value(Json::objectValue);
|
||||
value["foo"] = 23;
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->set("hello", value);
|
||||
writer_->finish();
|
||||
|
||||
expectResult("{\"hello\":{\"foo\":23}}");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testTrivial();
|
||||
testNearTrivial();
|
||||
testPrimitives();
|
||||
testEmpty();
|
||||
testEscaping();
|
||||
testArray();
|
||||
testLongArray();
|
||||
testEmbeddedArraySimple();
|
||||
testObject();
|
||||
testComplexObject();
|
||||
testJson();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(JsonWriter, json, ripple);
|
||||
|
||||
} // namespace Json
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,5 +12,7 @@ xrpl_add_test(basics)
|
||||
target_link_libraries(xrpl.test.basics PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(crypto)
|
||||
target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(json)
|
||||
target_link_libraries(xrpl.test.json PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(net)
|
||||
target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test)
|
||||
|
||||
@@ -17,50 +17,43 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <test/json/TestOutputSuite.h>
|
||||
|
||||
#include <xrpl/json/Output.h>
|
||||
#include <xrpl/json/json_reader.h>
|
||||
#include <xrpl/json/json_writer.h>
|
||||
|
||||
namespace Json {
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
struct Output_test : ripple::test::TestOutputSuite
|
||||
#include <string>
|
||||
|
||||
using namespace ripple;
|
||||
using namespace Json;
|
||||
|
||||
TEST_SUITE_BEGIN("JsonOutput");
|
||||
|
||||
static void
|
||||
checkOutput(std::string const& valueDesc)
|
||||
{
|
||||
void
|
||||
runTest(std::string const& name, std::string const& valueDesc)
|
||||
{
|
||||
setup(name);
|
||||
Json::Value value;
|
||||
BEAST_EXPECT(Json::Reader().parse(valueDesc, value));
|
||||
auto out = stringOutput(output_);
|
||||
outputJson(value, out);
|
||||
std::string output;
|
||||
Json::Value value;
|
||||
REQUIRE(Json::Reader().parse(valueDesc, value));
|
||||
auto out = stringOutput(output);
|
||||
outputJson(value, out);
|
||||
|
||||
// Compare with the original version.
|
||||
auto expected = Json::FastWriter().write(value);
|
||||
expectResult(expected);
|
||||
expectResult(valueDesc);
|
||||
expectResult(jsonAsString(value));
|
||||
}
|
||||
auto expected = Json::FastWriter().write(value);
|
||||
CHECK(output == expected);
|
||||
CHECK(output == valueDesc);
|
||||
CHECK(output == jsonAsString(value));
|
||||
}
|
||||
|
||||
void
|
||||
runTest(std::string const& name)
|
||||
{
|
||||
runTest(name, name);
|
||||
}
|
||||
TEST_CASE("output cases")
|
||||
{
|
||||
checkOutput("{}");
|
||||
checkOutput("[]");
|
||||
checkOutput(R"([23,4.25,true,null,"string"])");
|
||||
checkOutput(R"({"hello":"world"})");
|
||||
checkOutput("[{}]");
|
||||
checkOutput("[[]]");
|
||||
checkOutput(R"({"array":[{"12":23},{},null,false,0.5]})");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
runTest("empty dict", "{}");
|
||||
runTest("empty array", "[]");
|
||||
runTest("array", "[23,4.25,true,null,\"string\"]");
|
||||
runTest("dict", "{\"hello\":\"world\"}");
|
||||
runTest("array dict", "[{}]");
|
||||
runTest("array array", "[[]]");
|
||||
runTest("more complex", "{\"array\":[{\"12\":23},{},null,false,0.5]}");
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Output, json, ripple);
|
||||
|
||||
} // namespace Json
|
||||
TEST_SUITE_END();
|
||||
1294
src/tests/libxrpl/json/Value.cpp
Normal file
1294
src/tests/libxrpl/json/Value.cpp
Normal file
File diff suppressed because it is too large
Load Diff
192
src/tests/libxrpl/json/Writer.cpp
Normal file
192
src/tests/libxrpl/json/Writer.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpl/json/Writer.h>
|
||||
|
||||
#include <doctest/doctest.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace ripple;
|
||||
using namespace Json;
|
||||
|
||||
TEST_SUITE_BEGIN("JsonWriter");
|
||||
|
||||
struct WriterFixture
|
||||
{
|
||||
std::string output;
|
||||
std::unique_ptr<Writer> writer;
|
||||
|
||||
WriterFixture()
|
||||
{
|
||||
writer = std::make_unique<Writer>(stringOutput(output));
|
||||
}
|
||||
|
||||
void
|
||||
reset()
|
||||
{
|
||||
output.clear();
|
||||
writer = std::make_unique<Writer>(stringOutput(output));
|
||||
}
|
||||
|
||||
void
|
||||
expectOutput(std::string const& expected) const
|
||||
{
|
||||
CHECK(output == expected);
|
||||
}
|
||||
|
||||
void
|
||||
checkOutputAndReset(std::string const& expected)
|
||||
{
|
||||
expectOutput(expected);
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "trivial")
|
||||
{
|
||||
CHECK(output.empty());
|
||||
checkOutputAndReset("");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "near trivial")
|
||||
{
|
||||
CHECK(output.empty());
|
||||
writer->output(0);
|
||||
checkOutputAndReset("0");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "primitives")
|
||||
{
|
||||
writer->output(true);
|
||||
checkOutputAndReset("true");
|
||||
|
||||
writer->output(false);
|
||||
checkOutputAndReset("false");
|
||||
|
||||
writer->output(23);
|
||||
checkOutputAndReset("23");
|
||||
|
||||
writer->output(23.0);
|
||||
checkOutputAndReset("23.0");
|
||||
|
||||
writer->output(23.5);
|
||||
checkOutputAndReset("23.5");
|
||||
|
||||
writer->output("a string");
|
||||
checkOutputAndReset(R"("a string")");
|
||||
|
||||
writer->output(nullptr);
|
||||
checkOutputAndReset("null");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "empty")
|
||||
{
|
||||
writer->startRoot(Writer::array);
|
||||
writer->finish();
|
||||
checkOutputAndReset("[]");
|
||||
|
||||
writer->startRoot(Writer::object);
|
||||
writer->finish();
|
||||
checkOutputAndReset("{}");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "escaping")
|
||||
{
|
||||
writer->output("\\");
|
||||
checkOutputAndReset(R"("\\")");
|
||||
|
||||
writer->output("\"");
|
||||
checkOutputAndReset(R"("\"")");
|
||||
|
||||
writer->output("\\\"");
|
||||
checkOutputAndReset(R"("\\\"")");
|
||||
|
||||
writer->output("this contains a \\ in the middle of it.");
|
||||
checkOutputAndReset(R"("this contains a \\ in the middle of it.")");
|
||||
|
||||
writer->output("\b\f\n\r\t");
|
||||
checkOutputAndReset(R"("\b\f\n\r\t")");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "array")
|
||||
{
|
||||
writer->startRoot(Writer::array);
|
||||
writer->append(12);
|
||||
writer->finish();
|
||||
checkOutputAndReset("[12]");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "long array")
|
||||
{
|
||||
writer->startRoot(Writer::array);
|
||||
writer->append(12);
|
||||
writer->append(true);
|
||||
writer->append("hello");
|
||||
writer->finish();
|
||||
checkOutputAndReset(R"([12,true,"hello"])");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "embedded array simple")
|
||||
{
|
||||
writer->startRoot(Writer::array);
|
||||
writer->startAppend(Writer::array);
|
||||
writer->finish();
|
||||
writer->finish();
|
||||
checkOutputAndReset("[[]]");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "object")
|
||||
{
|
||||
writer->startRoot(Writer::object);
|
||||
writer->set("hello", "world");
|
||||
writer->finish();
|
||||
checkOutputAndReset(R"({"hello":"world"})");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "complex object")
|
||||
{
|
||||
writer->startRoot(Writer::object);
|
||||
writer->set("hello", "world");
|
||||
writer->startSet(Writer::array, "array");
|
||||
writer->append(true);
|
||||
writer->append(12);
|
||||
writer->startAppend(Writer::array);
|
||||
writer->startAppend(Writer::object);
|
||||
writer->set("goodbye", "cruel world.");
|
||||
writer->startSet(Writer::array, "subarray");
|
||||
writer->append(23.5);
|
||||
writer->finishAll();
|
||||
checkOutputAndReset(
|
||||
R"({"hello":"world","array":[true,12,[{"goodbye":"cruel world.","subarray":[23.5]}]]})");
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(WriterFixture, "json value")
|
||||
{
|
||||
Json::Value value(Json::objectValue);
|
||||
value["foo"] = 23;
|
||||
writer->startRoot(Writer::object);
|
||||
writer->set("hello", value);
|
||||
writer->finish();
|
||||
checkOutputAndReset(R"({"hello":{"foo":23}})");
|
||||
}
|
||||
|
||||
TEST_SUITE_END();
|
||||
2
src/tests/libxrpl/json/main.cpp
Normal file
2
src/tests/libxrpl/json/main.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include <doctest/doctest.h>
|
||||
@@ -118,13 +118,6 @@ escrowCreatePreflightHelper<MPTIssue>(PreflightContext const& ctx)
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
EscrowCreate::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfUniversalMask : 0;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
EscrowCreate::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -639,13 +632,6 @@ EscrowFinish::checkExtraFeatures(PreflightContext const& ctx)
|
||||
ctx.rules.enabled(featureCredentials);
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
EscrowFinish::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfUniversalMask : 0;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
EscrowFinish::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -1225,13 +1211,6 @@ EscrowFinish::doApply()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::uint32_t
|
||||
EscrowCancel::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfUniversalMask : 0;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
EscrowCancel::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
|
||||
@@ -36,9 +36,6 @@ public:
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
@@ -63,9 +60,6 @@ public:
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
@@ -93,9 +87,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -55,28 +55,11 @@ NFTokenMint::checkExtraFeatures(PreflightContext const& ctx)
|
||||
std::uint32_t
|
||||
NFTokenMint::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between
|
||||
// accounts allowed a TrustLine to be added to the issuer of that token
|
||||
// without explicit permission from that issuer. This was enabled by
|
||||
// minting the NFToken with the tfTrustLine flag set.
|
||||
//
|
||||
// That capability could be used to attack the NFToken issuer. It
|
||||
// would be possible for two accounts to trade the NFToken back and forth
|
||||
// building up any number of TrustLines on the issuer, increasing the
|
||||
// issuer's reserve without bound.
|
||||
//
|
||||
// The fixRemoveNFTokenAutoTrustLine amendment disables minting with the
|
||||
// tfTrustLine flag as a way to prevent the attack. But until the
|
||||
// amendment passes we still need to keep the old behavior available.
|
||||
std::uint32_t const nfTokenMintMask =
|
||||
ctx.rules.enabled(fixRemoveNFTokenAutoTrustLine)
|
||||
// if featureDynamicNFT enabled then new flag allowing mutable URI
|
||||
// available
|
||||
? ctx.rules.enabled(featureDynamicNFT) ? tfNFTokenMintMaskWithMutable
|
||||
: tfNFTokenMintMask
|
||||
: ctx.rules.enabled(featureDynamicNFT) ? tfNFTokenMintOldMaskWithMutable
|
||||
: tfNFTokenMintOldMask;
|
||||
|
||||
ctx.rules.enabled(featureDynamicNFT) ? tfNFTokenMintMaskWithMutable
|
||||
: tfNFTokenMintMask;
|
||||
return nfTokenMintMask;
|
||||
}
|
||||
|
||||
|
||||
@@ -175,13 +175,6 @@ PayChanCreate::makeTxConsequences(PreflightContext const& ctx)
|
||||
return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
PayChanCreate::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfUniversalMask : 0;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
PayChanCreate::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -335,13 +328,6 @@ PayChanFund::makeTxConsequences(PreflightContext const& ctx)
|
||||
return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
PayChanFund::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfUniversalMask : 0;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
PayChanFund::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -434,10 +420,9 @@ PayChanClaim::checkExtraFeatures(PreflightContext const& ctx)
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
PayChanClaim::getFlagsMask(PreflightContext const& ctx)
|
||||
PayChanClaim::getFlagsMask(PreflightContext const&)
|
||||
{
|
||||
// 0 means "Allow any flags"
|
||||
return ctx.rules.enabled(fix1543) ? tfPayChanClaimMask : 0;
|
||||
return tfPayChanClaimMask;
|
||||
}
|
||||
|
||||
NotTEC
|
||||
|
||||
@@ -36,9 +36,6 @@ public:
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
@@ -65,9 +62,6 @@ public:
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user