rippled
CreateTicket.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2014 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/ledger/Ledger.h>
21 #include <ripple/app/tx/impl/CreateTicket.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/protocol/Feature.h>
24 #include <ripple/protocol/Indexes.h>
25 #include <ripple/protocol/TxFlags.h>
26 #include <ripple/protocol/st.h>
27 
28 namespace ripple {
29 
30 TxConsequences
32 {
33  // Create TxConsequences identifying the number of sequences consumed.
34  return TxConsequences{ctx.tx, ctx.tx[sfTicketCount]};
35 }
36 
37 NotTEC
39 {
41  return temDISABLED;
42 
43  if (ctx.tx.getFlags() & tfUniversalMask)
44  return temINVALID_FLAG;
45 
46  if (std::uint32_t const count = ctx.tx[sfTicketCount];
47  count < minValidCount || count > maxValidCount)
48  return temINVALID_COUNT;
49 
50  if (NotTEC const ret{preflight1(ctx)}; !isTesSuccess(ret))
51  return ret;
52 
53  return preflight2(ctx);
54 }
55 
56 TER
58 {
59  auto const id = ctx.tx[sfAccount];
60  auto const sleAccountRoot = ctx.view.read(keylet::account(id));
61  if (!sleAccountRoot)
62  return terNO_ACCOUNT;
63 
64  // Make sure the TicketCreate would not cause the account to own
65  // too many tickets.
66  std::uint32_t const curTicketCount =
67  (*sleAccountRoot)[~sfTicketCount].value_or(0u);
68  std::uint32_t const addedTickets = ctx.tx[sfTicketCount];
69  std::uint32_t const consumedTickets =
70  ctx.tx.getSeqProxy().isTicket() ? 1u : 0u;
71 
72  // Note that unsigned integer underflow can't currently happen because
73  // o curTicketCount >= 0
74  // o addedTickets >= 1
75  // o consumedTickets <= 1
76  // So in the worst case addedTickets == consumedTickets and the
77  // computation yields curTicketCount.
78  if (curTicketCount + addedTickets - consumedTickets > maxTicketThreshold)
79  return tecDIR_FULL;
80 
81  return tesSUCCESS;
82 }
83 
84 TER
86 {
87  SLE::pointer const sleAccountRoot = view().peek(keylet::account(account_));
88  if (!sleAccountRoot)
89  return tefINTERNAL;
90 
91  // Each ticket counts against the reserve of the issuing account, but we
92  // check the starting balance because we want to allow dipping into the
93  // reserve to pay fees.
94  std::uint32_t const ticketCount = ctx_.tx[sfTicketCount];
95  {
96  XRPAmount const reserve = view().fees().accountReserve(
97  sleAccountRoot->getFieldU32(sfOwnerCount) + ticketCount);
98 
99  if (mPriorBalance < reserve)
101  }
102 
103  beast::Journal viewJ{ctx_.app.journal("View")};
104 
105  // The starting ticket sequence is the same as the current account
106  // root sequence. Before we got here to doApply(), the transaction
107  // machinery already incremented the account root sequence if that
108  // was appropriate.
109  std::uint32_t const firstTicketSeq = (*sleAccountRoot)[sfSequence];
110 
111  // Sanity check that the transaction machinery really did already
112  // increment the account root Sequence.
113  if (std::uint32_t const txSeq = ctx_.tx[sfSequence];
114  txSeq != 0 && txSeq != (firstTicketSeq - 1))
115  return tefINTERNAL;
116 
117  for (std::uint32_t i = 0; i < ticketCount; ++i)
118  {
119  std::uint32_t const curTicketSeq = firstTicketSeq + i;
120  Keylet const ticketKeylet = keylet::ticket(account_, curTicketSeq);
121  SLE::pointer sleTicket = std::make_shared<SLE>(ticketKeylet);
122 
123  sleTicket->setAccountID(sfAccount, account_);
124  sleTicket->setFieldU32(sfTicketSequence, curTicketSeq);
125  view().insert(sleTicket);
126 
127  auto const page = view().dirInsert(
129  ticketKeylet,
131 
132  JLOG(j_.trace()) << "Creating ticket " << to_string(ticketKeylet.key)
133  << ": " << (page ? "success" : "failure");
134 
135  if (!page)
136  return tecDIR_FULL;
137 
138  sleTicket->setFieldU64(sfOwnerNode, *page);
139  }
140 
141  // Update the record of the number of Tickets this account owns.
142  std::uint32_t const oldTicketCount =
143  (*(sleAccountRoot))[~sfTicketCount].value_or(0u);
144 
145  sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount);
146 
147  // Every added Ticket counts against the creator's reserve.
148  adjustOwnerCount(view(), sleAccountRoot, ticketCount, viewJ);
149 
150  // TicketCreate is the only transaction that can cause an account root's
151  // Sequence field to increase by more than one. October 2018.
152  sleAccountRoot->setFieldU32(sfSequence, firstTicketSeq + ticketCount);
153 
154  return tesSUCCESS;
155 }
156 
157 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:303
ripple::sfOwnerCount
const SF_UINT32 sfOwnerCount
ripple::preflight2
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:130
ripple::CreateTicket::maxValidCount
constexpr static std::uint32_t maxValidCount
Definition: CreateTicket.h:57
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::tefINTERNAL
@ tefINTERNAL
Definition: TER.h:155
ripple::Rules::enabled
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:94
std::shared_ptr< STLedgerEntry >
ripple::PreclaimContext::view
ReadView const & view
Definition: Transactor.h:56
ripple::sfOwnerNode
const SF_UINT64 sfOwnerNode
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::ApplyView::peek
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
ripple::describeOwnerDir
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition: View.cpp:731
ripple::CreateTicket::makeTxConsequences
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
Definition: CreateTicket.cpp:31
ripple::Transactor::j_
const beast::Journal j_
Definition: Transactor.h:89
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:597
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::ReadView::fees
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
ripple::STTx::getSeqProxy
SeqProxy getSeqProxy() const
Definition: STTx.cpp:183
ripple::sfTicketSequence
const SF_UINT32 sfTicketSequence
ripple::keylet::ticket
static const ticket_t ticket
Definition: Indexes.h:167
ripple::preflight1
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:78
ripple::ApplyContext::app
Application & app
Definition: ApplyContext.h:47
ripple::SeqProxy::isTicket
constexpr bool isTicket() const
Definition: SeqProxy.h:94
ripple::Keylet::key
uint256 key
Definition: Keylet.h:40
ripple::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:109
ripple::adjustOwnerCount
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:713
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::TERSubset
Definition: TER.h:340
ripple::sfTicketCount
const SF_UINT32 sfTicketCount
ripple::CreateTicket::preclaim
static TER preclaim(PreclaimContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
Definition: CreateTicket.cpp:57
ripple::STObject::getFlags
std::uint32_t getFlags() const
Definition: STObject.cpp:481
ripple::CreateTicket::maxTicketThreshold
constexpr static std::uint32_t maxTicketThreshold
Definition: CreateTicket.h:65
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::PreclaimContext::tx
STTx const & tx
Definition: Transactor.h:58
ripple::tecDIR_FULL
@ tecDIR_FULL
Definition: TER.h:254
ripple::terNO_ACCOUNT
@ terNO_ACCOUNT
Definition: TER.h:198
ripple::PreclaimContext
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:52
ripple::ApplyView::insert
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::Transactor::view
ApplyView & view()
Definition: Transactor.h:107
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:112
ripple::Fees::accountReserve
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
Definition: ReadView.h:66
ripple::Transactor::mPriorBalance
XRPAmount mPriorBalance
Definition: Transactor.h:92
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:274
ripple::featureTicketBatch
const uint256 featureTicketBatch
ripple::Transactor::ctx_
ApplyContext & ctx_
Definition: Transactor.h:88
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::CreateTicket::preflight
static NotTEC preflight(PreflightContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
Definition: CreateTicket.cpp:38
ripple::temINVALID_COUNT
@ temINVALID_COUNT
Definition: TER.h:119
ripple::PreflightContext::tx
STTx const & tx
Definition: Transactor.h:35
ripple::PreflightContext
State information when preflighting a tx.
Definition: Transactor.h:31
ripple::ApplyView::dirInsert
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:306
ripple::PreflightContext::rules
const Rules rules
Definition: Transactor.h:36
ripple::tfUniversalMask
constexpr std::uint32_t tfUniversalMask
Definition: TxFlags.h:60
ripple::TxConsequences
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition: applySteps.h:45
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::CreateTicket::doApply
TER doApply() override
Precondition: fee collection is likely.
Definition: CreateTicket.cpp:85
ripple::Transactor::account_
const AccountID account_
Definition: Transactor.h:91
ripple::ApplyContext::tx
STTx const & tx
Definition: ApplyContext.h:48
ripple::XRPAmount
Definition: XRPAmount.h:46