rippled
Loading...
Searching...
No Matches
FeeVote_test.cpp
1#include <test/jtx.h>
2
3#include <xrpld/app/ledger/Ledger.h>
4#include <xrpld/app/misc/FeeVote.h>
5#include <xrpld/app/tx/apply.h>
6
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>
14
15namespace xrpl {
16namespace test {
17
28
29STTx
31{
32 auto fill = [&](auto& obj) {
33 obj.setAccountID(sfAccount, AccountID());
34 obj.setFieldU32(sfLedgerSequence, seq);
35
36 if (rules.enabled(featureXRPFees))
37 {
38 // New XRPFees format - all three fields are REQUIRED
39 obj.setFieldAmount(sfBaseFeeDrops, fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0});
40 obj.setFieldAmount(sfReserveBaseDrops, fields.reserveBaseDrops ? *fields.reserveBaseDrops : XRPAmount{0});
41 obj.setFieldAmount(
42 sfReserveIncrementDrops, fields.reserveIncrementDrops ? *fields.reserveIncrementDrops : XRPAmount{0});
43 }
44 else
45 {
46 // Legacy format - all four fields are REQUIRED
47 obj.setFieldU64(sfBaseFee, fields.baseFee ? *fields.baseFee : 0);
48 obj.setFieldU32(sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0);
49 obj.setFieldU32(sfReserveIncrement, fields.reserveIncrement ? *fields.reserveIncrement : 0);
50 obj.setFieldU32(sfReferenceFeeUnits, fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
51 }
52 };
53 return STTx(ttFEE, fill);
54}
55
56STTx
58 Rules const& rules,
60 bool missingRequiredFields = true,
61 bool wrongFeatureFields = false,
62 std::uint32_t uniqueValue = 42)
63{
64 auto fill = [&](auto& obj) {
65 obj.setAccountID(sfAccount, AccountID());
66 obj.setFieldU32(sfLedgerSequence, seq);
67
68 if (wrongFeatureFields)
69 {
70 if (rules.enabled(featureXRPFees))
71 {
72 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
73 obj.setFieldU32(sfReserveBase, 200000);
74 obj.setFieldU32(sfReserveIncrement, 50000);
75 obj.setFieldU32(sfReferenceFeeUnits, 10);
76 }
77 else
78 {
79 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10 + uniqueValue});
80 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
81 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
82 }
83 }
84 else if (!missingRequiredFields)
85 {
86 // Create valid transaction (all required fields present)
87 if (rules.enabled(featureXRPFees))
88 {
89 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10 + uniqueValue});
90 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
91 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
92 }
93 else
94 {
95 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
96 obj.setFieldU32(sfReserveBase, 200000);
97 obj.setFieldU32(sfReserveIncrement, 50000);
98 obj.setFieldU32(sfReferenceFeeUnits, 10);
99 }
100 }
101 // If missingRequiredFields is true, we don't add the required fields
102 // (default behavior)
103 };
104 return STTx(ttFEE, fill);
105}
106
107bool
109{
110 auto const res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
111 return res.ter == tesSUCCESS;
112}
113
114bool
115verifyFeeObject(std::shared_ptr<Ledger const> const& ledger, Rules const& rules, FeeSettingsFields const& expected)
116{
117 auto const feeObject = ledger->read(keylet::fees());
118 if (!feeObject)
119 return false;
120
121 auto checkEquality = [&](auto const& field, auto const& expected) {
122 if (!feeObject->isFieldPresent(field))
123 return false;
124 return feeObject->at(field) == expected;
125 };
126
127 if (rules.enabled(featureXRPFees))
128 {
129 if (feeObject->isFieldPresent(sfBaseFee) || feeObject->isFieldPresent(sfReserveBase) ||
130 feeObject->isFieldPresent(sfReserveIncrement) || feeObject->isFieldPresent(sfReferenceFeeUnits))
131 return false;
132
133 if (!checkEquality(sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0})))
134 return false;
135 if (!checkEquality(sfReserveBaseDrops, expected.reserveBaseDrops.value_or(XRPAmount{0})))
136 return false;
137 if (!checkEquality(sfReserveIncrementDrops, expected.reserveIncrementDrops.value_or(XRPAmount{0})))
138 return false;
139 }
140 else
141 {
142 if (feeObject->isFieldPresent(sfBaseFeeDrops) || feeObject->isFieldPresent(sfReserveBaseDrops) ||
143 feeObject->isFieldPresent(sfReserveIncrementDrops))
144 return false;
145
146 // Read sfBaseFee as a hex string and compare to expected.baseFee
147 if (!checkEquality(sfBaseFee, expected.baseFee))
148 return false;
149 if (!checkEquality(sfReserveBase, expected.reserveBase))
150 return false;
151 if (!checkEquality(sfReserveIncrement, expected.reserveIncrement))
152 return false;
153 if (!checkEquality(sfReferenceFeeUnits, expected.referenceFeeUnits))
154 return false;
155 }
156
157 return true;
158}
159
162{
164 for (auto i = txSet->begin(); i != txSet->end(); ++i)
165 {
166 auto const data = i->slice();
167 auto serialIter = SerialIter(data);
168 txs.push_back(STTx(serialIter));
169 }
170 return txs;
171};
172
174{
175 void
177 {
178 FeeSetup const defaultSetup;
179 {
180 // defaults
181 Section config;
182 auto setup = setup_FeeVote(config);
183 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
184 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
185 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
186 }
187 {
188 Section config;
189 config.append({"reference_fee = 50", "account_reserve = 1234567", "owner_reserve = 1234"});
190 auto setup = setup_FeeVote(config);
191 BEAST_EXPECT(setup.reference_fee == 50);
192 BEAST_EXPECT(setup.account_reserve == 1234567);
193 BEAST_EXPECT(setup.owner_reserve == 1234);
194 }
195 {
196 Section config;
197 config.append({"reference_fee = blah", "account_reserve = yada", "owner_reserve = foo"});
198 // Illegal values are ignored, and the defaults left unchanged
199 auto setup = setup_FeeVote(config);
200 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
201 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
202 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
203 }
204 {
205 Section config;
206 config.append({"reference_fee = -50", "account_reserve = -1234567", "owner_reserve = -1234"});
207 // Illegal values are ignored, and the defaults left unchanged
208 auto setup = setup_FeeVote(config);
209 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
210 BEAST_EXPECT(setup.account_reserve == static_cast<std::uint32_t>(-1234567));
211 BEAST_EXPECT(setup.owner_reserve == static_cast<std::uint32_t>(-1234));
212 }
213 {
214 auto const big64 =
216 Section config;
217 config.append({"reference_fee = " + big64, "account_reserve = " + big64, "owner_reserve = " + big64});
218 // Illegal values are ignored, and the defaults left unchanged
219 auto setup = setup_FeeVote(config);
220 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
221 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
222 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
223 }
224 }
225
226 void
228 {
229 testcase("Basic SetFee transaction");
230
231 // Test with XRPFees disabled (legacy format)
232 {
233 jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
234 auto ledger = std::make_shared<Ledger>(
236
237 // Create the next ledger to apply transaction to
238 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
239
240 // Test successful fee transaction with legacy fields
241
242 FeeSettingsFields fields{
243 .baseFee = 10, .reserveBase = 200000, .reserveIncrement = 50000, .referenceFeeUnits = 10};
244 auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
245
246 OpenView accum(ledger.get());
247 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
248 accum.apply(*ledger);
249
250 // Verify fee object was created/updated correctly
251 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
252 }
253
254 // Test with XRPFees enabled (new format)
255 {
256 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
257 auto ledger = std::make_shared<Ledger>(
259
260 // Create the next ledger to apply transaction to
261 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
262
263 FeeSettingsFields fields{
264 .baseFeeDrops = XRPAmount{10},
265 .reserveBaseDrops = XRPAmount{200000},
266 .reserveIncrementDrops = XRPAmount{50000}};
267 // Test successful fee transaction with new fields
268 auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
269
270 OpenView accum(ledger.get());
271 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
272 accum.apply(*ledger);
273
274 // Verify fee object was created/updated correctly
275 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
276 }
277 }
278
279 void
281 {
282 testcase("Fee Transaction Validation");
283
284 {
285 jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
286 auto ledger = std::make_shared<Ledger>(
288
289 // Create the next ledger to apply transaction to
290 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
291
292 // Test transaction with missing required legacy fields
293 auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 1);
294 OpenView accum(ledger.get());
295 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
296
297 // Test transaction with new format fields when XRPFees is disabled
298 auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 2);
299 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
300 }
301
302 {
303 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
304 auto ledger = std::make_shared<Ledger>(
306
307 // Create the next ledger to apply transaction to
308 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
309
310 // Test transaction with missing required new fields
311 auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 3);
312 OpenView accum(ledger.get());
313 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
314
315 // Test transaction with legacy fields when XRPFees is enabled
316 auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 4);
317 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
318 }
319 }
320
321 void
323 {
324 testcase("Pseudo Transaction Properties");
325
327 auto ledger = std::make_shared<Ledger>(
329
330 // Create the next ledger to apply transaction to
331 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
332
333 auto feeTx = createFeeTx(
334 ledger->rules(),
335 ledger->seq(),
336 {.baseFeeDrops = XRPAmount{10},
337 .reserveBaseDrops = XRPAmount{200000},
338 .reserveIncrementDrops = XRPAmount{50000}});
339
340 // Verify pseudo-transaction properties
341 BEAST_EXPECT(feeTx.getAccountID(sfAccount) == AccountID());
342 BEAST_EXPECT(feeTx.getFieldAmount(sfFee) == XRPAmount{0});
343 BEAST_EXPECT(feeTx.getSigningPubKey().empty());
344 BEAST_EXPECT(feeTx.getSignature().empty());
345 BEAST_EXPECT(!feeTx.isFieldPresent(sfSigners));
346 BEAST_EXPECT(feeTx.getFieldU32(sfSequence) == 0);
347 BEAST_EXPECT(!feeTx.isFieldPresent(sfPreviousTxnID));
348
349 // But can be applied to a closed ledger
350 {
351 OpenView closedAccum(ledger.get());
352 BEAST_EXPECT(applyFeeAndTestResult(env, closedAccum, feeTx));
353 }
354 }
355
356 void
358 {
359 testcase("Multiple Fee Updates");
360
361 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
362 auto ledger = std::make_shared<Ledger>(
364
365 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
366
367 FeeSettingsFields fields1{
368 .baseFeeDrops = XRPAmount{10},
369 .reserveBaseDrops = XRPAmount{200000},
370 .reserveIncrementDrops = XRPAmount{50000}};
371 auto feeTx1 = createFeeTx(ledger->rules(), ledger->seq(), fields1);
372
373 {
374 OpenView accum(ledger.get());
375 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
376 accum.apply(*ledger);
377 }
378
379 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
380
381 // Apply second fee transaction with different values
382 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
383
384 FeeSettingsFields fields2{
385 .baseFeeDrops = XRPAmount{20},
386 .reserveBaseDrops = XRPAmount{300000},
387 .reserveIncrementDrops = XRPAmount{75000}};
388 auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2);
389
390 {
391 OpenView accum(ledger.get());
392 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
393 accum.apply(*ledger);
394 }
395
396 // Verify second update overwrote the first
397 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields2));
398 }
399
400 void
402 {
403 testcase("Wrong Ledger Sequence");
404
405 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
406 auto ledger = std::make_shared<Ledger>(
408
409 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
410
411 // Test transaction with wrong ledger sequence
412 auto feeTx = createFeeTx(
413 ledger->rules(),
414 ledger->seq() + 5, // Wrong sequence (should be ledger->seq())
415 {.baseFeeDrops = XRPAmount{10},
416 .reserveBaseDrops = XRPAmount{200000},
417 .reserveIncrementDrops = XRPAmount{50000}});
418
419 OpenView accum(ledger.get());
420
421 // The transaction should still succeed as long as other fields are
422 // valid
423 // The ledger sequence field is only used for informational purposes
424 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
425 }
426
427 void
429 {
430 testcase("Partial Field Updates");
431
432 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
433 auto ledger = std::make_shared<Ledger>(
435
436 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
437
438 FeeSettingsFields fields1{
439 .baseFeeDrops = XRPAmount{10},
440 .reserveBaseDrops = XRPAmount{200000},
441 .reserveIncrementDrops = XRPAmount{50000}};
442 auto feeTx1 = createFeeTx(ledger->rules(), ledger->seq(), fields1);
443
444 {
445 OpenView accum(ledger.get());
446 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
447 accum.apply(*ledger);
448 }
449
450 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
451
452 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
453
454 // Apply partial update (only some fields)
455 FeeSettingsFields fields2{.baseFeeDrops = XRPAmount{20}, .reserveBaseDrops = XRPAmount{200000}};
456 auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2);
457
458 {
459 OpenView accum(ledger.get());
460 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
461 accum.apply(*ledger);
462 }
463
464 // Verify the partial update worked
465 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields2));
466 }
467
468 void
470 {
471 testcase("Single Invalid Transaction");
472
473 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
474 auto ledger = std::make_shared<Ledger>(
476
477 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
478
479 // Test invalid transaction with non-zero account - this should fail
480 // validation
481 auto invalidTx = STTx(ttFEE, [&](auto& obj) {
482 obj.setAccountID(sfAccount,
483 AccountID(1)); // Should be zero (this makes it invalid)
484 obj.setFieldU32(sfLedgerSequence, ledger->seq());
485 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10});
486 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
487 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
488 });
489
490 OpenView accum(ledger.get());
491 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
492 }
493
494 void
496 {
497 testcase("doValidation");
498
499 using namespace jtx;
500
501 FeeSetup setup;
502 setup.reference_fee = 42;
503 setup.account_reserve = 1234567;
504 setup.owner_reserve = 7654321;
505
506 // Test with XRPFees enabled
507 {
508 Env env(*this, testable_amendments() | featureXRPFees);
509 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
510
511 auto ledger = std::make_shared<Ledger>(
513
514 auto sec = randomSecretKey();
515 auto pub = derivePublicKey(KeyType::secp256k1, sec);
516
518 env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) {
519 v.setFieldU32(sfLedgerSequence, 12345);
520 });
521
522 // Use the current ledger's fees as the "current" fees for
523 // doValidation
524 auto const& currentFees = ledger->fees();
525
526 feeVote->doValidation(currentFees, ledger->rules(), *val);
527
528 BEAST_EXPECT(val->isFieldPresent(sfBaseFeeDrops));
529 BEAST_EXPECT(val->getFieldAmount(sfBaseFeeDrops) == XRPAmount(setup.reference_fee));
530 }
531
532 // Test with XRPFees disabled (legacy format)
533 {
534 Env env(*this, testable_amendments() - featureXRPFees);
535 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
536
537 auto ledger = std::make_shared<Ledger>(
539
540 auto sec = randomSecretKey();
541 auto pub = derivePublicKey(KeyType::secp256k1, sec);
542
544 env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) {
545 v.setFieldU32(sfLedgerSequence, 12345);
546 });
547
548 auto const& currentFees = ledger->fees();
549
550 feeVote->doValidation(currentFees, ledger->rules(), *val);
551
552 // In legacy mode, should vote using legacy fields
553 BEAST_EXPECT(val->isFieldPresent(sfBaseFee));
554 BEAST_EXPECT(val->getFieldU64(sfBaseFee) == setup.reference_fee);
555 }
556 }
557
558 void
560 {
561 testcase("doVoting");
562
563 using namespace jtx;
564
565 FeeSetup setup;
566 setup.reference_fee = 42;
567 setup.account_reserve = 1234567;
568 setup.owner_reserve = 7654321;
569
570 Env env(*this, testable_amendments() | featureXRPFees);
571
572 // establish what the current fees are
573 BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
574 BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
575 BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
576
577 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
578 auto ledger = std::make_shared<Ledger>(
580
581 // doVoting requires a flag ledger (every 256th ledger)
582 // We need to create a ledger at sequence 256 to make it a flag ledger
583 for (int i = 0; i < 256 - 1; ++i)
584 {
585 ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
586 }
587 BEAST_EXPECT(ledger->isFlagLedger());
588
589 // Create some mock validations with fee votes
591
592 for (int i = 0; i < 5; i++)
593 {
594 auto sec = randomSecretKey();
595 auto pub = derivePublicKey(KeyType::secp256k1, sec);
596
598 env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [&](STValidation& v) {
599 v.setFieldU32(sfLedgerSequence, ledger->seq());
600 // Vote for different fees than current
601 v.setFieldAmount(sfBaseFeeDrops, XRPAmount{setup.reference_fee});
602 v.setFieldAmount(sfReserveBaseDrops, XRPAmount{setup.account_reserve});
603 v.setFieldAmount(sfReserveIncrementDrops, XRPAmount{setup.owner_reserve});
604 });
605 if (i % 2)
606 val->setTrusted();
607 validations.push_back(val);
608 }
609
611
612 // This should not throw since we have a flag ledger
613 feeVote->doVoting(ledger, validations, txSet);
614
615 auto const txs = getTxs(txSet);
616 BEAST_EXPECT(txs.size() == 1);
617 auto const& feeTx = txs[0];
618
619 BEAST_EXPECT(feeTx.getTxnType() == ttFEE);
620
621 BEAST_EXPECT(feeTx.getAccountID(sfAccount) == AccountID());
622 BEAST_EXPECT(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1);
623
624 BEAST_EXPECT(feeTx.isFieldPresent(sfBaseFeeDrops));
625 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveBaseDrops));
626 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveIncrementDrops));
627
628 // The legacy fields should NOT be present
629 BEAST_EXPECT(!feeTx.isFieldPresent(sfBaseFee));
630 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveBase));
631 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveIncrement));
632 BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
633
634 // Check the values
635 BEAST_EXPECT(feeTx.getFieldAmount(sfBaseFeeDrops) == XRPAmount{setup.reference_fee});
636 BEAST_EXPECT(feeTx.getFieldAmount(sfReserveBaseDrops) == XRPAmount{setup.account_reserve});
637 BEAST_EXPECT(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve});
638 }
639
640 void
641 run() override
642 {
643 testSetup();
644 testBasic();
645 testTransactionValidation();
646 testPseudoTransactionProperties();
647 testMultipleFeeUpdates();
648 testWrongLedgerSequence();
649 testPartialFieldUpdates();
650 testSingleInvalidTransaction();
651 testDoValidation();
652 testDoVoting();
653 }
654};
655
656BEAST_DEFINE_TESTSUITE(FeeVote, app, xrpl);
657
658} // namespace test
659} // namespace xrpl
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:148
virtual Config & config()=0
virtual beast::Journal journal(std::string const &name)=0
Manager to process fee votes.
Definition FeeVote.h:12
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:46
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:101
Rules controlling protocol behavior.
Definition Rules.h:19
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:118
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:718
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:772
Holds a collection of configuration values.
Definition BasicConfig.h:25
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
virtual Family & getNodeFamily()=0
virtual TimeKeeper & timeKeeper()=0
time_point now() const override
Returns the current time, using the server's clock.
Definition TimeKeeper.h:44
time_point closeTime() const
Returns the predicted close time, in network time.
Definition TimeKeeper.h:56
void run() override
Runs the suite.
A transaction testing environment.
Definition Env.h:98
Application & app()
Definition Env.h:230
beast::Journal const journal
Definition Env.h:139
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:298
T is_same_v
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:194
auto const data
General field definitions, or fields used in multiple transaction namespaces.
FeatureBitset testable_amendments()
Definition Env.h:55
bool verifyFeeObject(std::shared_ptr< Ledger const > const &ledger, Rules const &rules, FeeSettingsFields const &expected)
STTx createInvalidFeeTx(Rules const &rules, std::uint32_t seq, bool missingRequiredFields=true, bool wrongFeatureFields=false, std::uint32_t uniqueValue=42)
STTx createFeeTx(Rules const &rules, std::uint32_t seq, FeeSettingsFields const &fields)
bool applyFeeAndTestResult(jtx::Env &env, OpenView &view, STTx const &tx)
std::vector< STTx > getTxs(std::shared_ptr< SHAMap > const &txSet)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
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.
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:117
create_genesis_t const create_genesis
Definition Ledger.cpp:32
FeeSetup setup_FeeVote(Section const &section)
Definition Config.cpp:1024
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
@ tapNONE
Definition ApplyView.h:12
@ tesSUCCESS
Definition TER.h:226
T push_back(T... args)
Fee schedule for startup / standalone, and to vote for.
Definition Config.h:47
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition Config.h:49
XRPAmount account_reserve
The account reserve requirement in drops.
Definition Config.h:52
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
Definition Config.h:55
std::optional< std::uint64_t > baseFee
std::optional< XRPAmount > reserveIncrementDrops
std::optional< std::uint32_t > reserveBase
std::optional< XRPAmount > baseFeeDrops
std::optional< XRPAmount > reserveBaseDrops
std::optional< std::uint32_t > reserveIncrement
std::optional< std::uint32_t > referenceFeeUnits
Set the sequence number on a JTx.
Definition seq.h:15
T to_string(T... args)