mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-10 13:48:04 +00:00
Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix
This commit is contained in:
@@ -21,6 +21,10 @@ namespace beast::insight {
|
||||
* as desired (counters, events, gauges, meters, and an optional hook)
|
||||
* using the interface.
|
||||
*
|
||||
* Create them there, before the application calls onCollectionReady().
|
||||
* That call is when a collector starts polling and arms its observable
|
||||
* instruments, and it runs once.
|
||||
*
|
||||
* @see Counter, Event, Gauge, Hook, Meter
|
||||
* @see NullCollector, StatsDCollector
|
||||
*/
|
||||
@@ -140,6 +144,9 @@ public:
|
||||
|
||||
/**
|
||||
* Create a gauge with the specified name.
|
||||
*
|
||||
* Create it before onCollectionReady(); a gauge made after that is
|
||||
* never armed, so it is never exported.
|
||||
* @see Gauge
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
@@ -59,7 +59,9 @@
|
||||
* | Attrs: proposers, round_time_ms, quorum
|
||||
* | |
|
||||
* | +-- consensus.accept.apply [jtACCEPT thread, child of accept]
|
||||
* | Created: Adaptor::doAccept()
|
||||
* | Created: Adaptor::doAccept(), scoped: the txq spans doAccept
|
||||
* | goes on to create nest under it; the tx apply-stage
|
||||
* | spans are hash-derived roots and do not
|
||||
* | Attrs: ledger_seq, close_time_ripple_epoch_s, close_time_correct,
|
||||
* | close_resolution_ms, consensus_state, proposing, round_time_ms,
|
||||
* | parent_close_time_ripple_epoch_s, close_time_self_ripple_epoch_s,
|
||||
@@ -71,7 +73,7 @@
|
||||
* | Attrs: ledger_seq, proposing
|
||||
* |
|
||||
* +-- consensus.mode_change [main thread]
|
||||
* Created: Adaptor::onModeChange()
|
||||
* Created: Adaptor::onModeChange(), only when the mode moves
|
||||
* Attrs: mode_old, mode_new
|
||||
*
|
||||
* Standalone spans (no parent, created per-message in overlay):
|
||||
|
||||
@@ -347,6 +347,30 @@ isAuditorMirrorCurrent(SLE const& issuance, SLE const& mptoken);
|
||||
[[nodiscard]] bool
|
||||
areMirrorsCurrent(SLE const& issuance, SLE const& mptoken);
|
||||
|
||||
/**
|
||||
* @brief Set the holder's issuer mirror epoch to match the issuance's current issuer key epoch.
|
||||
*
|
||||
* Call this after writing the issuer mirror ciphertext under the issuance's
|
||||
* currently registered issuer key, so that the mirror reads as current afterwards.
|
||||
*
|
||||
* @param issuance The MPTokenIssuance ledger object.
|
||||
* @param mptoken The holder's MPToken ledger entry to update.
|
||||
*/
|
||||
void
|
||||
setIssuerMirrorEpoch(SLE const& issuance, SLE& mptoken);
|
||||
|
||||
/**
|
||||
* @brief Set the holder's auditor mirror epoch to match the issuance's current auditor key epoch.
|
||||
*
|
||||
* Call this after writing the auditor mirror ciphertext under the issuance's
|
||||
* currently registered auditor key. Does nothing when the holder has no auditor mirror.
|
||||
*
|
||||
* @param issuance The MPTokenIssuance ledger object.
|
||||
* @param mptoken The holder's MPToken ledger entry to update.
|
||||
*/
|
||||
void
|
||||
setAuditorMirrorEpoch(SLE const& issuance, SLE& mptoken);
|
||||
|
||||
/**
|
||||
* @brief Set the holder's MPToken mirror epochs to match the issuance's current key epochs.
|
||||
*
|
||||
|
||||
@@ -540,6 +540,11 @@ constexpr std::size_t kEcConvertBackProofLength =
|
||||
*/
|
||||
constexpr std::size_t kEcClawbackProofLength = SECP256K1_COMPACT_CLAWBACK_PROOF_SIZE;
|
||||
|
||||
/**
|
||||
* Length of compact equality proof.
|
||||
*/
|
||||
constexpr std::size_t kEcEqualityProofLength = 128;
|
||||
|
||||
/**
|
||||
* Extra base fee multiplier charged to confidential MPT transactions.
|
||||
*/
|
||||
|
||||
@@ -1134,6 +1134,19 @@ TRANSACTION(ttSPONSORSHIP_SET, 91, SponsorshipSet,
|
||||
{sfRemainingOwnerCountDelta, SoeOptional},
|
||||
}))
|
||||
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/token/ConfidentialMPTMirrorUpdate.h>
|
||||
#endif
|
||||
TRANSACTION(ttCONFIDENTIAL_MPT_MIRROR_UPDATE, 92, ConfidentialMPTMirrorUpdate,
|
||||
({.delegable = Delegation::Delegable, .amendment = featureConfidentialMPTKeyRotation}),
|
||||
({
|
||||
{sfMPTokenIssuanceID, SoeRequired},
|
||||
{sfHolder, SoeOptional},
|
||||
{sfIssuerEncryptedAmount, SoeOptional},
|
||||
{sfAuditorEncryptedAmount, SoeOptional},
|
||||
{sfZKProof, SoeRequired},
|
||||
}))
|
||||
|
||||
/** This system-generated transaction type is used to update the status of the various amendments.
|
||||
|
||||
For details, see: https://xrpl.org/amendments.html
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
// This file is auto-generated. Do not edit.
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/STParsedJSON.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/protocol_autogen/TransactionBase.h>
|
||||
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl::transactions {
|
||||
|
||||
class ConfidentialMPTMirrorUpdateBuilder;
|
||||
|
||||
/**
|
||||
* @brief Transaction: ConfidentialMPTMirrorUpdate
|
||||
*
|
||||
* Type: ttCONFIDENTIAL_MPT_MIRROR_UPDATE (92)
|
||||
* Delegable: Delegation::Delegable
|
||||
* Amendment: featureConfidentialMPTKeyRotation
|
||||
* Privileges: Privilege::NoPriv
|
||||
*
|
||||
* Immutable wrapper around STTx providing type-safe field access.
|
||||
* Use ConfidentialMPTMirrorUpdateBuilder to construct new transactions.
|
||||
*/
|
||||
class ConfidentialMPTMirrorUpdate : public TransactionBase
|
||||
{
|
||||
public:
|
||||
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_MIRROR_UPDATE;
|
||||
|
||||
/**
|
||||
* @brief Construct a ConfidentialMPTMirrorUpdate transaction wrapper from an existing STTx object.
|
||||
* @throws std::runtime_error if the transaction type doesn't match.
|
||||
*/
|
||||
explicit ConfidentialMPTMirrorUpdate(std::shared_ptr<STTx const> tx)
|
||||
: TransactionBase(std::move(tx))
|
||||
{
|
||||
// Verify transaction type
|
||||
if (tx_->getTxnType() != txType)
|
||||
{
|
||||
throw std::runtime_error("Invalid transaction type for ConfidentialMPTMirrorUpdate");
|
||||
}
|
||||
}
|
||||
|
||||
// Transaction-specific field getters
|
||||
|
||||
/**
|
||||
* @brief Get sfMPTokenIssuanceID (SoeRequired)
|
||||
* @return The field value.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
SF_UINT192::type::value_type
|
||||
getMPTokenIssuanceID() const
|
||||
{
|
||||
return this->tx_->at(sfMPTokenIssuanceID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfHolder (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
|
||||
getHolder() const
|
||||
{
|
||||
if (hasHolder())
|
||||
{
|
||||
return this->tx_->at(sfHolder);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfHolder is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasHolder() const
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfHolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfIssuerEncryptedAmount (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_VL::type::value_type>
|
||||
getIssuerEncryptedAmount() const
|
||||
{
|
||||
if (hasIssuerEncryptedAmount())
|
||||
{
|
||||
return this->tx_->at(sfIssuerEncryptedAmount);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfIssuerEncryptedAmount is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasIssuerEncryptedAmount() const
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfIssuerEncryptedAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfAuditorEncryptedAmount (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_VL::type::value_type>
|
||||
getAuditorEncryptedAmount() const
|
||||
{
|
||||
if (hasAuditorEncryptedAmount())
|
||||
{
|
||||
return this->tx_->at(sfAuditorEncryptedAmount);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfAuditorEncryptedAmount is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasAuditorEncryptedAmount() const
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfAuditorEncryptedAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfZKProof (SoeRequired)
|
||||
* @return The field value.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
SF_VL::type::value_type
|
||||
getZKProof() const
|
||||
{
|
||||
return this->tx_->at(sfZKProof);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Builder for ConfidentialMPTMirrorUpdate transactions.
|
||||
*
|
||||
* Provides a fluent interface for constructing transactions with method chaining.
|
||||
* Uses STObject internally for flexible transaction construction.
|
||||
* Inherits common field setters from TransactionBuilderBase.
|
||||
*/
|
||||
class ConfidentialMPTMirrorUpdateBuilder : public TransactionBuilderBase<ConfidentialMPTMirrorUpdateBuilder>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new ConfidentialMPTMirrorUpdateBuilder with required fields.
|
||||
* @param account The account initiating the transaction.
|
||||
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
|
||||
* @param zKProof The sfZKProof field value.
|
||||
* @param sequence Optional sequence number for the transaction.
|
||||
* @param fee Optional fee for the transaction.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder(SF_ACCOUNT::type::value_type account,
|
||||
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::decay_t<typename SF_VL::type::value_type> const& zKProof, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
|
||||
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
|
||||
)
|
||||
: TransactionBuilderBase<ConfidentialMPTMirrorUpdateBuilder>(ttCONFIDENTIAL_MPT_MIRROR_UPDATE, account, sequence, fee)
|
||||
{
|
||||
setMPTokenIssuanceID(mPTokenIssuanceID);
|
||||
setZKProof(zKProof);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a ConfidentialMPTMirrorUpdateBuilder from an existing STTx object.
|
||||
* @param tx The existing transaction to copy from.
|
||||
* @throws std::runtime_error if the transaction type doesn't match.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder(std::shared_ptr<STTx const> tx)
|
||||
{
|
||||
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_MIRROR_UPDATE)
|
||||
{
|
||||
throw std::runtime_error("Invalid transaction type for ConfidentialMPTMirrorUpdateBuilder");
|
||||
}
|
||||
object_ = *tx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transaction-specific field setters
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set sfMPTokenIssuanceID (SoeRequired)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder&
|
||||
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
|
||||
{
|
||||
object_[sfMPTokenIssuanceID] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfHolder (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder&
|
||||
setHolder(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
|
||||
{
|
||||
object_[sfHolder] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfIssuerEncryptedAmount (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder&
|
||||
setIssuerEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
|
||||
{
|
||||
object_[sfIssuerEncryptedAmount] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfAuditorEncryptedAmount (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder&
|
||||
setAuditorEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
|
||||
{
|
||||
object_[sfAuditorEncryptedAmount] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfZKProof (SoeRequired)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdateBuilder&
|
||||
setZKProof(std::decay_t<typename SF_VL::type::value_type> const& value)
|
||||
{
|
||||
object_[sfZKProof] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the ConfidentialMPTMirrorUpdate wrapper.
|
||||
* @param publicKey The public key for signing.
|
||||
* @param secretKey The secret key for signing.
|
||||
* @return The constructed transaction wrapper.
|
||||
*/
|
||||
ConfidentialMPTMirrorUpdate
|
||||
build(PublicKey const& publicKey, SecretKey const& secretKey)
|
||||
{
|
||||
sign(publicKey, secretKey);
|
||||
return ConfidentialMPTMirrorUpdate{std::make_shared<STTx>(std::move(object_))};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::transactions
|
||||
@@ -56,8 +56,7 @@
|
||||
* // Edge case -- an expensive value still needs a block guard,
|
||||
* // because arguments are evaluated even when the method is a no-op.
|
||||
* if constexpr (telemetry::kEnabled)
|
||||
* span.setAttribute(
|
||||
* pathfind_span::attr::sourceAccount, redactAccount(account));
|
||||
* span.setAttribute(tx_span::attr::txHash, to_string(txId));
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,34 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Account-address redaction for telemetry span attributes.
|
||||
* Account-address redaction helper for telemetry span attributes.
|
||||
*
|
||||
* Path-finding RPC handlers would otherwise emit the caller's raw
|
||||
* account addresses as span attributes. To keep plaintext addresses out
|
||||
* of the telemetry backend, they are hashed at the point of emission.
|
||||
* This header exposes a single pure helper that turns an address into a
|
||||
* short, stable, obfuscated token.
|
||||
* A single pure helper that turns a string into a short, stable,
|
||||
* obfuscated token, for a span attribute whose value should not be stored
|
||||
* in the clear and is hard to guess.
|
||||
*
|
||||
* Data flow:
|
||||
*
|
||||
* handler -> redactAccount(addr) -> span attribute -> OTLP export
|
||||
* Not applied to any span today. Account addresses are public ledger
|
||||
* identifiers, so the path-finding spans emit them raw (see
|
||||
* PathFindSpanNames.h) and no collector processor hashes them. Use this
|
||||
* helper only for a value that is genuinely private, and document the
|
||||
* reason at the attribute constant.
|
||||
*
|
||||
* The returned token is the first 16 hex characters (lowercase) of the
|
||||
* SHA-512Half digest of the address. It is deterministic (same address
|
||||
* always maps to the same token) so operators can still correlate spans
|
||||
* for a given account across nodes and restarts.
|
||||
* SHA-512Half digest of the input. It is deterministic (same input
|
||||
* always maps to the same token) so spans for one value still correlate
|
||||
* across nodes and restarts.
|
||||
*
|
||||
* The hash is unsalted, so it is obfuscation, not a secrecy guarantee:
|
||||
* XRP account addresses are a public, enumerable set, so a determined
|
||||
* observer with the telemetry stream could rebuild the address->token
|
||||
* mapping. The goal here is to keep plaintext addresses out of traces
|
||||
* and dashboards, not to defend against a precomputation attack. A salt
|
||||
* is intentionally omitted because it would break cross-node/restart
|
||||
* correlation, which is the reason for hashing rather than dropping.
|
||||
*
|
||||
* A second, independent hashing layer runs in the OpenTelemetry
|
||||
* Collector (an `attributes/hash` processor) as defense-in-depth for
|
||||
* any node that emits a raw value.
|
||||
* The hash is unsalted, so it is obfuscation, not a secrecy guarantee.
|
||||
* It hides a value only when that value is hard to guess: for an input
|
||||
* drawn from a small or enumerable set, such as an account address, an
|
||||
* observer can rebuild the value->token mapping by lookup, which is why
|
||||
* account addresses are emitted raw instead. A salt is intentionally
|
||||
* omitted because it would break cross-node/restart correlation, which is
|
||||
* the reason for hashing rather than dropping.
|
||||
*
|
||||
* @note This function is pure and reentrant: it holds no global state,
|
||||
* performs no I/O, and is safe to call concurrently from any thread.
|
||||
@@ -38,8 +34,7 @@
|
||||
* #include <xrpl/telemetry/Redaction.h>
|
||||
* using namespace xrpl::telemetry;
|
||||
*
|
||||
* span.setAttribute(
|
||||
* pathfind_span::attr::sourceAccount, redactAccount(src.asString()));
|
||||
* auto const token = redactAccount(value); // 16 lowercase hex chars
|
||||
* @endcode
|
||||
*
|
||||
* Edge case (empty input yields empty output):
|
||||
@@ -54,9 +49,10 @@
|
||||
namespace xrpl::telemetry {
|
||||
|
||||
/**
|
||||
* Hash an account address into a short, stable, obfuscated token.
|
||||
* Hash a value into a short, stable, obfuscated token.
|
||||
*
|
||||
* @param addr The account address to redact (e.g. an r-address).
|
||||
* @param addr The value to redact. Named for its original use on account
|
||||
* addresses; any string can be passed.
|
||||
* @return The first 16 lowercase hex characters of sha512Half(addr),
|
||||
* or an empty string when @p addr is empty.
|
||||
*/
|
||||
|
||||
@@ -574,7 +574,14 @@ public:
|
||||
setAttribute(std::string_view key, std::string_view value) noexcept;
|
||||
|
||||
/**
|
||||
* Set a string attribute (C-string overload). No-op on a null guard.
|
||||
* Set a string attribute from a C string. No-op on a null guard.
|
||||
*
|
||||
* @param key Attribute key.
|
||||
* @param value Null-terminated text. A null pointer records nothing, since
|
||||
* an empty value is already a meaningful value here.
|
||||
* @note This overload is required, not a convenience. Without it a string
|
||||
* literal binds to the bool overload, because pointer-to-bool is a standard
|
||||
* conversion and beats the std::string_view one.
|
||||
*/
|
||||
void
|
||||
setAttribute(std::string_view key, char const* value) noexcept;
|
||||
@@ -875,7 +882,14 @@ public:
|
||||
setAttribute(std::string_view key, std::string_view value) noexcept;
|
||||
|
||||
/**
|
||||
* Set a string attribute (C-string overload). No-op on a null guard.
|
||||
* Set a string attribute from a C string. No-op on a null guard.
|
||||
*
|
||||
* @param key Attribute key.
|
||||
* @param value Null-terminated text. A null pointer records nothing, since
|
||||
* an empty value is already a meaningful value here.
|
||||
* @note This overload is required, not a convenience. Without it a string
|
||||
* literal binds to the bool overload, because pointer-to-bool is a standard
|
||||
* conversion and beats the std::string_view one.
|
||||
*/
|
||||
void
|
||||
setAttribute(std::string_view key, char const* value) noexcept;
|
||||
@@ -918,6 +932,15 @@ public:
|
||||
void
|
||||
addEvent(std::string_view name) noexcept;
|
||||
|
||||
/**
|
||||
* Add a named event with key-value attributes to the span's timeline.
|
||||
* No-op on a null guard.
|
||||
* @param name Event name.
|
||||
* @param attrs Attribute pairs (all string_view for simplicity).
|
||||
*/
|
||||
void
|
||||
addEvent(std::string_view name, std::initializer_list<EventAttribute> attrs) noexcept;
|
||||
|
||||
/**
|
||||
* Record an exception as a span event and mark status as error.
|
||||
* No-op on a null guard.
|
||||
@@ -1355,6 +1378,10 @@ public:
|
||||
{
|
||||
}
|
||||
void
|
||||
addEvent(std::string_view, std::initializer_list<EventAttribute>) noexcept
|
||||
{
|
||||
}
|
||||
void
|
||||
recordException(std::exception const&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
@@ -168,6 +168,16 @@ inline constexpr auto kDefaultMetricExportInterval = std::chrono::milliseconds{1
|
||||
*/
|
||||
inline constexpr auto kDefaultMetricExportTimeout = std::chrono::milliseconds{500};
|
||||
|
||||
/**
|
||||
* Default OTLP/HTTP URL for metrics, signal path included.
|
||||
*
|
||||
* The collector's standard port on the same host. Declared here so the Setup
|
||||
* member, the config parser's default and the collector's startup log all name
|
||||
* one string. Outside the telemetry #ifdef, because the config parser reads it
|
||||
* in every build.
|
||||
*/
|
||||
inline constexpr char const* kDefaultMetricsEndpoint = "http://localhost:4318/v1/metrics";
|
||||
|
||||
/**
|
||||
* How a consensus round span picks its trace id.
|
||||
*
|
||||
@@ -316,7 +326,7 @@ public:
|
||||
* point the two signals at different collectors, or at one whose OTLP
|
||||
* paths are not the defaults.
|
||||
*/
|
||||
std::string metricsEndpoint = "http://localhost:4318/v1/metrics";
|
||||
std::string metricsEndpoint = kDefaultMetricsEndpoint;
|
||||
|
||||
/**
|
||||
* Whether to use TLS for the exporter connection.
|
||||
|
||||
172
include/xrpl/telemetry/TxAccountSpanNames.h
Normal file
172
include/xrpl/telemetry/TxAccountSpanNames.h
Normal file
@@ -0,0 +1,172 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Span attribute keys for the account-typed fields of a transaction.
|
||||
*
|
||||
* A transaction names one or more accounts: the sender in `Account`, and
|
||||
* depending on the type a `Destination`, `Owner`, `Issuer`, `Holder` and so
|
||||
* on. The tx.process span emits every one it finds as its own attribute, so
|
||||
* an account can be searched for in traces whatever role it played. An
|
||||
* account address is a public ledger identifier, so each is emitted as the
|
||||
* raw r-address and never hashed.
|
||||
*
|
||||
* One key per protocol field: `tx_` followed by the field's JSON name in
|
||||
* lower snake case. The full table is the initializer in
|
||||
* src/libxrpl/telemetry/TxAccountSpanNames.cpp; the common ones are
|
||||
*
|
||||
* STTx field span attribute key
|
||||
* ----------------- ------------------
|
||||
* Account tx_account
|
||||
* Destination tx_destination
|
||||
* Owner tx_owner
|
||||
* Issuer tx_issuer
|
||||
* RegularKey tx_regular_key
|
||||
* NFTokenMinter tx_nftoken_minter
|
||||
*
|
||||
* Only fields that some transaction format carries at top level have a key.
|
||||
* Account-typed fields that appear only in ledger entries or inner objects
|
||||
* (LowSponsor, LockingChainDoor, ...) map to nullopt. A library test walks
|
||||
* TxFormats and fails when a format gains an account field with no key.
|
||||
*
|
||||
* Why this header lives in libxrpl rather than beside TxSpanNames.h: the
|
||||
* mapping is keyed by protocol fields and its completeness is checked from
|
||||
* TxFormats, which a library test can reach and a daemon header cannot.
|
||||
*
|
||||
* Data flow:
|
||||
*
|
||||
* NetworkOPs::processTransaction (src/xrpld)
|
||||
* │ for each top-level field with getSType() == STI_ACCOUNT
|
||||
* ▼
|
||||
* accountFieldAttributeKey(field.getFName()) (this header)
|
||||
* │ the key, or nullopt for a field with no key
|
||||
* ▼
|
||||
* span->setAttribute(key, field.getText())
|
||||
*
|
||||
* @code
|
||||
* // Primary use: emit every account the transaction names. An empty
|
||||
* // account field is skipped so it is not rendered as the zero address.
|
||||
* for (auto const& field : stx)
|
||||
* {
|
||||
* if (field.getSType() != STI_ACCOUNT || field.isDefault())
|
||||
* continue;
|
||||
* if (auto const key = telemetry::accountFieldAttributeKey(field.getFName()))
|
||||
* span.setAttribute(*key, toBase58(stx.getAccountID(field.getFName())));
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @code
|
||||
* // Edge case: a field that is not a top-level transaction account has
|
||||
* // no key, so a caller must test the optional before using it.
|
||||
* accountFieldAttributeKey(sfFee); // == std::nullopt
|
||||
* accountFieldAttributeKey(sfLowSponsor); // == std::nullopt
|
||||
* @endcode
|
||||
*
|
||||
* @note Only top-level fields are covered. Accounts nested in Signers, in a
|
||||
* Batch's inner transactions, or as the issuer inside an Amount are not
|
||||
* emitted.
|
||||
* @note accountFieldAttributeKey() is thread-safe. Its table is built once
|
||||
* on first use and is read-only afterwards.
|
||||
*/
|
||||
|
||||
#include <xrpl/telemetry/SpanNames.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
class SField;
|
||||
} // namespace xrpl
|
||||
|
||||
namespace xrpl::telemetry {
|
||||
|
||||
namespace tx_account_span::attr {
|
||||
/**
|
||||
* "tx_account" — the sending account (`Account`). Every transaction has one.
|
||||
*/
|
||||
inline constexpr auto account = makeStr("tx_account");
|
||||
/**
|
||||
* "tx_destination" — the receiving account (`Destination`).
|
||||
*/
|
||||
inline constexpr auto destination = makeStr("tx_destination");
|
||||
/**
|
||||
* "tx_owner" — the owner of the object acted on (`Owner`).
|
||||
*/
|
||||
inline constexpr auto owner = makeStr("tx_owner");
|
||||
/**
|
||||
* "tx_issuer" — the issuer named by the transaction (`Issuer`).
|
||||
*/
|
||||
inline constexpr auto issuer = makeStr("tx_issuer");
|
||||
/**
|
||||
* "tx_authorize" — the account being authorised (`Authorize`).
|
||||
*/
|
||||
inline constexpr auto authorize = makeStr("tx_authorize");
|
||||
/**
|
||||
* "tx_unauthorize" — the account whose authorisation is removed (`Unauthorize`).
|
||||
*/
|
||||
inline constexpr auto unauthorize = makeStr("tx_unauthorize");
|
||||
/**
|
||||
* "tx_regular_key" — the regular key being set (`RegularKey`).
|
||||
*/
|
||||
inline constexpr auto regularKey = makeStr("tx_regular_key");
|
||||
/**
|
||||
* "tx_nftoken_minter" — the authorised NFToken minter (`NFTokenMinter`).
|
||||
*/
|
||||
inline constexpr auto nftokenMinter = makeStr("tx_nftoken_minter");
|
||||
/**
|
||||
* "tx_holder" — the token holder acted on (`Holder`).
|
||||
*/
|
||||
inline constexpr auto holder = makeStr("tx_holder");
|
||||
/**
|
||||
* "tx_delegate" — the delegate signing on the sender's behalf (`Delegate`).
|
||||
*/
|
||||
inline constexpr auto delegate = makeStr("tx_delegate");
|
||||
/**
|
||||
* "tx_sponsor" — the account paying the fee or reserve (`Sponsor`).
|
||||
*/
|
||||
inline constexpr auto sponsor = makeStr("tx_sponsor");
|
||||
/**
|
||||
* "tx_sponsee" — the account being sponsored (`Sponsee`).
|
||||
*/
|
||||
inline constexpr auto sponsee = makeStr("tx_sponsee");
|
||||
/**
|
||||
* "tx_counterparty" — the other party to a loan (`Counterparty`).
|
||||
*/
|
||||
inline constexpr auto counterparty = makeStr("tx_counterparty");
|
||||
/**
|
||||
* "tx_counterparty_sponsor" — the counterparty's sponsor (`CounterpartySponsor`).
|
||||
*/
|
||||
inline constexpr auto counterpartySponsor = makeStr("tx_counterparty_sponsor");
|
||||
/**
|
||||
* "tx_subject" — the subject of a credential (`Subject`).
|
||||
*/
|
||||
inline constexpr auto subject = makeStr("tx_subject");
|
||||
/**
|
||||
* "tx_other_chain_source" — the source account on the other chain (`OtherChainSource`).
|
||||
*/
|
||||
inline constexpr auto otherChainSource = makeStr("tx_other_chain_source");
|
||||
/**
|
||||
* "tx_other_chain_destination" — destination on the other chain (`OtherChainDestination`).
|
||||
*/
|
||||
inline constexpr auto otherChainDestination = makeStr("tx_other_chain_destination");
|
||||
/**
|
||||
* "tx_attestation_signer_account" — the attestation signer (`AttestationSignerAccount`).
|
||||
*/
|
||||
inline constexpr auto attestationSignerAccount = makeStr("tx_attestation_signer_account");
|
||||
/**
|
||||
* "tx_attestation_reward_account" — attestation reward account (`AttestationRewardAccount`).
|
||||
*/
|
||||
inline constexpr auto attestationRewardAccount = makeStr("tx_attestation_reward_account");
|
||||
} // namespace tx_account_span::attr
|
||||
|
||||
/**
|
||||
* Look up the span attribute key for an account-typed transaction field.
|
||||
*
|
||||
* @param field The protocol field, as returned by STBase::getFName().
|
||||
* @return The `tx_*` key for a top-level transaction account field, or
|
||||
* nullopt when the field is not account-typed or is carried only by ledger
|
||||
* entries and inner objects.
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::string_view>
|
||||
accountFieldAttributeKey(SField const& field);
|
||||
|
||||
} // namespace xrpl::telemetry
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Updates the encrypted mirror balances of a Confidential MPToken.
|
||||
*
|
||||
* @details
|
||||
* This transaction updates a single holder's mirrored confidential balances
|
||||
* (`sfIssuerEncryptedBalance` and/or `sfAuditorEncryptedBalance`) with the latest
|
||||
* ElGamal public keys defined on the `MPTokenIssuance`.
|
||||
*
|
||||
* It supports both issuer and holder self-migration modes, each mode supports multiple flows:
|
||||
* - Issuer mode: Submitted by the issuer.
|
||||
* 1. Issuer Key Rotation Migration: Re-encrypts the
|
||||
* holder's `sfIssuerEncryptedBalance` under the issuer's new ElGamal public key.
|
||||
*
|
||||
* 2. Auditor Key Rotation Migration: Re-encrypts the
|
||||
* holder's `sfAuditorEncryptedBalance` under the auditor's new ElGamal public key.
|
||||
*
|
||||
* 3. Simultaneous Rotation Migration: Updates both the issuer
|
||||
* and auditor encrypted balances in a single transaction to optimize network throughput.
|
||||
*
|
||||
* 4. Auditor Late-Registration Migration: When the issuer ElGamal
|
||||
* public key is already registered on the `MPTokenIssuance` object, the issuer can
|
||||
* register an auditor key at a later time through `MPTokenIssuanceSet`. Then the issuer uses this
|
||||
* flow to set the holder's initial `sfAuditorEncryptedBalance` on `MPToken` object.
|
||||
*
|
||||
* - Holder self-migration mode: Submitted by the holder. The holder decrypts their own
|
||||
* `sfConfidentialBalanceSpending` with holder's private key to recover the balance and
|
||||
* re-encrypts it under the relevant new ElGamal public key(s). This mode is always
|
||||
* available to the holder and is not conditioned on the issuer being unable to migrate
|
||||
* them: the ledger cannot verify whether an issuer has really lost its private key. That
|
||||
* loss is only the expected motivation, since an issuer that still holds its key can
|
||||
* migrate holders itself in issuer mode.
|
||||
* @note All holder migration flows strictly require the holder's
|
||||
* `sfConfidentialBalanceInbox` to be canonically zero; the holder must run
|
||||
* `ConfidentialMPTMergeInbox` first so the spending balance reflects the
|
||||
* full balance.
|
||||
*
|
||||
* 5. Holder Issuer-Mirror Migration: Re-encrypts the holder's
|
||||
* `sfIssuerEncryptedBalance` under the issuer's new ElGamal public key.
|
||||
*
|
||||
* 6. Holder Auditor-Mirror Migration: Re-encrypts the holder's
|
||||
* `sfAuditorEncryptedBalance` under the auditor's new ElGamal public key, or
|
||||
* sets it for the first time when the auditor key was late-registered. This is the
|
||||
* holder-driven counterpart to flows 2 and 4, for when the issuer does not migrate
|
||||
* the holder itself.
|
||||
*
|
||||
* 7. Simultaneous Holder Self-Migration: Updates both the issuer and auditor
|
||||
* encrypted balances in a single transaction (both keys have rotated).
|
||||
*/
|
||||
class ConfidentialMPTMirrorUpdate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
|
||||
|
||||
explicit ConfidentialMPTMirrorUpdate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
void
|
||||
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalizeInvariants(
|
||||
STTx const& tx,
|
||||
TER result,
|
||||
XRPAmount fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j) override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
Reference in New Issue
Block a user