1#include <xrpl/tx/transactors/system/Change.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/strHex.h>
7#include <xrpl/beast/utility/Zero.h>
8#include <xrpl/beast/utility/instrumentation.h>
9#include <xrpl/core/ServiceRegistry.h>
10#include <xrpl/ledger/AmendmentTable.h>
11#include <xrpl/protocol/Feature.h>
12#include <xrpl/protocol/Indexes.h>
13#include <xrpl/protocol/Protocol.h>
14#include <xrpl/protocol/PublicKey.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STArray.h>
17#include <xrpl/protocol/STLedgerEntry.h>
18#include <xrpl/protocol/STTx.h>
19#include <xrpl/protocol/STVector256.h>
20#include <xrpl/protocol/TER.h>
21#include <xrpl/protocol/TxFlags.h>
22#include <xrpl/protocol/TxFormats.h>
23#include <xrpl/protocol/XRPAmount.h>
24#include <xrpl/server/NetworkOPs.h>
25#include <xrpl/tx/Transactor.h>
45 if (account != beast::kZero)
47 JLOG(ctx.
j.
warn()) <<
"Change: Bad source id";
53 if (!fee.native() || fee != beast::kZero)
55 JLOG(ctx.
j.
warn()) <<
"Change: invalid fee";
62 JLOG(ctx.
j.
warn()) <<
"Change: Bad signature";
68 JLOG(ctx.
j.
warn()) <<
"Change: Bad sequence";
82 JLOG(ctx.
j.
warn()) <<
"Change transaction against open ledger";
138 switch (
ctx_.tx.getTxnType())
148 UNREACHABLE(
"xrpl::Change::doApply : invalid transaction type");
157 XRPL_ASSERT(
accountID_ == beast::kZero,
"xrpl::Change::preCompute : zero account");
163 uint256 const amendment(
ctx_.tx.getFieldH256(sfAmendment));
169 if (!amendmentObject)
175 STVector256 amendments = amendmentObject->getFieldV256(sfAmendments);
180 bool const gotMajority =
ctx_.tx.isFlag(tfGotMajority);
181 bool const lostMajority =
ctx_.tx.isFlag(tfLostMajority);
183 if (gotMajority && lostMajority)
186 STArray newMajorities(sfMajorities);
189 if (amendmentObject->isFieldPresent(sfMajorities))
191 STArray const& oldMajorities = amendmentObject->getFieldArray(sfMajorities);
192 for (
auto const& majority : oldMajorities)
194 if (majority.getFieldH256(sfAmendment) == amendment)
208 if (!found && lostMajority)
215 auto& entry = newMajorities.
back();
216 entry[sfAmendment] = amendment;
219 if (!
ctx_.registry.get().getAmendmentTable().isSupported(amendment))
221 JLOG(
j_.warn()) <<
"Unsupported amendment " << amendment <<
" received a majority.";
224 else if (!lostMajority)
227 amendments.pushBack(amendment);
228 amendmentObject->setFieldV256(sfAmendments, amendments);
230 ctx_.registry.get().getAmendmentTable().enable(amendment);
232 if (!
ctx_.registry.get().getAmendmentTable().isSupported(amendment))
234 JLOG(
j_.error()) <<
"Unsupported amendment " << amendment
235 <<
" activated: server blocked.";
236 ctx_.registry.get().getOPs().setAmendmentBlocked();
240 if (newMajorities.
empty())
242 amendmentObject->makeFieldAbsent(sfMajorities);
246 amendmentObject->setFieldArray(sfMajorities, newMajorities);
267 feeObject->at(field) = tx[field];
269 if (
view().rules().enabled(featureXRPFees))
271 set(feeObject,
ctx_.tx, sfBaseFeeDrops);
272 set(feeObject,
ctx_.tx, sfReserveBaseDrops);
273 set(feeObject,
ctx_.tx, sfReserveIncrementDrops);
275 feeObject->makeFieldAbsent(sfBaseFee);
276 feeObject->makeFieldAbsent(sfReferenceFeeUnits);
277 feeObject->makeFieldAbsent(sfReserveBase);
278 feeObject->makeFieldAbsent(sfReserveIncrement);
282 set(feeObject,
ctx_.tx, sfBaseFee);
283 set(feeObject,
ctx_.tx, sfReferenceFeeUnits);
284 set(feeObject,
ctx_.tx, sfReserveBase);
285 set(feeObject,
ctx_.tx, sfReserveIncrement);
290 JLOG(
j_.warn()) <<
"Fees have been changed";
299 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, not a flag ledger, seq=" <<
view().
seq();
303 if (!
ctx_.tx.isFieldPresent(sfUNLModifyDisabling) ||
304 ctx_.tx.getFieldU8(sfUNLModifyDisabling) > 1 || !
ctx_.tx.isFieldPresent(sfLedgerSequence) ||
305 !
ctx_.tx.isFieldPresent(sfUNLModifyValidator))
307 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, wrong Tx format.";
311 bool const disabling =
ctx_.tx.getFieldU8(sfUNLModifyDisabling) != 0u;
312 auto const seq =
ctx_.tx.getFieldU32(sfLedgerSequence);
313 if (seq !=
view().seq())
315 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, wrong ledger seq=" << seq;
319 Blob const validator =
ctx_.tx.getFieldVL(sfUNLModifyValidator);
322 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, bad validator key";
326 JLOG(
j_.info()) <<
"N-UNL: applyUNLModify, " << (disabling ?
"ToDisable" :
"ToReEnable")
327 <<
" seq=" << seq <<
" validator data:" <<
strHex(validator);
337 bool const found = [&] {
338 if (negUnlObject->isFieldPresent(sfDisabledValidators))
340 auto const& negUnl = negUnlObject->getFieldArray(sfDisabledValidators);
341 for (
auto const& v : negUnl)
343 if (v.isFieldPresent(sfPublicKey) && v.getFieldVL(sfPublicKey) == validator)
353 if (negUnlObject->isFieldPresent(sfValidatorToDisable))
355 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, already has ToDisable";
360 if (negUnlObject->isFieldPresent(sfValidatorToReEnable))
362 if (negUnlObject->getFieldVL(sfValidatorToReEnable) == validator)
364 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, ToDisable is same as ToReEnable";
372 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, ToDisable already in negative UNL";
376 negUnlObject->setFieldVL(sfValidatorToDisable, validator);
381 if (negUnlObject->isFieldPresent(sfValidatorToReEnable))
383 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, already has ToReEnable";
388 if (negUnlObject->isFieldPresent(sfValidatorToDisable))
390 if (negUnlObject->getFieldVL(sfValidatorToDisable) == validator)
392 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, ToReEnable is same as ToDisable";
400 JLOG(
j_.warn()) <<
"N-UNL: applyUNLModify, ToReEnable is not in negative UNL";
404 negUnlObject->setFieldVL(sfValidatorToReEnable, validator);
A generic endpoint for log messages.
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.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
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 TER preclaim(PreclaimContext const &ctx)
void preCompute() override
virtual Rules const & rules() const =0
Returns the tx processing rules.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
virtual bool open() const =0
Returns true if this reflects an open ledger.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
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
std::uint32_t getFieldU32(SField const &field) const
bool isFieldPresent(SField const &field) const
static STObject makeInnerObject(SField const &name)
AccountID getAccountID(SField const &field) const
STAmount const & getFieldAmount(SField const &field) const
static Blob getSignature(STObject const &sigObject)
TxType getTxnType() const
Blob getSigningPubKey() const
static NotTEC invokePreflight(PreflightContext const &ctx)
AccountID const accountID_
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Keylet const & amendments() noexcept
The index of the amendment table.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
bool isFlagLedger(LedgerIndex seq)
Returns true if the given ledgerIndex is a flag ledgerIndex.
std::string strHex(FwdIt begin, FwdIt end)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
TERSubset< CanCvtToNotTEC > NotTEC
TERSubset< CanCvtToTER > TER
NotTEC preflight0(PreflightContext const &ctx, std::uint32_t flagMask)
Performs early sanity checks on the txid and flags.
std::vector< unsigned char > Blob
Storage for linear binary data.
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.
T time_since_epoch(T... args)