Merge commit '4eb34f3' into ripple/se/fees

This commit is contained in:
Mayukha Vadari
2026-01-28 16:39:06 -05:00
1031 changed files with 27899 additions and 66877 deletions

View File

@@ -45,30 +45,18 @@ createFeeTx(
if (rules.enabled(featureXRPFees))
{
// New XRPFees format - all three fields are REQUIRED
obj.setFieldAmount(sfBaseFeeDrops, fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0});
obj.setFieldAmount(sfReserveBaseDrops, fields.reserveBaseDrops ? *fields.reserveBaseDrops : XRPAmount{0});
obj.setFieldAmount(
sfBaseFeeDrops,
fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0});
obj.setFieldAmount(
sfReserveBaseDrops,
fields.reserveBaseDrops ? *fields.reserveBaseDrops
: XRPAmount{0});
obj.setFieldAmount(
sfReserveIncrementDrops,
fields.reserveIncrementDrops ? *fields.reserveIncrementDrops
: XRPAmount{0});
sfReserveIncrementDrops, fields.reserveIncrementDrops ? *fields.reserveIncrementDrops : XRPAmount{0});
}
else
{
// Legacy format - all four fields are REQUIRED
obj.setFieldU64(sfBaseFee, fields.baseFee ? *fields.baseFee : 0);
obj.setFieldU32(
sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0);
obj.setFieldU32(
sfReserveIncrement,
fields.reserveIncrement ? *fields.reserveIncrement : 0);
obj.setFieldU32(
sfReferenceFeeUnits,
fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
obj.setFieldU32(sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0);
obj.setFieldU32(sfReserveIncrement, fields.reserveIncrement ? *fields.reserveIncrement : 0);
obj.setFieldU32(sfReferenceFeeUnits, fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
}
if (rules.enabled(featureSmartEscrow) || forceAllFields)
{
@@ -151,10 +139,7 @@ applyFeeAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx)
}
bool
verifyFeeObject(
std::shared_ptr<Ledger const> const& ledger,
Rules const& rules,
FeeSettingsFields const& expected)
verifyFeeObject(std::shared_ptr<Ledger const> const& ledger, Rules const& rules, FeeSettingsFields const& expected)
{
auto const feeObject = ledger->read(keylet::fees());
if (!feeObject)
@@ -168,28 +153,20 @@ verifyFeeObject(
if (rules.enabled(featureXRPFees))
{
if (feeObject->isFieldPresent(sfBaseFee) ||
feeObject->isFieldPresent(sfReserveBase) ||
feeObject->isFieldPresent(sfReserveIncrement) ||
feeObject->isFieldPresent(sfReferenceFeeUnits))
if (feeObject->isFieldPresent(sfBaseFee) || feeObject->isFieldPresent(sfReserveBase) ||
feeObject->isFieldPresent(sfReserveIncrement) || feeObject->isFieldPresent(sfReferenceFeeUnits))
return false;
if (!checkEquality(
sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0})))
if (!checkEquality(sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0})))
return false;
if (!checkEquality(
sfReserveBaseDrops,
expected.reserveBaseDrops.value_or(XRPAmount{0})))
if (!checkEquality(sfReserveBaseDrops, expected.reserveBaseDrops.value_or(XRPAmount{0})))
return false;
if (!checkEquality(
sfReserveIncrementDrops,
expected.reserveIncrementDrops.value_or(XRPAmount{0})))
if (!checkEquality(sfReserveIncrementDrops, expected.reserveIncrementDrops.value_or(XRPAmount{0})))
return false;
}
else
{
if (feeObject->isFieldPresent(sfBaseFeeDrops) ||
feeObject->isFieldPresent(sfReserveBaseDrops) ||
if (feeObject->isFieldPresent(sfBaseFeeDrops) || feeObject->isFieldPresent(sfReserveBaseDrops) ||
feeObject->isFieldPresent(sfReserveIncrementDrops))
return false;
@@ -324,10 +301,8 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(setup.gas_price == static_cast<std::uint32_t>(-300));
}
{
auto const big64 = std::to_string(
static_cast<std::uint64_t>(
std::numeric_limits<XRPAmount::value_type>::max()) +
1);
auto const big64 =
std::to_string(static_cast<std::uint64_t>(std::numeric_limits<XRPAmount::value_type>::max()) + 1);
Section config;
config.append(
{"reference_fee = " + big64,
@@ -363,22 +338,15 @@ class FeeVote_test : public beast::unit_test::suite
jtx::testable_amendments() - featureXRPFees -
featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test successful fee transaction with legacy fields
FeeSettingsFields fields{
.baseFee = 10,
.reserveBase = 200000,
.reserveIncrement = 50000,
.referenceFeeUnits = 10};
.baseFee = 10, .reserveBase = 200000, .reserveIncrement = 50000, .referenceFeeUnits = 10};
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
@@ -395,14 +363,10 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(
*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields{
.baseFeeDrops = XRPAmount{10},
@@ -495,18 +459,13 @@ class FeeVote_test : public beast::unit_test::suite
jtx::testable_amendments() - featureXRPFees -
featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test transaction with missing required legacy fields
auto invalidTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), true, false, 1);
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 1);
OpenView accum(ledger.get());
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
@@ -522,18 +481,13 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(
*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test transaction with missing required new fields
auto invalidTx = createInvalidFeeTx(
ledger->rules(), ledger->seq(), true, false, 3);
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 3);
OpenView accum(ledger.get());
BEAST_EXPECT(
!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
@@ -582,14 +536,10 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
auto feeTx = createFeeTx(
ledger->rules(),
@@ -622,13 +572,9 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields1{
.baseFeeDrops = XRPAmount{10},
@@ -646,8 +592,7 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
// Apply second fee transaction with different values
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields2{
.baseFeeDrops = XRPAmount{20},
@@ -673,13 +618,9 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test transaction with wrong ledger sequence
auto feeTx = createFeeTx(
@@ -704,13 +645,9 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields1{
.baseFeeDrops = XRPAmount{10},
@@ -727,13 +664,10 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Apply partial update (only some fields)
FeeSettingsFields fields2{
.baseFeeDrops = XRPAmount{20},
.reserveBaseDrops = XRPAmount{200000}};
FeeSettingsFields fields2{.baseFeeDrops = XRPAmount{20}, .reserveBaseDrops = XRPAmount{200000}};
auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2);
{
@@ -754,20 +688,15 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test invalid transaction with non-zero account - this should fail
// validation
auto invalidTx = STTx(ttFEE, [&](auto& obj) {
obj.setAccountID(
sfAccount,
AccountID(1)); // Should be zero (this makes it invalid)
obj.setAccountID(sfAccount,
AccountID(1)); // Should be zero (this makes it invalid)
obj.setFieldU32(sfLedgerSequence, ledger->seq());
obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10});
obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
@@ -797,20 +726,13 @@ class FeeVote_test : public beast::unit_test::suite
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
auto sec = randomSecretKey();
auto pub = derivePublicKey(KeyType::secp256k1, sec);
auto val = std::make_shared<STValidation>(
env.app().timeKeeper().now(),
pub,
sec,
calcNodeID(pub),
[](STValidation& v) {
env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) {
v.setFieldU32(sfLedgerSequence, 12345);
});
@@ -821,9 +743,7 @@ class FeeVote_test : public beast::unit_test::suite
feeVote->doValidation(currentFees, ledger->rules(), *val);
BEAST_EXPECT(val->isFieldPresent(sfBaseFeeDrops));
BEAST_EXPECT(
val->getFieldAmount(sfBaseFeeDrops) ==
XRPAmount(setup.reference_fee));
BEAST_EXPECT(val->getFieldAmount(sfBaseFeeDrops) == XRPAmount(setup.reference_fee));
}
// Test with XRPFees disabled (legacy format)
@@ -834,20 +754,13 @@ class FeeVote_test : public beast::unit_test::suite
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
auto sec = randomSecretKey();
auto pub = derivePublicKey(KeyType::secp256k1, sec);
auto val = std::make_shared<STValidation>(
env.app().timeKeeper().now(),
pub,
sec,
calcNodeID(pub),
[](STValidation& v) {
env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) {
v.setFieldU32(sfLedgerSequence, 12345);
});
@@ -876,24 +789,19 @@ class FeeVote_test : public beast::unit_test::suite
Env env(*this, testable_amendments() - featureSmartEscrow);
// establish what the current fees are
BEAST_EXPECT(
env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// doVoting requires a flag ledger (every 256th ledger)
// We need to create a ledger at sequence 256 to make it a flag ledger
for (int i = 0; i < 256 - 1; ++i)
{
ledger = std::make_shared<Ledger>(
*ledger, env.app().timeKeeper().closeTime());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
}
BEAST_EXPECT(ledger->isFlagLedger());
@@ -906,28 +814,19 @@ class FeeVote_test : public beast::unit_test::suite
auto pub = derivePublicKey(KeyType::secp256k1, sec);
auto val = std::make_shared<STValidation>(
env.app().timeKeeper().now(),
pub,
sec,
calcNodeID(pub),
[&](STValidation& v) {
env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [&](STValidation& v) {
v.setFieldU32(sfLedgerSequence, ledger->seq());
// Vote for different fees than current
v.setFieldAmount(
sfBaseFeeDrops, XRPAmount{setup.reference_fee});
v.setFieldAmount(
sfReserveBaseDrops, XRPAmount{setup.account_reserve});
v.setFieldAmount(
sfReserveIncrementDrops,
XRPAmount{setup.owner_reserve});
v.setFieldAmount(sfBaseFeeDrops, XRPAmount{setup.reference_fee});
v.setFieldAmount(sfReserveBaseDrops, XRPAmount{setup.account_reserve});
v.setFieldAmount(sfReserveIncrementDrops, XRPAmount{setup.owner_reserve});
});
if (i % 2)
val->setTrusted();
validations.push_back(val);
}
auto txSet = std::make_shared<SHAMap>(
SHAMapType::TRANSACTION, env.app().getNodeFamily());
auto txSet = std::make_shared<SHAMap>(SHAMapType::TRANSACTION, env.app().getNodeFamily());
// This should not throw since we have a flag ledger
feeVote->doVoting(ledger, validations, txSet);
@@ -952,15 +851,9 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
// Check the values
BEAST_EXPECT(
feeTx.getFieldAmount(sfBaseFeeDrops) ==
XRPAmount{setup.reference_fee});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveBaseDrops) ==
XRPAmount{setup.account_reserve});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveIncrementDrops) ==
XRPAmount{setup.owner_reserve});
BEAST_EXPECT(feeTx.getFieldAmount(sfBaseFeeDrops) == XRPAmount{setup.reference_fee});
BEAST_EXPECT(feeTx.getFieldAmount(sfReserveBaseDrops) == XRPAmount{setup.account_reserve});
BEAST_EXPECT(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve});
}
void