rippled
LocalTxs.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/ledger/LocalTxs.h>
22 #include <ripple/app/main/Application.h>
23 #include <ripple/protocol/Indexes.h>
24 
25 /*
26  This code prevents scenarios like the following:
27 1) A client submits a transaction.
28 2) The transaction gets into the ledger this server
29  believes will be the consensus ledger.
30 3) The server builds a succeeding open ledger without the
31  transaction (because it's in the prior ledger).
32 4) The local consensus ledger is not the majority ledger
33  (due to network conditions, Byzantine fault, etcetera)
34  the majority ledger does not include the transaction.
35 5) The server builds a new open ledger that does not include
36  the transaction or have it in a prior ledger.
37 6) The client submits another transaction and gets a terPRE_SEQ
38  preliminary result.
39 7) The server does not relay that second transaction, at least
40  not yet.
41 
42 With this code, when step 5 happens, the first transaction will
43 be applied to that open ledger so the second transaction will
44 succeed normally at step 6. Transactions remain tracked and
45 test-applied to all new open ledgers until seen in a fully-
46 validated ledger
47 */
48 
49 namespace ripple {
50 
51 // This class wraps a pointer to a transaction along with
52 // its expiration ledger. It also caches the issuing account.
53 class LocalTx
54 {
55 public:
56 
57  // The number of ledgers to hold a transaction is essentially
58  // arbitrary. It should be sufficient to allow the transaction to
59  // get into a fully-validated ledger.
60  static int const holdLedgers = 5;
61 
63  : m_txn (txn)
64  , m_expire (index + holdLedgers)
65  , m_id (txn->getTransactionID ())
66  , m_account (txn->getAccountID(sfAccount))
67  , m_seq (txn->getSequence())
68  {
69  if (txn->isFieldPresent (sfLastLedgerSequence))
70  m_expire = std::min (m_expire, txn->getFieldU32 (sfLastLedgerSequence) + 1);
71  }
72 
73  uint256 const& getID () const
74  {
75  return m_id;
76  }
77 
79  {
80  return m_seq;
81  }
82 
83  bool isExpired (LedgerIndex i) const
84  {
85  return i > m_expire;
86  }
87 
89  {
90  return m_txn;
91  }
92 
93  AccountID const& getAccount () const
94  {
95  return m_account;
96  }
97 
98 private:
99 
105 };
106 
107 //------------------------------------------------------------------------------
108 
110  : public LocalTxs
111 {
112 public:
113  LocalTxsImp() = default;
114 
115  // Add a new transaction to the set of local transactions
116  void push_back (LedgerIndex index, std::shared_ptr<STTx const> const& txn) override
117  {
118  std::lock_guard lock (m_lock);
119 
120  m_txns.emplace_back (index, txn);
121  }
122 
124  getTxSet () override
125  {
126  CanonicalTXSet tset (uint256 {});
127 
128  // Get the set of local transactions as a canonical
129  // set (so they apply in a valid order)
130  {
131  std::lock_guard lock (m_lock);
132 
133  for (auto const& it : m_txns)
134  tset.insert (it.getTX());
135  }
136 
137  return tset;
138  }
139 
140  // Remove transactions that have either been accepted
141  // into a fully-validated ledger, are (now) impossible,
142  // or have expired
143  void sweep (ReadView const& view) override
144  {
145  std::lock_guard lock (m_lock);
146 
147  m_txns.remove_if ([&view](auto const& txn)
148  {
149  if (txn.isExpired (view.info().seq))
150  return true;
151  if (view.txExists(txn.getID()))
152  return true;
153 
154  std::shared_ptr<SLE const> sle = view.read(
155  keylet::account(txn.getAccount()));
156  if (! sle)
157  return false;
158  return sle->getFieldU32 (sfSequence) > txn.getSeq ();
159  });
160  }
161 
162  std::size_t size () override
163  {
164  std::lock_guard lock (m_lock);
165 
166  return m_txns.size ();
167  }
168 
169 private:
172 };
173 
176 {
177  return std::make_unique<LocalTxsImp> ();
178 }
179 
180 } // ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::LocalTx::getAccount
AccountID const & getAccount() const
Definition: LocalTxs.cpp:93
ripple::LocalTx::getSeq
std::uint32_t getSeq() const
Definition: LocalTxs.cpp:78
ripple::LocalTxsImp::m_txns
std::list< LocalTx > m_txns
Definition: LocalTxs.cpp:171
std::shared_ptr
STL class.
ripple::LocalTx::isExpired
bool isExpired(LedgerIndex i) const
Definition: LocalTxs.cpp:83
std::list
STL class.
ripple::LocalTx::m_expire
LedgerIndex m_expire
Definition: LocalTxs.cpp:101
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:340
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:460
ripple::LocalTxsImp::sweep
void sweep(ReadView const &view) override
Definition: LocalTxs.cpp:143
std::lock_guard
STL class.
ripple::LocalTxsImp::push_back
void push_back(LedgerIndex index, std::shared_ptr< STTx const > const &txn) override
Definition: LocalTxs.cpp:116
ripple::LocalTx::LocalTx
LocalTx(LedgerIndex index, std::shared_ptr< STTx const > const &txn)
Definition: LocalTxs.cpp:62
ripple::ReadView::txExists
virtual bool txExists(key_type const &key) const =0
Returns true if a tx exists in the tx map.
ripple::LocalTxsImp::m_lock
std::mutex m_lock
Definition: LocalTxs.cpp:170
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:87
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:36
ripple::LocalTx::m_seq
std::uint32_t m_seq
Definition: LocalTxs.cpp:104
ripple::base_uint< 256 >
ripple::sfLastLedgerSequence
const SF_U32 sfLastLedgerSequence(access, STI_UINT32, 27, "LastLedgerSequence")
Definition: SField.h:364
ripple::LocalTx::getTX
std::shared_ptr< STTx const > const & getTX() const
Definition: LocalTxs.cpp:88
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::LocalTxs
Definition: LocalTxs.h:33
std::uint32_t
ripple::LocalTx
Definition: LocalTxs.cpp:53
ripple::LocalTx::m_account
AccountID m_account
Definition: LocalTxs.cpp:103
ripple::LocalTx::getID
uint256 const & getID() const
Definition: LocalTxs.cpp:73
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::LocalTxsImp
Definition: LocalTxs.cpp:109
std::min
T min(T... args)
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:186
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LocalTxsImp::size
std::size_t size() override
Definition: LocalTxs.cpp:162
ripple::LocalTx::m_id
uint256 m_id
Definition: LocalTxs.cpp:102
std::mutex
STL class.
std::size_t
ripple::make_LocalTxs
std::unique_ptr< LocalTxs > make_LocalTxs()
Definition: LocalTxs.cpp:175
ripple::LocalTxsImp::getTxSet
CanonicalTXSet getTxSet() override
Definition: LocalTxs.cpp:124
std::unique_ptr
STL class.
ripple::LocalTx::m_txn
std::shared_ptr< STTx const > m_txn
Definition: LocalTxs.cpp:100
ripple::LocalTxsImp::LocalTxsImp
LocalTxsImp()=default
ripple::LocalTx::holdLedgers
static const int holdLedgers
Definition: LocalTxs.cpp:60