rippled
SetSignerList.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/tx/impl/SetSignerList.h>
21 
22 #include <ripple/app/ledger/Ledger.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/ledger/ApplyView.h>
25 #include <ripple/protocol/Feature.h>
26 #include <ripple/protocol/Indexes.h>
27 #include <ripple/protocol/STArray.h>
28 #include <ripple/protocol/STObject.h>
29 #include <ripple/protocol/STTx.h>
30 #include <algorithm>
31 #include <cstdint>
32 
33 namespace ripple {
34 
35 // We're prepared for there to be multiple signer lists in the future,
36 // but we don't need them yet. So for the time being we're manually
37 // setting the sfSignerListID to zero in all cases.
39 
41  NotTEC,
46  STTx const& tx,
47  ApplyFlags flags,
49 {
50  // Check the quorum. A non-zero quorum means we're creating or replacing
51  // the list. A zero quorum means we're destroying the list.
52  auto const quorum = tx[sfSignerQuorum];
54  Operation op = unknown;
55 
56  bool const hasSignerEntries(tx.isFieldPresent(sfSignerEntries));
57  if (quorum && hasSignerEntries)
58  {
59  auto signers = SignerEntries::deserialize(tx, j, "transaction");
60 
61  if (signers.second != tesSUCCESS)
62  return std::make_tuple(signers.second, quorum, sign, op);
63 
64  std::sort(signers.first.begin(), signers.first.end());
65 
66  // Save deserialized list for later.
67  sign = std::move(signers.first);
68  op = set;
69  }
70  else if ((quorum == 0) && !hasSignerEntries)
71  {
72  op = destroy;
73  }
74 
75  return std::make_tuple(tesSUCCESS, quorum, sign, op);
76 }
77 
78 NotTEC
80 {
81  auto const ret = preflight1(ctx);
82  if (!isTesSuccess(ret))
83  return ret;
84 
85  auto const result = determineOperation(ctx.tx, ctx.flags, ctx.j);
86  if (std::get<0>(result) != tesSUCCESS)
87  return std::get<0>(result);
88 
89  if (std::get<3>(result) == unknown)
90  {
91  // Neither a set nor a destroy. Malformed.
92  JLOG(ctx.j.trace())
93  << "Malformed transaction: Invalid signer set list format.";
94  return temMALFORMED;
95  }
96 
97  if (std::get<3>(result) == set)
98  {
99  // Validate our settings.
100  auto const account = ctx.tx.getAccountID(sfAccount);
102  std::get<1>(result), std::get<2>(result), account, ctx.j);
103  if (ter != tesSUCCESS)
104  {
105  return ter;
106  }
107  }
108 
109  return preflight2(ctx);
110 }
111 
112 TER
114 {
115  // Perform the operation preCompute() decided on.
116  switch (do_)
117  {
118  case set:
119  return replaceSignerList();
120 
121  case destroy:
122  return destroySignerList();
123 
124  default:
125  break;
126  }
127  assert(false); // Should not be possible to get here.
128  return temMALFORMED;
129 }
130 
131 void
133 {
134  // Get the quorum and operation info.
135  auto result = determineOperation(ctx_.tx, view().flags(), j_);
136  assert(std::get<0>(result) == tesSUCCESS);
137  assert(std::get<3>(result) != unknown);
138 
139  quorum_ = std::get<1>(result);
140  signers_ = std::get<2>(result);
141  do_ = std::get<3>(result);
142 
143  return Transactor::preCompute();
144 }
145 
146 // The return type is signed so it is compatible with the 3rd argument
147 // of adjustOwnerCount() (which must be signed).
148 //
149 // NOTE: This way of computing the OwnerCount associated with a SignerList
150 // is valid until the featureMultiSignReserve amendment passes. Once it
151 // passes then just 1 OwnerCount is associated with a SignerList.
152 static int
154 {
155  // We always compute the full change in OwnerCount, taking into account:
156  // o The fact that we're adding/removing a SignerList and
157  // o Accounting for the number of entries in the list.
158  // We can get away with that because lists are not adjusted incrementally;
159  // we add or remove an entire list.
160  //
161  // The rule is:
162  // o Simply having a SignerList costs 2 OwnerCount units.
163  // o And each signer in the list costs 1 more OwnerCount unit.
164  // So, at a minimum, adding a SignerList with 1 entry costs 3 OwnerCount
165  // units. A SignerList with 8 entries would cost 10 OwnerCount units.
166  //
167  // The static_cast should always be safe since entryCount should always
168  // be in the range from 1 to 8. We've got a lot of room to grow.
169  assert(entryCount >= STTx::minMultiSigners);
170  assert(entryCount <= STTx::maxMultiSigners);
171  return 2 + static_cast<int>(entryCount);
172 }
173 
174 static TER
176  Application& app,
177  ApplyView& view,
178  Keylet const& accountKeylet,
179  Keylet const& ownerDirKeylet,
180  Keylet const& signerListKeylet)
181 {
182  // We have to examine the current SignerList so we know how much to
183  // reduce the OwnerCount.
184  SLE::pointer signers = view.peek(signerListKeylet);
185 
186  // If the signer list doesn't exist we've already succeeded in deleting it.
187  if (!signers)
188  return tesSUCCESS;
189 
190  // There are two different ways that the OwnerCount could be managed.
191  // If the lsfOneOwnerCount bit is set then remove just one owner count.
192  // Otherwise use the pre-MultiSignReserve amendment calculation.
193  int removeFromOwnerCount = -1;
194  if ((signers->getFlags() & lsfOneOwnerCount) == 0)
195  {
196  STArray const& actualList = signers->getFieldArray(sfSignerEntries);
197  removeFromOwnerCount =
198  signerCountBasedOwnerCountDelta(actualList.size()) * -1;
199  }
200 
201  // Remove the node from the account directory.
202  auto const hint = (*signers)[sfOwnerNode];
203 
204  if (!view.dirRemove(ownerDirKeylet, hint, signerListKeylet.key, false))
205  {
206  return tefBAD_LEDGER;
207  }
208 
210  view,
211  view.peek(accountKeylet),
212  removeFromOwnerCount,
213  app.journal("View"));
214 
215  view.erase(signers);
216 
217  return tesSUCCESS;
218 }
219 
220 TER
222  Application& app,
223  ApplyView& view,
224  AccountID const& account)
225 {
226  auto const accountKeylet = keylet::account(account);
227  auto const ownerDirKeylet = keylet::ownerDir(account);
228  auto const signerListKeylet = keylet::signers(account);
229 
231  app, view, accountKeylet, ownerDirKeylet, signerListKeylet);
232 }
233 
234 NotTEC
236  std::uint32_t quorum,
238  AccountID const& account,
239  beast::Journal j)
240 {
241  // Reject if there are too many or too few entries in the list.
242  {
243  std::size_t const signerCount = signers.size();
244  if ((signerCount < STTx::minMultiSigners) ||
245  (signerCount > STTx::maxMultiSigners))
246  {
247  JLOG(j.trace()) << "Too many or too few signers in signer list.";
248  return temMALFORMED;
249  }
250  }
251 
252  // Make sure there are no duplicate signers.
253  assert(std::is_sorted(signers.begin(), signers.end()));
254  if (std::adjacent_find(signers.begin(), signers.end()) != signers.end())
255  {
256  JLOG(j.trace()) << "Duplicate signers in signer list";
257  return temBAD_SIGNER;
258  }
259 
260  // Make sure no signers reference this account. Also make sure the
261  // quorum can be reached.
262  std::uint64_t allSignersWeight(0);
263  for (auto const& signer : signers)
264  {
265  std::uint32_t const weight = signer.weight;
266  if (weight <= 0)
267  {
268  JLOG(j.trace()) << "Every signer must have a positive weight.";
269  return temBAD_WEIGHT;
270  }
271 
272  allSignersWeight += signer.weight;
273 
274  if (signer.account == account)
275  {
276  JLOG(j.trace()) << "A signer may not self reference account.";
277  return temBAD_SIGNER;
278  }
279 
280  // Don't verify that the signer accounts exist. Non-existent accounts
281  // may be phantom accounts (which are permitted).
282  }
283  if ((quorum <= 0) || (allSignersWeight < quorum))
284  {
285  JLOG(j.trace()) << "Quorum is unreachable";
286  return temBAD_QUORUM;
287  }
288  return tesSUCCESS;
289 }
290 
291 TER
293 {
294  auto const accountKeylet = keylet::account(account_);
295  auto const ownerDirKeylet = keylet::ownerDir(account_);
296  auto const signerListKeylet = keylet::signers(account_);
297 
298  // This may be either a create or a replace. Preemptively remove any
299  // old signer list. May reduce the reserve, so this is done before
300  // checking the reserve.
301  if (TER const ter = removeSignersFromLedger(
302  ctx_.app, view(), accountKeylet, ownerDirKeylet, signerListKeylet))
303  return ter;
304 
305  auto const sle = view().peek(accountKeylet);
306  if (!sle)
307  return tefINTERNAL;
308 
309  // Compute new reserve. Verify the account has funds to meet the reserve.
310  std::uint32_t const oldOwnerCount{(*sle)[sfOwnerCount]};
311 
312  // The required reserve changes based on featureMultiSignReserve...
313  int addedOwnerCount{1};
316  {
317  addedOwnerCount = signerCountBasedOwnerCountDelta(signers_.size());
318  flags = 0;
319  }
320 
321  XRPAmount const newReserve{
322  view().fees().accountReserve(oldOwnerCount + addedOwnerCount)};
323 
324  // We check the reserve against the starting balance because we want to
325  // allow dipping into the reserve to pay fees. This behavior is consistent
326  // with CreateTicket.
327  if (mPriorBalance < newReserve)
329 
330  // Everything's ducky. Add the ltSIGNER_LIST to the ledger.
331  auto signerList = std::make_shared<SLE>(signerListKeylet);
332  view().insert(signerList);
333  writeSignersToSLE(signerList, flags);
334 
335  auto viewJ = ctx_.app.journal("View");
336  // Add the signer list to the account's directory.
337  auto const page = dirAdd(
338  ctx_.view(),
339  ownerDirKeylet,
340  signerListKeylet.key,
341  false,
343  viewJ);
344 
345  JLOG(j_.trace()) << "Create signer list for account " << toBase58(account_)
346  << ": " << (page ? "success" : "failure");
347 
348  if (!page)
349  return tecDIR_FULL;
350 
351  signerList->setFieldU64(sfOwnerNode, *page);
352 
353  // If we succeeded, the new entry counts against the
354  // creator's reserve.
355  adjustOwnerCount(view(), sle, addedOwnerCount, viewJ);
356  return tesSUCCESS;
357 }
358 
359 TER
361 {
362  auto const accountKeylet = keylet::account(account_);
363  // Destroying the signer list is only allowed if either the master key
364  // is enabled or there is a regular key.
365  SLE::pointer ledgerEntry = view().peek(accountKeylet);
366  if (!ledgerEntry)
367  return tefINTERNAL;
368 
369  if ((ledgerEntry->isFlag(lsfDisableMaster)) &&
370  (!ledgerEntry->isFieldPresent(sfRegularKey)))
371  return tecNO_ALTERNATIVE_KEY;
372 
373  auto const ownerDirKeylet = keylet::ownerDir(account_);
374  auto const signerListKeylet = keylet::signers(account_);
376  ctx_.app, view(), accountKeylet, ownerDirKeylet, signerListKeylet);
377 }
378 
379 void
381  SLE::pointer const& ledgerEntry,
382  std::uint32_t flags) const
383 {
384  // Assign the quorum, default SignerListID, and flags.
385  ledgerEntry->setFieldU32(sfSignerQuorum, quorum_);
386  ledgerEntry->setFieldU32(sfSignerListID, defaultSignerListID_);
387  if (flags) // Only set flags if they are non-default (default is zero).
388  ledgerEntry->setFieldU32(sfFlags, flags);
389 
390  // Create the SignerListArray one SignerEntry at a time.
391  STArray toLedger(signers_.size());
392  for (auto const& entry : signers_)
393  {
394  toLedger.emplace_back(sfSignerEntry);
395  STObject& obj = toLedger.back();
396  obj.reserve(2);
397  obj.setAccountID(sfAccount, entry.account);
398  obj.setFieldU16(sfSignerWeight, entry.weight);
399  }
400 
401  // Assign the SignerEntries.
402  ledgerEntry->setFieldArray(sfSignerEntries, toLedger);
403 }
404 
405 } // namespace ripple
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:285
ripple::Application
Definition: Application.h:97
ripple::STObject::setAccountID
void setAccountID(SField const &field, AccountID const &)
Definition: STObject.cpp:662
ripple::sfRegularKey
const SF_Account sfRegularKey(access, STI_ACCOUNT, 8, "RegularKey")
Definition: SField.h:487
ripple::preflight2
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:90
std::make_tuple
T make_tuple(T... args)
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::tefINTERNAL
@ tefINTERNAL
Definition: TER.h:149
std::shared_ptr< STLedgerEntry >
ripple::STObject::setFieldU16
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:626
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::lsfDisableMaster
@ lsfDisableMaster
Definition: LedgerFormats.h:109
ripple::describeOwnerDir
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition: View.cpp:713
ripple::Transactor::j_
const beast::Journal j_
Definition: Transactor.h:90
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:576
ripple::SetSignerList::destroySignerList
TER destroySignerList()
Definition: SetSignerList.cpp:360
ripple::ApplyView::erase
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
ripple::sfSignerQuorum
const SF_U32 sfSignerQuorum(access, STI_UINT32, 35, "SignerQuorum")
Definition: SField.h:388
std::vector
STL class.
ripple::removeSignersFromLedger
static TER removeSignersFromLedger(Application &app, ApplyView &view, Keylet const &accountKeylet, Keylet const &ownerDirKeylet, Keylet const &signerListKeylet)
Definition: SetSignerList.cpp:175
ripple::ReadView::fees
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
ripple::sfFlags
const SF_U32 sfFlags(access, STI_UINT32, 2, "Flags")
Definition: SField.h:354
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:30
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:178
std::tuple
ripple::sfOwnerNode
const SF_U64 sfOwnerNode(access, STI_UINT64, 4, "OwnerNode")
Definition: SField.h:398
ripple::SetSignerList::Operation
Operation
Definition: SetSignerList.h:45
ripple::sfSignerEntries
const SField sfSignerEntries(access, STI_ARRAY, 4, "SignerEntries")
Definition: SField.h:517
ripple::sfOwnerCount
const SF_U32 sfOwnerCount(access, STI_UINT32, 13, "OwnerCount")
Definition: SField.h:365
ripple::PreflightContext::j
const beast::Journal j
Definition: Transactor.h:39
ripple::SetSignerList::set
@ set
Definition: SetSignerList.h:45
ripple::SetSignerList::validateQuorumAndSignerEntries
static NotTEC validateQuorumAndSignerEntries(std::uint32_t quorum, std::vector< SignerEntries::SignerEntry > const &signers, AccountID const &account, beast::Journal j)
Definition: SetSignerList.cpp:235
std::sort
T sort(T... args)
algorithm
ripple::defaultSignerListID_
static const std::uint32_t defaultSignerListID_
Definition: SetSignerList.cpp:38
ripple::preflight1
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:56
ripple::ApplyView
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:140
std::is_sorted
T is_sorted(T... args)
ripple::ApplyContext::app
Application & app
Definition: ApplyContext.h:47
ripple::ApplyView::dirRemove
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
Definition: ApplyView.cpp:189
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 160, detail::AccountIDTag >
ripple::tefBAD_LEDGER
@ tefBAD_LEDGER
Definition: TER.h:146
ripple::temBAD_QUORUM
@ temBAD_QUORUM
Definition: TER.h:111
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:642
ripple::tecNO_ALTERNATIVE_KEY
@ tecNO_ALTERNATIVE_KEY
Definition: TER.h:254
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:121
ripple::STObject::getAccountID
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:562
ripple::temBAD_SIGNER
@ temBAD_SIGNER
Definition: TER.h:110
ripple::SetSignerList::do_
Operation do_
Definition: SetSignerList.h:46
ripple::sfSignerListID
const SF_U32 sfSignerListID(access, STI_UINT32, 38, "SignerListID")
Definition: SField.h:391
ripple::TERSubset
Definition: TER.h:322
ripple::STArray
Definition: STArray.h:28
ripple::SetSignerList::unknown
@ unknown
Definition: SetSignerList.h:45
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:547
ripple::lsfOneOwnerCount
@ lsfOneOwnerCount
Definition: LedgerFormats.h:131
cstdint
ripple::STTx
Definition: STTx.h:42
ripple::sfSignerEntry
const SField sfSignerEntry(access, STI_OBJECT, 11, "SignerEntry")
Definition: SField.h:508
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::Rules::enabled
bool enabled(uint256 const &id) const
Returns true if a feature is enabled.
Definition: ReadView.cpp:103
ripple::STObject::reserve
void reserve(std::size_t n)
Definition: STObject.h:315
ripple::SetSignerList::determineOperation
static std::tuple< NotTEC, std::uint32_t, std::vector< SignerEntries::SignerEntry >, Operation > determineOperation(STTx const &tx, ApplyFlags flags, beast::Journal j)
Definition: SetSignerList.cpp:45
ripple::ApplyContext::view
ApplyView & view()
Definition: ApplyContext.h:54
ripple::STArray::back
STObject & back()
Definition: STArray.h:83
ripple::signerCountBasedOwnerCountDelta
static int signerCountBasedOwnerCountDelta(std::size_t entryCount)
Definition: SetSignerList.cpp:153
ripple::tecDIR_FULL
@ tecDIR_FULL
Definition: TER.h:245
ripple::dirAdd
boost::optional< std::uint64_t > dirAdd(ApplyView &view, Keylet const &dir, uint256 const &uLedgerIndex, bool strictOrder, std::function< void(SLE::ref)> fDescriber, beast::Journal j)
Definition: View.cpp:721
ripple::SetSignerList::doApply
TER doApply() override
Definition: SetSignerList.cpp:113
ripple::STObject
Definition: STObject.h:51
ripple::sfSignerWeight
const SF_U16 sfSignerWeight(access, STI_UINT16, 3, "SignerWeight")
Definition: SField.h:348
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::PreflightContext::flags
ApplyFlags flags
Definition: Transactor.h:38
ripple::STTx::maxMultiSigners
static const std::size_t maxMultiSigners
Definition: STTx.h:52
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::SetSignerList::destroy
@ destroy
Definition: SetSignerList.h:45
ripple::SetSignerList::signers_
std::vector< SignerEntries::SignerEntry > signers_
Definition: SetSignerList.h:48
ripple::Transactor::view
ApplyView & view()
Definition: Transactor.h:107
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:124
ripple::STArray::emplace_back
void emplace_back(Args &&... args)
Definition: STArray.h:96
ripple::Fees::accountReserve
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
Definition: ReadView.h:65
ripple::ReadView::rules
virtual Rules const & rules() const =0
Returns the tx processing rules.
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:401
ripple::SetSignerList::preCompute
void preCompute() override
Definition: SetSignerList.cpp:132
ripple::Transactor::mPriorBalance
XRPAmount mPriorBalance
Definition: Transactor.h:93
std::adjacent_find
T adjacent_find(T... args)
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:265
ripple::STTx::minMultiSigners
static const std::size_t minMultiSigners
Definition: STTx.h:51
ripple::Transactor::ctx_
ApplyContext & ctx_
Definition: Transactor.h:89
ripple::Transactor::account_
AccountID account_
Definition: Transactor.h:92
ripple::SetSignerList::replaceSignerList
TER replaceSignerList()
Definition: SetSignerList.cpp:292
std::size_t
ripple::SignerEntries::deserialize
static std::pair< std::vector< SignerEntry >, NotTEC > deserialize(STObject const &obj, beast::Journal journal, std::string const &annotation)
Definition: SignerEntries.cpp:29
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:82
ripple::STArray::size
size_type size() const
Definition: STArray.h:138
ripple::PreflightContext::tx
STTx const & tx
Definition: Transactor.h:36
ripple::PreflightContext
State information when preflighting a tx.
Definition: Transactor.h:32
ripple::keylet::signers
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Definition: Indexes.cpp:250
ripple::SetSignerList::writeSignersToSLE
void writeSignersToSLE(SLE::pointer const &ledgerEntry, std::uint32_t flags) const
Definition: SetSignerList.cpp:380
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:213
ripple::Transactor::preCompute
virtual void preCompute()
Definition: Transactor.cpp:291
ripple::SetSignerList::quorum_
std::uint32_t quorum_
Definition: SetSignerList.h:47
ripple::ApplyContext::tx
STTx const & tx
Definition: ApplyContext.h:48
ripple::temBAD_WEIGHT
@ temBAD_WEIGHT
Definition: TER.h:112
ripple::SetSignerList::preflight
static NotTEC preflight(PreflightContext const &ctx)
Definition: SetSignerList.cpp:79
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::NotTEC
TERSubset< CanCvtToNotTEC > NotTEC
Definition: TER.h:507
ripple::SetSignerList::removeFromLedger
static TER removeFromLedger(Application &app, ApplyView &view, AccountID const &account)
Definition: SetSignerList.cpp:221