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 ripple {
16namespace test {
17
28
29STTx
31 Rules const& rules,
33 FeeSettingsFields const& fields)
34{
35 auto fill = [&](auto& obj) {
36 obj.setAccountID(sfAccount, AccountID());
37 obj.setFieldU32(sfLedgerSequence, seq);
38
39 if (rules.enabled(featureXRPFees))
40 {
41 // New XRPFees format - all three fields are REQUIRED
42 obj.setFieldAmount(
43 sfBaseFeeDrops,
44 fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0});
45 obj.setFieldAmount(
46 sfReserveBaseDrops,
47 fields.reserveBaseDrops ? *fields.reserveBaseDrops
48 : XRPAmount{0});
49 obj.setFieldAmount(
50 sfReserveIncrementDrops,
52 : XRPAmount{0});
53 }
54 else
55 {
56 // Legacy format - all four fields are REQUIRED
57 obj.setFieldU64(sfBaseFee, fields.baseFee ? *fields.baseFee : 0);
58 obj.setFieldU32(
59 sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0);
60 obj.setFieldU32(
61 sfReserveIncrement,
62 fields.reserveIncrement ? *fields.reserveIncrement : 0);
63 obj.setFieldU32(
64 sfReferenceFeeUnits,
65 fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
66 }
67 };
68 return STTx(ttFEE, fill);
69}
70
71STTx
73 Rules const& rules,
75 bool missingRequiredFields = true,
76 bool wrongFeatureFields = false,
77 std::uint32_t uniqueValue = 42)
78{
79 auto fill = [&](auto& obj) {
80 obj.setAccountID(sfAccount, AccountID());
81 obj.setFieldU32(sfLedgerSequence, seq);
82
83 if (wrongFeatureFields)
84 {
85 if (rules.enabled(featureXRPFees))
86 {
87 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
88 obj.setFieldU32(sfReserveBase, 200000);
89 obj.setFieldU32(sfReserveIncrement, 50000);
90 obj.setFieldU32(sfReferenceFeeUnits, 10);
91 }
92 else
93 {
94 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10 + uniqueValue});
95 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
96 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
97 }
98 }
99 else if (!missingRequiredFields)
100 {
101 // Create valid transaction (all required fields present)
102 if (rules.enabled(featureXRPFees))
103 {
104 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10 + uniqueValue});
105 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
106 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
107 }
108 else
109 {
110 obj.setFieldU64(sfBaseFee, 10 + uniqueValue);
111 obj.setFieldU32(sfReserveBase, 200000);
112 obj.setFieldU32(sfReserveIncrement, 50000);
113 obj.setFieldU32(sfReferenceFeeUnits, 10);
114 }
115 }
116 // If missingRequiredFields is true, we don't add the required fields
117 // (default behavior)
118 };
119 return STTx(ttFEE, fill);
120}
121
122bool
124{
125 auto const res =
126 apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
127 return res.ter == tesSUCCESS;
128}
129
130bool
132 std::shared_ptr<Ledger const> const& ledger,
133 Rules const& rules,
134 FeeSettingsFields const& expected)
135{
136 auto const feeObject = ledger->read(keylet::fees());
137 if (!feeObject)
138 return false;
139
140 auto checkEquality = [&](auto const& field, auto const& expected) {
141 if (!feeObject->isFieldPresent(field))
142 return false;
143 return feeObject->at(field) == expected;
144 };
145
146 if (rules.enabled(featureXRPFees))
147 {
148 if (feeObject->isFieldPresent(sfBaseFee) ||
149 feeObject->isFieldPresent(sfReserveBase) ||
150 feeObject->isFieldPresent(sfReserveIncrement) ||
151 feeObject->isFieldPresent(sfReferenceFeeUnits))
152 return false;
153
154 if (!checkEquality(
155 sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0})))
156 return false;
157 if (!checkEquality(
158 sfReserveBaseDrops,
159 expected.reserveBaseDrops.value_or(XRPAmount{0})))
160 return false;
161 if (!checkEquality(
162 sfReserveIncrementDrops,
163 expected.reserveIncrementDrops.value_or(XRPAmount{0})))
164 return false;
165 }
166 else
167 {
168 if (feeObject->isFieldPresent(sfBaseFeeDrops) ||
169 feeObject->isFieldPresent(sfReserveBaseDrops) ||
170 feeObject->isFieldPresent(sfReserveIncrementDrops))
171 return false;
172
173 // Read sfBaseFee as a hex string and compare to expected.baseFee
174 if (!checkEquality(sfBaseFee, expected.baseFee))
175 return false;
176 if (!checkEquality(sfReserveBase, expected.reserveBase))
177 return false;
178 if (!checkEquality(sfReserveIncrement, expected.reserveIncrement))
179 return false;
180 if (!checkEquality(sfReferenceFeeUnits, expected.referenceFeeUnits))
181 return false;
182 }
183
184 return true;
185}
186
189{
191 for (auto i = txSet->begin(); i != txSet->end(); ++i)
192 {
193 auto const data = i->slice();
194 auto serialIter = SerialIter(data);
195 txs.push_back(STTx(serialIter));
196 }
197 return txs;
198};
199
201{
202 void
204 {
205 FeeSetup const defaultSetup;
206 {
207 // defaults
208 Section config;
209 auto setup = setup_FeeVote(config);
210 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
211 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
212 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
213 }
214 {
215 Section config;
216 config.append(
217 {"reference_fee = 50",
218 "account_reserve = 1234567",
219 "owner_reserve = 1234"});
220 auto setup = setup_FeeVote(config);
221 BEAST_EXPECT(setup.reference_fee == 50);
222 BEAST_EXPECT(setup.account_reserve == 1234567);
223 BEAST_EXPECT(setup.owner_reserve == 1234);
224 }
225 {
226 Section config;
227 config.append(
228 {"reference_fee = blah",
229 "account_reserve = yada",
230 "owner_reserve = foo"});
231 // Illegal values are ignored, and the defaults left unchanged
232 auto setup = setup_FeeVote(config);
233 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
234 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
235 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
236 }
237 {
238 Section config;
239 config.append(
240 {"reference_fee = -50",
241 "account_reserve = -1234567",
242 "owner_reserve = -1234"});
243 // Illegal values are ignored, and the defaults left unchanged
244 auto setup = setup_FeeVote(config);
245 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
246 BEAST_EXPECT(
247 setup.account_reserve == static_cast<std::uint32_t>(-1234567));
248 BEAST_EXPECT(
249 setup.owner_reserve == static_cast<std::uint32_t>(-1234));
250 }
251 {
252 auto const big64 = std::to_string(
253 static_cast<std::uint64_t>(
255 1);
256 Section config;
257 config.append(
258 {"reference_fee = " + big64,
259 "account_reserve = " + big64,
260 "owner_reserve = " + big64});
261 // Illegal values are ignored, and the defaults left unchanged
262 auto setup = setup_FeeVote(config);
263 BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
264 BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
265 BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
266 }
267 }
268
269 void
271 {
272 testcase("Basic SetFee transaction");
273
274 // Test with XRPFees disabled (legacy format)
275 {
276 jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
277 auto ledger = std::make_shared<Ledger>(
279 env.app().config(),
281 env.app().getNodeFamily());
282
283 // Create the next ledger to apply transaction to
285 *ledger, env.app().timeKeeper().closeTime());
286
287 // Test successful fee transaction with legacy fields
288
289 FeeSettingsFields fields{
290 .baseFee = 10,
291 .reserveBase = 200000,
292 .reserveIncrement = 50000,
293 .referenceFeeUnits = 10};
294 auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
295
296 OpenView accum(ledger.get());
297 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
298 accum.apply(*ledger);
299
300 // Verify fee object was created/updated correctly
301 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
302 }
303
304 // Test with XRPFees enabled (new format)
305 {
306 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
307 auto ledger = std::make_shared<Ledger>(
309 env.app().config(),
311 env.app().getNodeFamily());
312
313 // Create the next ledger to apply transaction to
315 *ledger, env.app().timeKeeper().closeTime());
316
317 FeeSettingsFields fields{
318 .baseFeeDrops = XRPAmount{10},
319 .reserveBaseDrops = XRPAmount{200000},
320 .reserveIncrementDrops = XRPAmount{50000}};
321 // Test successful fee transaction with new fields
322 auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
323
324 OpenView accum(ledger.get());
325 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
326 accum.apply(*ledger);
327
328 // Verify fee object was created/updated correctly
329 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
330 }
331 }
332
333 void
335 {
336 testcase("Fee Transaction Validation");
337
338 {
339 jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
340 auto ledger = std::make_shared<Ledger>(
342 env.app().config(),
344 env.app().getNodeFamily());
345
346 // Create the next ledger to apply transaction to
348 *ledger, env.app().timeKeeper().closeTime());
349
350 // Test transaction with missing required legacy fields
351 auto invalidTx = createInvalidFeeTx(
352 ledger->rules(), ledger->seq(), true, false, 1);
353 OpenView accum(ledger.get());
354 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
355
356 // Test transaction with new format fields when XRPFees is disabled
357 auto disallowedTx = createInvalidFeeTx(
358 ledger->rules(), ledger->seq(), false, true, 2);
359 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
360 }
361
362 {
363 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
364 auto ledger = std::make_shared<Ledger>(
366 env.app().config(),
368 env.app().getNodeFamily());
369
370 // Create the next ledger to apply transaction to
372 *ledger, env.app().timeKeeper().closeTime());
373
374 // Test transaction with missing required new fields
375 auto invalidTx = createInvalidFeeTx(
376 ledger->rules(), ledger->seq(), true, false, 3);
377 OpenView accum(ledger.get());
378 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
379
380 // Test transaction with legacy fields when XRPFees is enabled
381 auto disallowedTx = createInvalidFeeTx(
382 ledger->rules(), ledger->seq(), false, true, 4);
383 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
384 }
385 }
386
387 void
389 {
390 testcase("Pseudo Transaction Properties");
391
393 auto ledger = std::make_shared<Ledger>(
395 env.app().config(),
397 env.app().getNodeFamily());
398
399 // Create the next ledger to apply transaction to
401 *ledger, env.app().timeKeeper().closeTime());
402
403 auto feeTx = createFeeTx(
404 ledger->rules(),
405 ledger->seq(),
406 {.baseFeeDrops = XRPAmount{10},
407 .reserveBaseDrops = XRPAmount{200000},
408 .reserveIncrementDrops = XRPAmount{50000}});
409
410 // Verify pseudo-transaction properties
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));
418
419 // But can be applied to a closed ledger
420 {
421 OpenView closedAccum(ledger.get());
422 BEAST_EXPECT(applyFeeAndTestResult(env, closedAccum, feeTx));
423 }
424 }
425
426 void
428 {
429 testcase("Multiple Fee Updates");
430
431 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
432 auto ledger = std::make_shared<Ledger>(
434 env.app().config(),
436 env.app().getNodeFamily());
437
439 *ledger, env.app().timeKeeper().closeTime());
440
441 FeeSettingsFields fields1{
442 .baseFeeDrops = XRPAmount{10},
443 .reserveBaseDrops = XRPAmount{200000},
444 .reserveIncrementDrops = XRPAmount{50000}};
445 auto feeTx1 = createFeeTx(ledger->rules(), ledger->seq(), fields1);
446
447 {
448 OpenView accum(ledger.get());
449 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
450 accum.apply(*ledger);
451 }
452
453 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
454
455 // Apply second fee transaction with different values
457 *ledger, env.app().timeKeeper().closeTime());
458
459 FeeSettingsFields fields2{
460 .baseFeeDrops = XRPAmount{20},
461 .reserveBaseDrops = XRPAmount{300000},
462 .reserveIncrementDrops = XRPAmount{75000}};
463 auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2);
464
465 {
466 OpenView accum(ledger.get());
467 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
468 accum.apply(*ledger);
469 }
470
471 // Verify second update overwrote the first
472 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields2));
473 }
474
475 void
477 {
478 testcase("Wrong Ledger Sequence");
479
480 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
481 auto ledger = std::make_shared<Ledger>(
483 env.app().config(),
485 env.app().getNodeFamily());
486
488 *ledger, env.app().timeKeeper().closeTime());
489
490 // Test transaction with wrong ledger sequence
491 auto feeTx = createFeeTx(
492 ledger->rules(),
493 ledger->seq() + 5, // Wrong sequence (should be ledger->seq())
494 {.baseFeeDrops = XRPAmount{10},
495 .reserveBaseDrops = XRPAmount{200000},
496 .reserveIncrementDrops = XRPAmount{50000}});
497
498 OpenView accum(ledger.get());
499
500 // The transaction should still succeed as long as other fields are
501 // valid
502 // The ledger sequence field is only used for informational purposes
503 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
504 }
505
506 void
508 {
509 testcase("Partial Field Updates");
510
511 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
512 auto ledger = std::make_shared<Ledger>(
514 env.app().config(),
516 env.app().getNodeFamily());
517
519 *ledger, env.app().timeKeeper().closeTime());
520
521 FeeSettingsFields fields1{
522 .baseFeeDrops = XRPAmount{10},
523 .reserveBaseDrops = XRPAmount{200000},
524 .reserveIncrementDrops = XRPAmount{50000}};
525 auto feeTx1 = createFeeTx(ledger->rules(), ledger->seq(), fields1);
526
527 {
528 OpenView accum(ledger.get());
529 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
530 accum.apply(*ledger);
531 }
532
533 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1));
534
536 *ledger, env.app().timeKeeper().closeTime());
537
538 // Apply partial update (only some fields)
539 FeeSettingsFields fields2{
540 .baseFeeDrops = XRPAmount{20},
541 .reserveBaseDrops = XRPAmount{200000}};
542 auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2);
543
544 {
545 OpenView accum(ledger.get());
546 BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
547 accum.apply(*ledger);
548 }
549
550 // Verify the partial update worked
551 BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields2));
552 }
553
554 void
556 {
557 testcase("Single Invalid Transaction");
558
559 jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
560 auto ledger = std::make_shared<Ledger>(
562 env.app().config(),
564 env.app().getNodeFamily());
565
567 *ledger, env.app().timeKeeper().closeTime());
568
569 // Test invalid transaction with non-zero account - this should fail
570 // validation
571 auto invalidTx = STTx(ttFEE, [&](auto& obj) {
572 obj.setAccountID(
573 sfAccount,
574 AccountID(1)); // Should be zero (this makes it invalid)
575 obj.setFieldU32(sfLedgerSequence, ledger->seq());
576 obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10});
577 obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000});
578 obj.setFieldAmount(sfReserveIncrementDrops, XRPAmount{50000});
579 });
580
581 OpenView accum(ledger.get());
582 BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
583 }
584
585 void
587 {
588 testcase("doValidation");
589
590 using namespace jtx;
591
592 FeeSetup setup;
593 setup.reference_fee = 42;
594 setup.account_reserve = 1234567;
595 setup.owner_reserve = 7654321;
596
597 // Test with XRPFees enabled
598 {
599 Env env(*this, testable_amendments() | featureXRPFees);
600 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
601
602 auto ledger = std::make_shared<Ledger>(
604 env.app().config(),
606 env.app().getNodeFamily());
607
608 auto sec = randomSecretKey();
609 auto pub = derivePublicKey(KeyType::secp256k1, sec);
610
612 env.app().timeKeeper().now(),
613 pub,
614 sec,
615 calcNodeID(pub),
616 [](STValidation& v) {
617 v.setFieldU32(sfLedgerSequence, 12345);
618 });
619
620 // Use the current ledger's fees as the "current" fees for
621 // doValidation
622 auto const& currentFees = ledger->fees();
623
624 feeVote->doValidation(currentFees, ledger->rules(), *val);
625
626 BEAST_EXPECT(val->isFieldPresent(sfBaseFeeDrops));
627 BEAST_EXPECT(
628 val->getFieldAmount(sfBaseFeeDrops) ==
629 XRPAmount(setup.reference_fee));
630 }
631
632 // Test with XRPFees disabled (legacy format)
633 {
634 Env env(*this, testable_amendments() - featureXRPFees);
635 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
636
637 auto ledger = std::make_shared<Ledger>(
639 env.app().config(),
641 env.app().getNodeFamily());
642
643 auto sec = randomSecretKey();
644 auto pub = derivePublicKey(KeyType::secp256k1, sec);
645
647 env.app().timeKeeper().now(),
648 pub,
649 sec,
650 calcNodeID(pub),
651 [](STValidation& v) {
652 v.setFieldU32(sfLedgerSequence, 12345);
653 });
654
655 auto const& currentFees = ledger->fees();
656
657 feeVote->doValidation(currentFees, ledger->rules(), *val);
658
659 // In legacy mode, should vote using legacy fields
660 BEAST_EXPECT(val->isFieldPresent(sfBaseFee));
661 BEAST_EXPECT(val->getFieldU64(sfBaseFee) == setup.reference_fee);
662 }
663 }
664
665 void
667 {
668 testcase("doVoting");
669
670 using namespace jtx;
671
672 FeeSetup setup;
673 setup.reference_fee = 42;
674 setup.account_reserve = 1234567;
675 setup.owner_reserve = 7654321;
676
677 Env env(*this, testable_amendments() | featureXRPFees);
678
679 // establish what the current fees are
680 BEAST_EXPECT(
681 env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
682 BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
683 BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
684
685 auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
686 auto ledger = std::make_shared<Ledger>(
688 env.app().config(),
690 env.app().getNodeFamily());
691
692 // doVoting requires a flag ledger (every 256th ledger)
693 // We need to create a ledger at sequence 256 to make it a flag ledger
694 for (int i = 0; i < 256 - 1; ++i)
695 {
697 *ledger, env.app().timeKeeper().closeTime());
698 }
699 BEAST_EXPECT(ledger->isFlagLedger());
700
701 // Create some mock validations with fee votes
703
704 for (int i = 0; i < 5; i++)
705 {
706 auto sec = randomSecretKey();
707 auto pub = derivePublicKey(KeyType::secp256k1, sec);
708
710 env.app().timeKeeper().now(),
711 pub,
712 sec,
713 calcNodeID(pub),
714 [&](STValidation& v) {
715 v.setFieldU32(sfLedgerSequence, ledger->seq());
716 // Vote for different fees than current
718 sfBaseFeeDrops, XRPAmount{setup.reference_fee});
720 sfReserveBaseDrops, XRPAmount{setup.account_reserve});
722 sfReserveIncrementDrops,
723 XRPAmount{setup.owner_reserve});
724 });
725 if (i % 2)
726 val->setTrusted();
727 validations.push_back(val);
728 }
729
730 auto txSet = std::make_shared<SHAMap>(
732
733 // This should not throw since we have a flag ledger
734 feeVote->doVoting(ledger, validations, txSet);
735
736 auto const txs = getTxs(txSet);
737 BEAST_EXPECT(txs.size() == 1);
738 auto const& feeTx = txs[0];
739
740 BEAST_EXPECT(feeTx.getTxnType() == ttFEE);
741
742 BEAST_EXPECT(feeTx.getAccountID(sfAccount) == AccountID());
743 BEAST_EXPECT(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1);
744
745 BEAST_EXPECT(feeTx.isFieldPresent(sfBaseFeeDrops));
746 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveBaseDrops));
747 BEAST_EXPECT(feeTx.isFieldPresent(sfReserveIncrementDrops));
748
749 // The legacy fields should NOT be present
750 BEAST_EXPECT(!feeTx.isFieldPresent(sfBaseFee));
751 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveBase));
752 BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveIncrement));
753 BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
754
755 // Check the values
756 BEAST_EXPECT(
757 feeTx.getFieldAmount(sfBaseFeeDrops) ==
758 XRPAmount{setup.reference_fee});
759 BEAST_EXPECT(
760 feeTx.getFieldAmount(sfReserveBaseDrops) ==
761 XRPAmount{setup.account_reserve});
762 BEAST_EXPECT(
763 feeTx.getFieldAmount(sfReserveIncrementDrops) ==
764 XRPAmount{setup.owner_reserve});
765 }
766
767 void
768 run() override
769 {
770 testSetup();
771 testBasic();
772 testTransactionValidation();
773 testPseudoTransactionProperties();
774 testMultipleFeeUpdates();
775 testWrongLedgerSequence();
776 testPartialFieldUpdates();
777 testSingleInvalidTransaction();
778 testDoValidation();
779 testDoVoting();
780 }
781};
782
783BEAST_DEFINE_TESTSUITE(FeeVote, app, ripple);
784
785} // namespace test
786} // namespace ripple
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
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.
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:109
Rules controlling protocol behavior.
Definition Rules.h:19
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:111
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:792
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:738
Holds a collection of configuration values.
Definition BasicConfig.h:26
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.
Definition TimeKeeper.h:45
time_point closeTime() const
Returns the predicted close time, in network time.
Definition TimeKeeper.h:57
void run() override
Runs the suite.
A transaction testing environment.
Definition Env.h:102
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:312
Application & app()
Definition Env.h:242
beast::Journal const journal
Definition Env.h:143
T is_same_v
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:203
auto const data
General field definitions, or fields used in multiple transaction namespaces.
FeatureBitset testable_amendments()
Definition Env.h:55
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.
Definition algorithm.h:6
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
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.
@ tesSUCCESS
Definition TER.h:226
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:127
FeeSetup setup_FeeVote(Section const &section)
Definition Config.cpp:1110
create_genesis_t const create_genesis
Definition Ledger.cpp:32
@ tapNONE
Definition ApplyView.h:12
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 owner_reserve
The per-owned item reserve requirement in drops.
Definition Config.h:55
XRPAmount account_reserve
The account reserve requirement in drops.
Definition Config.h:52
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.
Definition seq.h:15
T to_string(T... args)