Amendment Architecture
← Back to Building Amendments: Lifecycle and Core Protocol Impact
Introduction
The amendment system is one of the most sophisticated architectural components of rippled. It allows the XRPL network to evolve in a decentralized manner by introducing new features and bug fixes while maintaining network consistency. Unlike traditional blockchain systems that require coordinated hard forks, XRPL uses a distributed consensus mechanism to activate protocol changes.
In this section, we will explore the internal architecture of the amendment system: the fundamental components, data structures, and integration with the consensus engine. We will see how rippled manages the list of amendments, tracks their state, and coordinates their activation across the network.
Amendment System Overview
The amendment system in XRPL is based on several key principles:
Distributed consensus: Amendments can only be activated if more than 80% of the UNL validators vote in their favor for a minimum period of two weeks. This ensures that no single entity can impose changes on the network.
Stability period: The two-week period after the 80% threshold is exceeded allows node operators to prepare for upcoming changes. This critical window provides the necessary time to update software, test integrations, and coordinate.
Automatic activation: Once consensus is reached and the stability period has elapsed, the amendment is automatically activated via an EnableAmendment pseudo-transaction injected into the ledger by the network itself.
Network protection: If a node does not support an activated amendment, it automatically enters "amendment blocked" mode and stops participating in consensus until it is updated. This protects network integrity by preventing an outdated node from applying incorrect rules.
AmendmentTable: The Central Manager
AmendmentTable Interface
The AmendmentTable class is the public interface of the amendment system. It is defined in src/xrpld/app/misc/AmendmentTable.h and provides essential methods for:
Amendment management:
find(uint256 const& amendment): Search for an amendment by its hashenable(uint256 const& amendment): Activate an amendment locallyisEnabled(uint256 const& amendment): Check if an amendment is enabledisSupported(uint256 const& amendment): Check if the node supports an amendment
Voting and validation:
doVoting(NetClock::time_point closeTime, ...): Execute voting logic for a consensus rounddoValidation(std::set<uint256> const& enabledAmendments): Determine which amendments to announce in validationsgetDesired(): Return all amendments that the node wishes to see enabled
Ledger synchronization:
doValidatedLedger(std::shared_ptr<ReadView const> const& ledger): Synchronize amendment state after ledger validationhasUnsupportedEnabled(): Check if unsupported amendments are enabledfirstUnsupportedExpected(): Return when the first unsupported amendment is expected to activate
Monitoring and inspection:
getJson(): Generate a JSON representation of all amendment statestrustChanged(hash_set<PublicKey> const& added, ...): Notify changes in the trusted validator list
AmendmentTableImpl: The Implementation
The concrete implementation AmendmentTableImpl (in src/xrpld/app/misc/detail/AmendmentTable.cpp) manages the complete internal state of the amendment system.
Key data structures:
Thread safety: All operations on amendment state are protected by a mutex. The amendment system can be queried from multiple threads simultaneously (network thread, consensus thread, RPC thread), so synchronization is critical.
AmendmentState: The State of an Amendment
Each amendment in the system is represented by an AmendmentState structure that captures its complete state:
AmendmentVote: Vote Types
The AmendmentVote type represents the local node's position:
up: The node votes to activate the amendmentdown: The node votes against the amendment (or has no opinion)obsolete: The amendment is marked as obsolete and should no longer be voted on
Enabled vs Supported
It is crucial to understand the distinction between these two states:
enabled: The amendment is activated on the network (present in the ledger in the sfAmendments field). All nodes must apply the rules of this amendment, whether they support it or not.
supported: The local node has the necessary code to apply the rules of this amendment. If a node does not support an enabled amendment, it will block (amendment blocked).
Amendment Registry: features.macro
All known amendments are defined in the macro file include/xrpl/protocol/detail/features.macro. This file uses preprocessor macros to automatically generate the necessary code.
Declaration Format
Amendment Categories
Supported Amendments: Amendments for which the node has implementation code. They are listed in features.macro with Supported::yes.
Obsolete Amendments: Historical amendments that are no longer relevant but must remain in the code in case they are activated. Marked with VoteBehavior::Obsolete.
Retired Amendments: Amendments that have been active for at least two years, whose pre-amendment code has been removed, and whose identifiers are deprecated. Marked with XRPL_RETIRE.
Registration Process
To register a new amendment in the system:
Add the entry in
features.macrowith the appropriate macro (XRPL_FEATUREorXRPL_FIX)Increment
numFeaturesininclude/xrpl/protocol/Feature.hThe amendment will be automatically included in the feature registry and available for voting
FeatureInfo: Amendment Metadata
The FeatureInfo structure encapsulates amendment metadata:
Amendment Hash Calculation
The hash of an amendment is calculated by taking the SHA-512Half of the amendment name. For example:
This hash is used as a unique identifier throughout the system: in validations, in EnableAmendment transactions, and in the ledger's sfAmendments field.
Integration with Consensus
The amendment system is tightly integrated with XRPL's consensus engine. This integration occurs at several levels:
Validation Phase
When a validator creates a validation for a ledger, it includes the list of amendments it supports and wishes to see activated. This list is generated by doValidation() and included in the validation message broadcast to the network.
Vote Collection
During each consensus round, the validations received from other validators are analyzed to extract their amendment votes. These votes are aggregated into the TrustedVotes structure which maintains:
The total number of trusted validations received
The number of votes for each specific amendment
A timeout mechanism to expire old votes
Threshold Calculation
The system calculates whether an amendment has exceeded the required threshold (more than 80% of UNL validators) using the AmendmentSet class which:
Aggregates all collected votes
Calculates the threshold based on the number of trusted validators
Determines which amendments pass the threshold
Generates the necessary actions (tfGotMajority, tfLostMajority, or activation)
Application to Ledger
Amendment decisions (got majority, lost majority, or enable) are applied to the ledger via pseudo-transactions that modify the sfMajorities and sfAmendments fields of the global ledger object.
Database Persistence
The amendment system persists critical data in the node's database.
FeatureVotes Table
The FeatureVotes table stores the local node's votes:
Fields:
Hash: The amendment hash (in hexadecimal)Name: The human-readable name of the amendmentVote: The vote value (0=down, 1=up, 2=obsolete)VoteTime: Timestamp of the vote (for history)
Persistence Operations
persistVote(): Records the current vote of an amendment in the database. This function is called when an administrator changes the vote via RPC or when the node initializes its votes at startup.
readAmendments(): Reads previously recorded votes from the database at node startup. Uses a SQL window function to retrieve only the most recent vote for each amendment.
Special Cases and Edge Cases
Low Number of Validators
If the network has very few UNL validators, the threshold calculation ensures that at least 1 vote is required. The threshold is calculated as:
This avoids situations where a single validator could activate an amendment in a test network with a single validator.
Network Partition
In case of network partition, amendments may not reach the required threshold if validators are divided. The normal consensus process handles these cases by not activating the amendment until consensus is restored.
Standalone Mode
In standalone mode (a single node without network), the node can still execute voting logic, but since there are no other validators, no amendment will ever be activated by consensus. Amendments can be manually enabled via admin commands for testing.
Source Code References
The amendment system components are distributed across multiple files:
Interface and implementation:
src/xrpld/app/misc/AmendmentTable.h- Public interfacesrc/xrpld/app/misc/detail/AmendmentTable.cpp- Complete implementation
Feature registry:
include/xrpl/protocol/detail/features.macro- Definitions of all amendmentsinclude/xrpl/protocol/Feature.h- Declarations and constantssrc/libxrpl/protocol/Feature.cpp- Code generated from macros
Persistence:
src/xrpld/app/rdb/detail/Wallet.cpp- FunctionsvoteAmendment()andreadAmendments()src/xrpld/app/rdb/Wallet.h- Declarations of persistence functions
Consensus integration:
src/xrpld/app/consensus/RCLConsensus.cpp- Integration with consensussrc/xrpld/consensus/Consensus.h- Generic consensus engine
Last updated

