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/ledger/View.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Indexes.h>
7#include <xrpl/protocol/TxFlags.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]; 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 = (*sleAccountRoot)[~sfTicketCount].value_or(0u);
38 std::uint32_t const addedTickets = ctx.tx[sfTicketCount];
39 std::uint32_t const consumedTickets = ctx.tx.getSeqProxy().isTicket() ? 1u : 0u;
40
41 // Note that unsigned integer underflow can't currently happen because
42 // o curTicketCount >= 0
43 // o addedTickets >= 1
44 // o consumedTickets <= 1
45 // So in the worst case addedTickets == consumedTickets and the
46 // computation yields curTicketCount.
47 if (curTicketCount + addedTickets - consumedTickets > maxTicketThreshold)
48 return tecDIR_FULL;
49
50 return tesSUCCESS;
51}
52
53TER
55{
56 SLE::pointer const sleAccountRoot = view().peek(keylet::account(account_));
57 if (!sleAccountRoot)
58 return tefINTERNAL; // LCOV_EXCL_LINE
59
60 // Each ticket counts against the reserve of the issuing account, but we
61 // check the starting balance because we want to allow dipping into the
62 // reserve to pay fees.
63 std::uint32_t const ticketCount = ctx_.tx[sfTicketCount];
64 {
65 XRPAmount const reserve = view().fees().accountReserve(sleAccountRoot->getFieldU32(sfOwnerCount) + ticketCount);
66
67 if (mPriorBalance < reserve)
69 }
70
71 beast::Journal viewJ{ctx_.app.journal("View")};
72
73 // The starting ticket sequence is the same as the current account
74 // root sequence. Before we got here to doApply(), the transaction
75 // machinery already incremented the account root sequence if that
76 // was appropriate.
77 std::uint32_t const firstTicketSeq = (*sleAccountRoot)[sfSequence];
78
79 // Sanity check that the transaction machinery really did already
80 // increment the account root Sequence.
81 if (std::uint32_t const txSeq = ctx_.tx[sfSequence]; txSeq != 0 && txSeq != (firstTicketSeq - 1))
82 return tefINTERNAL; // LCOV_EXCL_LINE
83
84 for (std::uint32_t i = 0; i < ticketCount; ++i)
85 {
86 std::uint32_t const curTicketSeq = firstTicketSeq + i;
87 Keylet const ticketKeylet = keylet::ticket(account_, curTicketSeq);
88 SLE::pointer sleTicket = std::make_shared<SLE>(ticketKeylet);
89
90 sleTicket->setAccountID(sfAccount, account_);
91 sleTicket->setFieldU32(sfTicketSequence, curTicketSeq);
92 view().insert(sleTicket);
93
94 auto const page = view().dirInsert(keylet::ownerDir(account_), ticketKeylet, describeOwnerDir(account_));
95
96 JLOG(j_.trace()) << "Creating ticket " << to_string(ticketKeylet.key) << ": " << (page ? "success" : "failure");
97
98 if (!page)
99 return tecDIR_FULL; // LCOV_EXCL_LINE
100
101 sleTicket->setFieldU64(sfOwnerNode, *page);
102 }
103
104 // Update the record of the number of Tickets this account owns.
105 std::uint32_t const oldTicketCount = (*(sleAccountRoot))[~sfTicketCount].value_or(0u);
106
107 sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount);
108
109 // Every added Ticket counts against the creator's reserve.
110 adjustOwnerCount(view(), sleAccountRoot, ticketCount, viewJ);
111
112 // TicketCreate is the only transaction that can cause an account root's
113 // Sequence field to increase by more than one. October 2018.
114 sleAccountRoot->setFieldU32(sfSequence, firstTicketSeq + ticketCount);
115
116 return tesSUCCESS;
117}
118
119} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream trace() const
Severity stream access functions.
Definition Journal.h:294
STTx const & tx
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:283
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
static TER preclaim(PreclaimContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
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 maxTicketThreshold
static constexpr std::uint32_t maxValidCount
TER doApply() override
Precondition: fee collection is likely.
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:193
constexpr bool isTicket() const
Definition SeqProxy.h:74
virtual beast::Journal journal(std::string const &name)=0
AccountID const account_
Definition Transactor.h:112
beast::Journal const j_
Definition Transactor.h:110
ApplyView & view()
Definition Transactor.h:128
XRPAmount mPriorBalance
Definition Transactor.h:113
ApplyContext & ctx_
Definition Transactor.h:108
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:37
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:325
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:160
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:597
@ 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.
Definition View.cpp:941
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:955
@ 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:53
ReadView const & view
Definition Transactor.h:56
State information when preflighting a tx.
Definition Transactor.h:15