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