1#include <xrpl/tx/transactors/account/SignerListSet.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/core/ServiceRegistry.h>
7#include <xrpl/ledger/ApplyView.h>
8#include <xrpl/ledger/ReadView.h>
9#include <xrpl/ledger/helpers/AccountRootHelpers.h>
10#include <xrpl/ledger/helpers/DirectoryHelpers.h>
11#include <xrpl/ledger/helpers/SponsorHelpers.h>
12#include <xrpl/protocol/AccountID.h>
13#include <xrpl/protocol/Feature.h>
14#include <xrpl/protocol/Indexes.h>
15#include <xrpl/protocol/Keylet.h>
16#include <xrpl/protocol/LedgerFormats.h>
17#include <xrpl/protocol/SField.h>
18#include <xrpl/protocol/STArray.h>
19#include <xrpl/protocol/STLedgerEntry.h>
20#include <xrpl/protocol/STObject.h>
21#include <xrpl/protocol/STTx.h>
22#include <xrpl/protocol/TER.h>
23#include <xrpl/protocol/TxFlags.h>
24#include <xrpl/protocol/XRPAmount.h>
25#include <xrpl/tx/SignerEntries.h>
26#include <xrpl/tx/Transactor.h>
48 auto const quorum = tx[sfSignerQuorum];
53 if ((quorum != 0u) && hasSignerEntries)
63 sign = std::move(*signers);
66 else if ((quorum == 0) && !hasSignerEntries)
87 return std::get<0>(result);
92 JLOG(ctx.
j.
trace()) <<
"Malformed transaction: Invalid signer set list format.";
101 std::get<1>(result), std::get<2>(result), account, ctx.
j, ctx.
rules);
127 UNREACHABLE(
"xrpl::SignerListSet::doApply : invalid operation");
139 "xrpl::SignerListSet::preCompute : result is tesSUCCESS");
142 "xrpl::SignerListSet::preCompute : result is known operation");
146 do_ = std::get<3>(result);
171 "xrpl::signerCountBasedOwnerCountDelta : minimum signers");
174 "xrpl::signerCountBasedOwnerCountDelta : maximum signers");
175 return 2 +
static_cast<int>(entryCount);
182 Keylet const& accountKeylet,
183 Keylet const& ownerDirKeylet,
184 Keylet const& signerListKeylet,
199 if (!signers->isFlag(lsfOneOwnerCount))
201 STArray const& actualList = signers->getFieldArray(sfSignerEntries);
206 auto const hint = (*signers)[sfOwnerNode];
208 if (!view.
dirRemove(ownerDirKeylet, hint, signerListKeylet.
key,
false))
211 JLOG(j.
fatal()) <<
"Unable to delete SignerList from owner.";
217 view, view.
peek(accountKeylet), signers, removeFromOwnerCount, registry.
getJournal(
"View"));
236 registry,
view, accountKeylet, ownerDirKeylet, signerListKeylet, j);
252 JLOG(j.
trace()) <<
"Too many or too few signers in signer list.";
260 "xrpl::SignerListSet::validateQuorumAndSignerEntries : sorted "
264 JLOG(j.
trace()) <<
"Duplicate signers in signer list";
271 for (
auto const& signer : signers)
276 JLOG(j.
trace()) <<
"Every signer must have a positive weight.";
280 allSignersWeight += signer.weight;
282 if (signer.account == account)
284 JLOG(j.
trace()) <<
"A signer may not self reference account.";
290 if ((quorum <= 0) || (allSignersWeight < quorum))
292 JLOG(j.
trace()) <<
"Quorum is unreachable";
309 ctx_.registry,
view(), accountKeylet, ownerDirKeylet, signerListKeylet,
j_))
312 auto const sle =
view().
peek(accountKeylet);
316 static constexpr int kAddedOwnerCount = 1;
323 ctx_.getApplyViewContext(),
326 {.ownerCountDelta = kAddedOwnerCount},
336 auto viewJ =
ctx_.registry.get().getJournal(
"View");
342 << (page ?
"success" :
"failure");
347 signerList->setFieldU64(sfOwnerNode, *page);
366 if ((ledgerEntry->isFlag(lsfDisableMaster)) && (!ledgerEntry->isFieldPresent(sfRegularKey)))
372 ctx_.registry,
view(), accountKeylet, ownerDirKeylet, signerListKeylet,
j_);
379 if (
ctx_.view().rules().enabled(fixIncludeKeyletFields))
381 ledgerEntry->setAccountID(sfOwner,
accountID_);
383 ledgerEntry->setFieldU32(sfSignerQuorum,
quorum_);
386 ledgerEntry->setFieldU32(sfFlags, flags);
395 obj[sfAccount] = entry.account;
396 obj[sfSignerWeight] = entry.weight;
405 ledgerEntry->setFieldArray(sfSignerEntries, toLedger);
T adjacent_find(T... args)
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
const_iterator begin() const
UInt size() const
Number of values in array or object.
const_iterator end() const
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void insert(SLE::ref sle)=0
Insert a new state SLE.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
virtual void erase(SLE::ref sle)=0
Remove a peeked SLE.
virtual Rules const & rules() const =0
Returns the tx processing rules.
Rules controlling protocol behavior.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
void pushBack(STObject const &object)
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
void reserve(std::size_t n)
bool isFieldPresent(SField const &field) const
static STObject makeInnerObject(SField const &name)
AccountID getAccountID(SField const &field) const
void setFieldH256(SField const &field, uint256 const &)
static constexpr std::size_t kMinMultiSigners
static constexpr std::size_t kMaxMultiSigners
Service registry for dependency injection.
virtual beast::Journal getJournal(std::string const &name)=0
static std::expected< std::vector< SignerEntry >, NotTEC > deserialize(STObject const &obj, beast::Journal journal, std::string_view annotation)
static NotTEC preflight(PreflightContext const &ctx)
void preCompute() override
static std::tuple< NotTEC, std::uint32_t, std::vector< SignerEntries::SignerEntry >, Operation > determineOperation(STTx const &tx, ApplyFlags flags, beast::Journal j)
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
static NotTEC validateQuorumAndSignerEntries(std::uint32_t quorum, std::vector< SignerEntries::SignerEntry > const &signers, AccountID const &account, beast::Journal j, Rules const &)
std::vector< SignerEntries::SignerEntry > signers_
static TER removeFromLedger(ServiceRegistry ®istry, ApplyView &view, AccountID const &account, beast::Journal j)
void writeSignersToSLE(SLE::pointer const &ledgerEntry, std::uint32_t flags) const
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
AccountID const accountID_
virtual void preCompute()
Keylet signerList(AccountID const &account) noexcept
A SignerList.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void decreaseOwnerCountForObject(ApplyView &view, SLE::ref accountSle, SLE::ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
void increaseOwnerCount(ApplyView &view, SLE::ref accountSle, SLE::ref sponsorSle, std::uint32_t count, beast::Journal j)
Increase owner-count fields when the caller supplies the sponsor.
static std::uint32_t const kDefaultSignerListId
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
void addSponsorToLedgerEntry(SLE::ref sle, SLE::const_ref sponsorSle, SF_ACCOUNT const &field=sfSponsor)
Stamp a reserve sponsor onto a ledger entry using an explicit sponsor SLE.
TERSubset< CanCvtToNotTEC > NotTEC
static std::uint32_t signerCountBasedOwnerCountDelta(std::size_t entryCount, Rules const &rules)
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TER checkReserve(ApplyViewContext ctx, SLE::const_ref accSle, XRPAmount accBalance, SLE::const_ref sponsorSle, Adjustment adj, beast::Journal j, TER insufReserveCode=tecINSUFFICIENT_RESERVE)
Check if an account has sufficient reserve.
bool isTesSuccess(TER x) noexcept
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
TERSubset< CanCvtToTER > TER
constexpr FlagValue tfUniversalMask
static TER removeSignersFromLedger(ServiceRegistry ®istry, ApplyView &view, Keylet const &accountKeylet, Keylet const &ownerDirKeylet, Keylet const &signerListKeylet, beast::Journal j)
A pair of SHAMap key and LedgerEntryType.
State information when preflighting a tx.