3#include <xrpld/app/ledger/Ledger.h>
4#include <xrpld/app/misc/FeeVote.h>
5#include <xrpld/app/tx/apply.h>
7#include <xrpl/basics/BasicConfig.h>
8#include <xrpl/ledger/View.h>
9#include <xrpl/protocol/Feature.h>
10#include <xrpl/protocol/Indexes.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/STTx.h>
13#include <xrpl/protocol/SecretKey.h>
35 auto fill = [&](
auto& obj) {
37 obj.setFieldU32(sfLedgerSequence,
seq);
39 if (rules.
enabled(featureXRPFees))
50 sfReserveIncrementDrops,
68 return STTx(ttFEE, fill);
75 bool missingRequiredFields =
true,
76 bool wrongFeatureFields =
false,
79 auto fill = [&](
auto& obj) {
81 obj.setFieldU32(sfLedgerSequence,
seq);
83 if (wrongFeatureFields)
85 if (rules.
enabled(featureXRPFees))
87 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
88 obj.setFieldU32(sfReserveBase, 200000);
89 obj.setFieldU32(sfReserveIncrement, 50000);
90 obj.setFieldU32(sfReferenceFeeUnits, 10);
94 obj.setFieldAmount(sfBaseFeeDrops,
XRPAmount{10 + uniqueValue});
95 obj.setFieldAmount(sfReserveBaseDrops,
XRPAmount{200000});
96 obj.setFieldAmount(sfReserveIncrementDrops,
XRPAmount{50000});
99 else if (!missingRequiredFields)
102 if (rules.
enabled(featureXRPFees))
104 obj.setFieldAmount(sfBaseFeeDrops,
XRPAmount{10 + uniqueValue});
105 obj.setFieldAmount(sfReserveBaseDrops,
XRPAmount{200000});
106 obj.setFieldAmount(sfReserveIncrementDrops,
XRPAmount{50000});
110 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
111 obj.setFieldU32(sfReserveBase, 200000);
112 obj.setFieldU32(sfReserveIncrement, 50000);
113 obj.setFieldU32(sfReferenceFeeUnits, 10);
119 return STTx(ttFEE, fill);
140 auto checkEquality = [&](
auto const& field,
auto const& expected) {
141 if (!feeObject->isFieldPresent(field))
143 return feeObject->at(field) == expected;
146 if (rules.
enabled(featureXRPFees))
148 if (feeObject->isFieldPresent(sfBaseFee) ||
149 feeObject->isFieldPresent(sfReserveBase) ||
150 feeObject->isFieldPresent(sfReserveIncrement) ||
151 feeObject->isFieldPresent(sfReferenceFeeUnits))
162 sfReserveIncrementDrops,
168 if (feeObject->isFieldPresent(sfBaseFeeDrops) ||
169 feeObject->isFieldPresent(sfReserveBaseDrops) ||
170 feeObject->isFieldPresent(sfReserveIncrementDrops))
174 if (!checkEquality(sfBaseFee, expected.
baseFee))
176 if (!checkEquality(sfReserveBase, expected.
reserveBase))
191 for (
auto i = txSet->begin(); i != txSet->end(); ++i)
193 auto const data = i->slice();
210 BEAST_EXPECT(setup.reference_fee == defaultSetup.
reference_fee);
212 BEAST_EXPECT(setup.owner_reserve == defaultSetup.
owner_reserve);
217 {
"reference_fee = 50",
218 "account_reserve = 1234567",
219 "owner_reserve = 1234"});
221 BEAST_EXPECT(setup.reference_fee == 50);
222 BEAST_EXPECT(setup.account_reserve == 1234567);
223 BEAST_EXPECT(setup.owner_reserve == 1234);
228 {
"reference_fee = blah",
229 "account_reserve = yada",
230 "owner_reserve = foo"});
233 BEAST_EXPECT(setup.reference_fee == defaultSetup.
reference_fee);
235 BEAST_EXPECT(setup.owner_reserve == defaultSetup.
owner_reserve);
240 {
"reference_fee = -50",
241 "account_reserve = -1234567",
242 "owner_reserve = -1234"});
245 BEAST_EXPECT(setup.reference_fee == defaultSetup.
reference_fee);
247 setup.account_reserve ==
static_cast<std::uint32_t>(-1234567));
258 {
"reference_fee = " + big64,
259 "account_reserve = " + big64,
260 "owner_reserve = " + big64});
263 BEAST_EXPECT(setup.reference_fee == defaultSetup.
reference_fee);
265 BEAST_EXPECT(setup.owner_reserve == defaultSetup.
owner_reserve);
272 testcase(
"Basic SetFee transaction");
291 .reserveBase = 200000,
292 .reserveIncrement = 50000,
293 .referenceFeeUnits = 10};
294 auto feeTx =
createFeeTx(ledger->rules(), ledger->seq(), fields);
298 accum.
apply(*ledger);
320 .reserveIncrementDrops =
XRPAmount{50000}};
322 auto feeTx =
createFeeTx(ledger->rules(), ledger->seq(), fields);
326 accum.
apply(*ledger);
336 testcase(
"Fee Transaction Validation");
352 ledger->rules(), ledger->seq(),
true,
false, 1);
358 ledger->rules(), ledger->seq(),
false,
true, 2);
376 ledger->rules(), ledger->seq(),
true,
false, 3);
382 ledger->rules(), ledger->seq(),
false,
true, 4);
390 testcase(
"Pseudo Transaction Properties");
406 {.baseFeeDrops = XRPAmount{10},
408 .reserveIncrementDrops =
XRPAmount{50000}});
411 BEAST_EXPECT(feeTx.getAccountID(sfAccount) ==
AccountID());
412 BEAST_EXPECT(feeTx.getFieldAmount(sfFee) ==
XRPAmount{0});
413 BEAST_EXPECT(feeTx.getSigningPubKey().empty());
414 BEAST_EXPECT(feeTx.getSignature().empty());
415 BEAST_EXPECT(!feeTx.isFieldPresent(sfSigners));
416 BEAST_EXPECT(feeTx.getFieldU32(sfSequence) == 0);
417 BEAST_EXPECT(!feeTx.isFieldPresent(sfPreviousTxnID));
429 testcase(
"Multiple Fee Updates");
444 .reserveIncrementDrops =
XRPAmount{50000}};
445 auto feeTx1 =
createFeeTx(ledger->rules(), ledger->seq(), fields1);
450 accum.
apply(*ledger);
462 .reserveIncrementDrops =
XRPAmount{75000}};
463 auto feeTx2 =
createFeeTx(ledger->rules(), ledger->seq(), fields2);
468 accum.
apply(*ledger);
478 testcase(
"Wrong Ledger Sequence");
494 {.baseFeeDrops = XRPAmount{10},
496 .reserveIncrementDrops =
XRPAmount{50000}});
509 testcase(
"Partial Field Updates");
511 jtx::Env env(*
this, jtx::testable_amendments() | featureXRPFees);
524 .reserveIncrementDrops =
XRPAmount{50000}};
525 auto feeTx1 =
createFeeTx(ledger->rules(), ledger->seq(), fields1);
530 accum.
apply(*ledger);
542 auto feeTx2 =
createFeeTx(ledger->rules(), ledger->seq(), fields2);
547 accum.
apply(*ledger);
557 testcase(
"Single Invalid Transaction");
559 jtx::Env env(*
this, jtx::testable_amendments() | featureXRPFees);
571 auto invalidTx =
STTx(ttFEE, [&](
auto& obj) {
575 obj.setFieldU32(sfLedgerSequence, ledger->seq());
576 obj.setFieldAmount(sfBaseFeeDrops,
XRPAmount{10});
577 obj.setFieldAmount(sfReserveBaseDrops,
XRPAmount{200000});
578 obj.setFieldAmount(sfReserveIncrementDrops,
XRPAmount{50000});
588 testcase(
"doValidation");
622 auto const& currentFees = ledger->fees();
624 feeVote->doValidation(currentFees, ledger->rules(), *val);
626 BEAST_EXPECT(val->isFieldPresent(sfBaseFeeDrops));
628 val->getFieldAmount(sfBaseFeeDrops) ==
655 auto const& currentFees = ledger->fees();
657 feeVote->doValidation(currentFees, ledger->rules(), *val);
660 BEAST_EXPECT(val->isFieldPresent(sfBaseFee));
661 BEAST_EXPECT(val->getFieldU64(sfBaseFee) == setup.
reference_fee);
668 testcase(
"doVoting");
694 for (
int i = 0; i < 256 - 1; ++i)
699 BEAST_EXPECT(ledger->isFlagLedger());
704 for (
int i = 0; i < 5; i++)
722 sfReserveIncrementDrops,
734 feeVote->doVoting(ledger, validations, txSet);
736 auto const txs =
getTxs(txSet);
737 BEAST_EXPECT(txs.size() == 1);
738 auto const& feeTx = txs[0];
740 BEAST_EXPECT(feeTx.getTxnType() == ttFEE);
742 BEAST_EXPECT(feeTx.getAccountID(sfAccount) ==
AccountID());
743 BEAST_EXPECT(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1);
745 BEAST_EXPECT(feeTx.isFieldPresent(sfBaseFeeDrops));
746 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveBaseDrops));
747 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveIncrementDrops));
750 BEAST_EXPECT(!feeTx.isFieldPresent(sfBaseFee));
751 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveBase));
752 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveIncrement));
753 BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
757 feeTx.getFieldAmount(sfBaseFeeDrops) ==
760 feeTx.getFieldAmount(sfReserveBaseDrops) ==
763 feeTx.getFieldAmount(sfReserveIncrementDrops) ==
772 testTransactionValidation();
773 testPseudoTransactionProperties();
774 testMultipleFeeUpdates();
775 testWrongLedgerSequence();
776 testPartialFieldUpdates();
777 testSingleInvalidTransaction();
testcase_t testcase
Memberspace for declaring test cases.
virtual Config & config()=0
virtual beast::Journal journal(std::string const &name)=0
virtual TimeKeeper & timeKeeper()=0
virtual Family & getNodeFamily()=0
Manager to process fee votes.
Writable ledger view that accumulates state and tx changes.
void apply(TxsRawView &to) const
Apply changes.
Rules controlling protocol behavior.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
void setFieldAmount(SField const &field, STAmount const &)
void setFieldU32(SField const &field, std::uint32_t)
Holds a collection of configuration values.
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
time_point now() const override
Returns the current time, using the server's clock.
time_point closeTime() const
Returns the predicted close time, in network time.
void testPartialFieldUpdates()
void testSingleInvalidTransaction()
void testMultipleFeeUpdates()
void testPseudoTransactionProperties()
void testWrongLedgerSequence()
void run() override
Runs the suite.
void testTransactionValidation()
A transaction testing environment.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
beast::Journal const journal
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
auto const data
General field definitions, or fields used in multiple transaction namespaces.
FeatureBitset testable_amendments()
bool applyFeeAndTestResult(jtx::Env &env, OpenView &view, STTx const &tx)
STTx createFeeTx(Rules const &rules, std::uint32_t seq, FeeSettingsFields const &fields)
std::vector< STTx > getTxs(std::shared_ptr< SHAMap > const &txSet)
STTx createInvalidFeeTx(Rules const &rules, std::uint32_t seq, bool missingRequiredFields=true, bool wrongFeatureFields=false, std::uint32_t uniqueValue=42)
bool verifyFeeObject(std::shared_ptr< Ledger const > const &ledger, Rules const &rules, FeeSettingsFields const &expected)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
std::unique_ptr< FeeVote > make_FeeVote(FeeSetup const &setup, beast::Journal journal)
Create an instance of the FeeVote logic.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
FeeSetup setup_FeeVote(Section const §ion)
create_genesis_t const create_genesis
Fee schedule for startup / standalone, and to vote for.
XRPAmount reference_fee
The cost of a reference transaction in drops.
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
XRPAmount account_reserve
The account reserve requirement in drops.
std::optional< XRPAmount > reserveBaseDrops
std::optional< std::uint32_t > reserveBase
std::optional< std::uint32_t > reserveIncrement
std::optional< XRPAmount > reserveIncrementDrops
std::optional< std::uint32_t > referenceFeeUnits
std::optional< std::uint64_t > baseFee
std::optional< XRPAmount > baseFeeDrops
Set the sequence number on a JTx.