rippled
Loading...
Searching...
No Matches
TicketCreate.cpp
1#include <xrpl/ledger/View.h>
2#include <xrpl/ledger/helpers/AccountRootHelpers.h>
3#include <xrpl/ledger/helpers/DirectoryHelpers.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/Indexes.h>
6#include <xrpl/protocol/TxFlags.h>
7#include <xrpl/tx/transactors/system/TicketCreate.h>
8
9namespace xrpl {
10
11TxConsequences
13{
14 // Create TxConsequences identifying the number of sequences consumed.
15 return TxConsequences{ctx.tx, ctx.tx[sfTicketCount]};
16}
17
20{
21 if (std::uint32_t const count = ctx.tx[sfTicketCount];
22 count < minValidCount || count > maxValidCount)
23 return temINVALID_COUNT;
24
25 return tesSUCCESS;
26}
27
28TER
30{
31 auto const id = ctx.tx[sfAccount];
32 auto const sleAccountRoot = ctx.view.read(keylet::account(id));
33 if (!sleAccountRoot)
34 return terNO_ACCOUNT;
35
36 // Make sure the TicketCreate would not cause the account to own
37 // too many tickets.
38 std::uint32_t const curTicketCount = (*sleAccountRoot)[~sfTicketCount].value_or(0u);
39 std::uint32_t const addedTickets = ctx.tx[sfTicketCount];
40 std::uint32_t const consumedTickets = ctx.tx.getSeqProxy().isTicket() ? 1u : 0u;
41
42 // Note that unsigned integer underflow can't currently happen because
43 // o curTicketCount >= 0
44 // o addedTickets >= 1
45 // o consumedTickets <= 1
46 // So in the worst case addedTickets == consumedTickets and the
47 // computation yields curTicketCount.
48 if (curTicketCount + addedTickets - consumedTickets > maxTicketThreshold)
49 return tecDIR_FULL;
50
51 return tesSUCCESS;
52}
53
54TER
56{
57 SLE::pointer const sleAccountRoot = view().peek(keylet::account(account_));
58 if (!sleAccountRoot)
59 return tefINTERNAL; // LCOV_EXCL_LINE
60
61 // Each ticket counts against the reserve of the issuing account, but we
62 // check the starting balance because we want to allow dipping into the
63 // reserve to pay fees.
64 std::uint32_t const ticketCount = ctx_.tx[sfTicketCount];
65 {
66 XRPAmount const reserve =
67 view().fees().accountReserve(sleAccountRoot->getFieldU32(sfOwnerCount) + ticketCount);
68
69 if (preFeeBalance_ < reserve)
71 }
72
73 beast::Journal const viewJ{ctx_.registry.get().getJournal("View")};
74
75 // The starting ticket sequence is the same as the current account
76 // root sequence. Before we got here to doApply(), the transaction
77 // machinery already incremented the account root sequence if that
78 // was appropriate.
79 std::uint32_t const firstTicketSeq = (*sleAccountRoot)[sfSequence];
80
81 // Sanity check that the transaction machinery really did already
82 // increment the account root Sequence.
83 if (std::uint32_t const txSeq = ctx_.tx[sfSequence];
84 txSeq != 0 && txSeq != (firstTicketSeq - 1))
85 return tefINTERNAL; // LCOV_EXCL_LINE
86
87 for (std::uint32_t i = 0; i < ticketCount; ++i)
88 {
89 std::uint32_t const curTicketSeq = firstTicketSeq + i;
90 Keylet const ticketKeylet = keylet::ticket(account_, curTicketSeq);
91 SLE::pointer const sleTicket = std::make_shared<SLE>(ticketKeylet);
92
93 sleTicket->setAccountID(sfAccount, account_);
94 sleTicket->setFieldU32(sfTicketSequence, curTicketSeq);
95 view().insert(sleTicket);
96
97 auto const page =
99
100 JLOG(j_.trace()) << "Creating ticket " << to_string(ticketKeylet.key) << ": "
101 << (page ? "success" : "failure");
102
103 if (!page)
104 return tecDIR_FULL; // LCOV_EXCL_LINE
105
106 sleTicket->setFieldU64(sfOwnerNode, *page);
107 }
108
109 // Update the record of the number of Tickets this account owns.
110 std::uint32_t const oldTicketCount = (*(sleAccountRoot))[~sfTicketCount].value_or(0u);
111
112 sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount);
113
114 // Every added Ticket counts against the creator's reserve.
115 adjustOwnerCount(view(), sleAccountRoot, ticketCount, viewJ);
116
117 // TicketCreate is the only transaction that can cause an account root's
118 // Sequence field to increase by more than one. October 2018.
119 sleAccountRoot->setFieldU32(sfSequence, firstTicketSeq + ticketCount);
120
121 return tesSUCCESS;
122}
123
124} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream trace() const
Severity stream access functions.
Definition Journal.h:295
STTx const & tx
std::reference_wrapper< ServiceRegistry > registry
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition ApplyView.h:289
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
SeqProxy getSeqProxy() const
Definition STTx.cpp:194
constexpr bool isTicket() const
Definition SeqProxy.h:74
static NotTEC preflight(PreflightContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
static constexpr std::uint32_t maxValidCount
TER doApply() override
Precondition: fee collection is likely.
static constexpr std::uint32_t maxTicketThreshold
static TER preclaim(PreclaimContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
AccountID const account_
Definition Transactor.h:116
beast::Journal const j_
Definition Transactor.h:114
ApplyView & view()
Definition Transactor.h:132
XRPAmount preFeeBalance_
Definition Transactor.h:117
ApplyContext & ctx_
Definition Transactor.h:112
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:38
T is_same_v
static ticket_t const ticket
Definition Indexes.h:148
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:336
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ terNO_ACCOUNT
Definition TER.h:197
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:602
@ tefINTERNAL
Definition TER.h:153
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
@ temINVALID_COUNT
Definition TER.h:101
@ tecDIR_FULL
Definition TER.h:268
@ tecINSUFFICIENT_RESERVE
Definition TER.h:288
@ tesSUCCESS
Definition TER.h:225
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
uint256 key
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:57
ReadView const & view
Definition Transactor.h:60
State information when preflighting a tx.
Definition Transactor.h:14