mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Compare commits
66 Commits
bthomee/ma
...
dangell7/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d1c83b1cc | ||
|
|
38850e1180 | ||
|
|
b418b416b0 | ||
|
|
2305bc98a4 | ||
|
|
677758b1cc | ||
|
|
25d7c2c4ec | ||
|
|
0a626d95f4 | ||
|
|
6006c281e2 | ||
|
|
e79673cf40 | ||
|
|
7f41012e59 | ||
|
|
b449a6ee84 | ||
|
|
34ef577604 | ||
|
|
3a172301ce | ||
|
|
6c1a92fe93 | ||
|
|
7813683091 | ||
|
|
b814a09a08 | ||
|
|
6d369e0f02 | ||
|
|
b182430178 | ||
|
|
fe31cdc9f6 | ||
|
|
ff4520cc45 | ||
|
|
fe9c8d568f | ||
|
|
a0e09187b9 | ||
|
|
f3627fb5d5 | ||
|
|
5f638f5553 | ||
|
|
92046785d1 | ||
|
|
b90a843ddd | ||
|
|
bb529d0317 | ||
|
|
a2f1973574 | ||
|
|
847e875635 | ||
|
|
778da954b4 | ||
|
|
0586b5678e | ||
|
|
66158d786f | ||
|
|
c57ffdbcb8 | ||
|
|
4e3f953fc4 | ||
|
|
a4f8aa623f | ||
|
|
8695313565 | ||
|
|
68c9d5ca0f | ||
|
|
211054baff | ||
|
|
4fd4e93b3e | ||
|
|
4cd6cc3e01 | ||
|
|
a37c556079 | ||
|
|
5e808794d8 | ||
|
|
12c0d67ff6 | ||
|
|
00d3cee6cc | ||
|
|
96d17b7f66 | ||
|
|
ec44347ffc | ||
|
|
c9458b72ca | ||
|
|
ebcfd6645d | ||
|
|
efa57e872b | ||
|
|
33f4c92b61 | ||
|
|
2601442e16 | ||
|
|
9686604963 | ||
|
|
0efae5d16e | ||
|
|
4755bb8606 | ||
|
|
92d40de4cb | ||
|
|
b2c5927b48 | ||
|
|
7c1183547a | ||
|
|
14467fba5e | ||
|
|
fc00723836 | ||
|
|
c24a6041f7 | ||
|
|
e1d97bea12 | ||
|
|
53aa5ca903 | ||
|
|
510c0d82e9 | ||
|
|
17565d21d4 | ||
|
|
07ff532d30 | ||
|
|
2c37ef7762 |
@@ -37,7 +37,7 @@ BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
|
||||
54
.claude/CLAUDE.md
Normal file
54
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Workflow Orchestration
|
||||
|
||||
## 1. Plan Mode Default
|
||||
- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions)
|
||||
- If something goes sideways, STOP and re-plan immediately - don't keep pushing
|
||||
- Use plan mode for verification steps, not just building
|
||||
- Write detailed specs upfront to reduce ambiguity
|
||||
|
||||
## 2. Subagent Strategy
|
||||
- Use subagents liberally to keep main context window clean
|
||||
- Offload research, exploration, and parallel analysis to subagents
|
||||
- For complex problems, throw compute at it via parallelizing
|
||||
- One task per subagent for focused execution
|
||||
|
||||
## 3. Self-Improvement Loop
|
||||
- After ANY correction from the user: update `tasks/lessons.md` with the pattern
|
||||
- Write rules for yourself that prevent the same mistake
|
||||
- Ruthlessly iterate on these rules until mistake drops
|
||||
- Review lessons at session start for relevant project
|
||||
|
||||
## 4. Verification Before Done
|
||||
- Never mark a task complete without proving it works
|
||||
- Diff behavior between main and your changes when relevant
|
||||
- Ask yourself: "Would a staff engineer approve this?"
|
||||
- Run tests, check logs, demonstrate correctness
|
||||
|
||||
## 5. Demand Elegance (Balanced)
|
||||
- For non-trivial changes: pause and ask "is there a more elegant way?"
|
||||
- If a fix feels hacky: "Know now, do later, implement the elegant solution"
|
||||
- Skip this for simple, obvious fixes - don't over-engineer
|
||||
- Challenge your own first solution
|
||||
|
||||
## 6. Autonomous Bug Fixing
|
||||
- When given a bug report: just fix it. Don't ask for hand-holding
|
||||
- Point at logs, errors, failing tests - then resolve them
|
||||
- Zero context switching required from the user
|
||||
- Go fix failing CI tests without being told how
|
||||
|
||||
# Task Management
|
||||
|
||||
1. **Plan First**: Write plan to `tasks/todo.md` with checkable items
|
||||
2. **Verify Plans**: Check in before starting implementation
|
||||
3. **Track Progress**: Mark items complete as you go
|
||||
4. **Explain Changes**: High-level summary at each step
|
||||
5. **Document Results**: Add review section to `tasks/todo.md`
|
||||
6. **Capture Lessons**: Update `tasks/lessons.md` after corrections
|
||||
|
||||
# Core Principles
|
||||
|
||||
**Simplicity First**: Make every change as simple as possible. Impact minimal code.
|
||||
|
||||
**No Boilerplate**: Skip documentation. No README/docs bloat. Test only if requested.
|
||||
|
||||
**Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.
|
||||
530
.claude/skills/amendment.md
Normal file
530
.claude/skills/amendment.md
Normal file
@@ -0,0 +1,530 @@
|
||||
# XRPL Amendment Creation Skill
|
||||
|
||||
This skill guides you through creating XRPL amendments, whether for brand new features or fixes/extensions to existing functionality.
|
||||
|
||||
## Amendment Types
|
||||
|
||||
There are two main types of amendments:
|
||||
|
||||
1. **New Feature Amendment** (`feature{Name}`) - Entirely new functionality
|
||||
2. **Fix/Extension Amendment** (`fix{Name}`) - Modifications to existing functionality
|
||||
|
||||
## Step 1: Determine Amendment Type
|
||||
|
||||
Ask the user:
|
||||
- Is this a **brand new feature** (new transaction type, ledger entry, or capability)?
|
||||
- Or is this a **fix or extension** to existing functionality?
|
||||
|
||||
---
|
||||
|
||||
## For NEW FEATURE Amendments
|
||||
|
||||
### Checklist:
|
||||
|
||||
#### 1. Feature Definition in features.macro
|
||||
**ONLY FILE TO EDIT:** `include/xrpl/protocol/detail/features.macro`
|
||||
|
||||
- [ ] Add to TOP of features.macro (reverse chronological order):
|
||||
```
|
||||
XRPL_FEATURE(YourFeatureName, Supported::no, VoteBehavior::DefaultNo)
|
||||
```
|
||||
- [ ] This creates the variable `featureYourFeatureName` automatically
|
||||
- [ ] Follow naming convention: Use the feature name WITHOUT the "feature" prefix
|
||||
- [ ] Examples: `Batch` → `featureBatch`, `LendingProtocol` → `featureLendingProtocol`
|
||||
|
||||
#### 2. Support Status
|
||||
- [ ] Start with `Supported::no` during development
|
||||
- [ ] Change to `Supported::yes` when ready for network voting
|
||||
- [ ] Use `VoteBehavior::DefaultNo` (validators must explicitly vote for it)
|
||||
|
||||
#### 3. Code Implementation
|
||||
- [ ] Implement new functionality (transaction type, ledger entry, etc.)
|
||||
- [ ] Add feature gate check in preflight:
|
||||
```cpp
|
||||
if (!env.current()->rules().enabled(feature{Name}))
|
||||
{
|
||||
return temDISABLED;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Disable Route Handling
|
||||
- [ ] Ensure transaction returns `temDISABLED` when amendment is disabled
|
||||
- [ ] Implement early rejection in preflight/preclaim phase
|
||||
- [ ] Add appropriate error messages
|
||||
|
||||
#### 5. Test Implementation
|
||||
Create comprehensive test suite with this structure:
|
||||
|
||||
```cpp
|
||||
class {FeatureName}_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testEnable(FeatureBitset features)
|
||||
{
|
||||
testcase("enabled");
|
||||
|
||||
// Test with feature DISABLED
|
||||
{
|
||||
auto const amendNoFeature = features - feature{Name};
|
||||
Env env{*this, amendNoFeature};
|
||||
|
||||
env(transaction, ter(temDISABLED));
|
||||
}
|
||||
|
||||
// Test with feature ENABLED
|
||||
{
|
||||
Env env{*this, features};
|
||||
|
||||
env(transaction, ter(tesSUCCESS));
|
||||
// Validate new functionality works
|
||||
}
|
||||
}
|
||||
|
||||
void testPreflight(FeatureBitset features)
|
||||
{
|
||||
testcase("preflight");
|
||||
// Test malformed transaction validation
|
||||
}
|
||||
|
||||
void testPreclaim(FeatureBitset features)
|
||||
{
|
||||
testcase("preclaim");
|
||||
// Test signature and claim phase validation
|
||||
}
|
||||
|
||||
void testWithFeats(FeatureBitset features)
|
||||
{
|
||||
testEnable(features);
|
||||
testPreflight(features);
|
||||
testPreclaim(features);
|
||||
// Add feature-specific tests
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
auto const all = supported_amendments();
|
||||
testWithFeats(all);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 6. Test Coverage Requirements
|
||||
- [ ] Test amendment DISABLED state (returns `temDISABLED`)
|
||||
- [ ] Test amendment ENABLED state (returns `tesSUCCESS`)
|
||||
- [ ] Test malformed transactions
|
||||
- [ ] Test signature validation
|
||||
- [ ] Test edge cases specific to feature
|
||||
- [ ] Test amendment transition behavior
|
||||
|
||||
#### 7. Documentation
|
||||
- [ ] Create specification document (XLS_{NAME}.md)
|
||||
- [ ] Document new transaction types, ledger entries, or capabilities
|
||||
- [ ] Create test plan document
|
||||
- [ ] Document expected behavior when enabled/disabled
|
||||
|
||||
---
|
||||
|
||||
## For FIX/EXTENSION Amendments
|
||||
|
||||
### Checklist:
|
||||
|
||||
#### 1. Fix Definition in features.macro
|
||||
**ONLY FILE TO EDIT:** `include/xrpl/protocol/detail/features.macro`
|
||||
|
||||
- [ ] Add to TOP of features.macro (reverse chronological order):
|
||||
```
|
||||
XRPL_FIX(YourFixName, Supported::no, VoteBehavior::DefaultNo)
|
||||
```
|
||||
- [ ] This creates the variable `fixYourFixName` automatically
|
||||
- [ ] Follow naming convention: Use the fix name WITHOUT the "fix" prefix (it's added automatically)
|
||||
- [ ] Examples: `TokenEscrowV1` → `fixTokenEscrowV1`, `DirectoryLimit` → `fixDirectoryLimit`
|
||||
- [ ] Start with `Supported::no` during development, change to `Supported::yes` when ready
|
||||
|
||||
#### 2. Backward Compatibility Implementation
|
||||
**Critical**: Use enable() with if/else to preserve existing functionality
|
||||
|
||||
```cpp
|
||||
// Check if fix is enabled
|
||||
bool const fix{Name} = env.current()->rules().enabled(fix{Name});
|
||||
|
||||
// Conditional logic based on amendment state
|
||||
if (fix{Name})
|
||||
{
|
||||
// NEW behavior with fix applied
|
||||
// This is the corrected/improved logic
|
||||
}
|
||||
else
|
||||
{
|
||||
// OLD behavior (legacy path)
|
||||
// Preserve original functionality for backward compatibility
|
||||
}
|
||||
```
|
||||
|
||||
**Alternative pattern with ternary operator:**
|
||||
```cpp
|
||||
auto& viewToUse = sb.rules().enabled(fix{Name}) ? sb : legacyView;
|
||||
```
|
||||
|
||||
#### 3. Multiple Fix Versions Pattern
|
||||
For iterative fixes, use version checking:
|
||||
|
||||
```cpp
|
||||
bool const fixV1 = rv.rules().enabled(fixXahauV1);
|
||||
bool const fixV2 = rv.rules().enabled(fixXahauV2);
|
||||
|
||||
switch (transactionType)
|
||||
{
|
||||
case TYPE_1:
|
||||
if (fixV1) {
|
||||
// Behavior with V1 fix
|
||||
} else {
|
||||
// Legacy behavior
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_2:
|
||||
if (fixV2) {
|
||||
// Behavior with V2 fix
|
||||
} else if (fixV1) {
|
||||
// Behavior with only V1
|
||||
} else {
|
||||
// Legacy behavior
|
||||
}
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Test Both Paths
|
||||
Always test BOTH enabled and disabled states:
|
||||
|
||||
```cpp
|
||||
void testFix(FeatureBitset features)
|
||||
{
|
||||
testcase("fix behavior");
|
||||
|
||||
for (bool withFix : {false, true})
|
||||
{
|
||||
auto const amend = withFix ? features : features - fix{Name};
|
||||
Env env{*this, amend};
|
||||
|
||||
// Setup test scenario
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
if (!withFix)
|
||||
{
|
||||
// Test OLD behavior (before fix)
|
||||
env(operation, ter(expectedErrorWithoutFix));
|
||||
// Verify old behavior is preserved
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test NEW behavior (after fix)
|
||||
env(operation, ter(expectedErrorWithFix));
|
||||
// Verify fix works correctly
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5. Security Fix Pattern
|
||||
For security-critical fixes (like fixBatchInnerSigs):
|
||||
|
||||
```cpp
|
||||
// Test vulnerability exists WITHOUT fix
|
||||
{
|
||||
auto const amendNoFix = features - fix{Name};
|
||||
Env env{*this, amendNoFix};
|
||||
|
||||
// Demonstrate vulnerability
|
||||
// Expected: Validity::Valid (WRONG - vulnerable!)
|
||||
BEAST_EXPECT(result == Validity::Valid);
|
||||
}
|
||||
|
||||
// Test vulnerability is FIXED WITH amendment
|
||||
{
|
||||
Env env{*this, features};
|
||||
|
||||
// Demonstrate fix
|
||||
// Expected: Validity::SigBad (CORRECT - protected!)
|
||||
BEAST_EXPECT(result == Validity::SigBad);
|
||||
}
|
||||
```
|
||||
|
||||
#### 6. Test Coverage Requirements
|
||||
- [ ] Test fix DISABLED (legacy behavior preserved)
|
||||
- [ ] Test fix ENABLED (new behavior applied)
|
||||
- [ ] Test amendment transition
|
||||
- [ ] For security fixes: demonstrate vulnerability without fix
|
||||
- [ ] For security fixes: demonstrate protection with fix
|
||||
- [ ] Test edge cases that triggered the fix
|
||||
- [ ] Test combinations with other amendments
|
||||
|
||||
#### 7. Documentation
|
||||
- [ ] Document what was broken/suboptimal
|
||||
- [ ] Document the fix applied
|
||||
- [ ] Document backward compatibility behavior
|
||||
- [ ] Create test summary showing both paths
|
||||
|
||||
---
|
||||
|
||||
## Best Practices for All Amendments
|
||||
|
||||
### 1. Naming Conventions
|
||||
- New features: `feature{DescriptiveName}` (e.g., `featureBatch`, `featureHooks`)
|
||||
- Fixes: `fix{IssueDescription}` (e.g., `fixBatchInnerSigs`, `fixNSDelete`)
|
||||
- Use CamelCase without underscores
|
||||
|
||||
### 2. Feature Flag Checking
|
||||
```cpp
|
||||
// At the point where behavior diverges:
|
||||
bool const amendmentEnabled = env.current()->rules().enabled(feature{Name});
|
||||
|
||||
// Or in view/rules context:
|
||||
if (!rv.rules().enabled(feature{Name}))
|
||||
return {}; // or legacy behavior
|
||||
```
|
||||
|
||||
### 3. Error Codes
|
||||
- New features when disabled: `temDISABLED`
|
||||
- Fixes may return different validation errors based on state
|
||||
- Document all error code changes
|
||||
|
||||
### 4. Test Structure Template
|
||||
```cpp
|
||||
class Amendment_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Core tests
|
||||
void testEnable(FeatureBitset features); // Enable/disable states
|
||||
void testPreflight(FeatureBitset features); // Validation
|
||||
void testPreclaim(FeatureBitset features); // Claim phase
|
||||
|
||||
// Feature-specific tests
|
||||
void test{SpecificScenario1}(FeatureBitset features);
|
||||
void test{SpecificScenario2}(FeatureBitset features);
|
||||
|
||||
// Master orchestrator
|
||||
void testWithFeats(FeatureBitset features)
|
||||
{
|
||||
testEnable(features);
|
||||
testPreflight(features);
|
||||
testPreclaim(features);
|
||||
test{SpecificScenario1}(features);
|
||||
test{SpecificScenario2}(features);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
auto const all = supported_amendments();
|
||||
testWithFeats(all);
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Amendment, app, ripple);
|
||||
```
|
||||
|
||||
### 5. Documentation Files
|
||||
Create these files:
|
||||
- **Specification**: `XLS_{FEATURE_NAME}.md` - Technical specification
|
||||
- **Test Plan**: `{FEATURE}_COMPREHENSIVE_TEST_PLAN.md` - Test strategy
|
||||
- **Test Summary**: `{FEATURE}_TEST_IMPLEMENTATION_SUMMARY.md` - Test results
|
||||
- **Review Findings**: `{FEATURE}_REVIEW_FINDINGS.md` (if applicable)
|
||||
|
||||
### 6. Amendment Transition Testing
|
||||
Test the moment an amendment activates:
|
||||
|
||||
```cpp
|
||||
void testAmendmentTransition(FeatureBitset features)
|
||||
{
|
||||
testcase("amendment transition");
|
||||
|
||||
// Start with amendment disabled
|
||||
auto const amendNoFeature = features - feature{Name};
|
||||
Env env{*this, amendNoFeature};
|
||||
|
||||
// Perform operations in disabled state
|
||||
env(operation1, ter(temDISABLED));
|
||||
|
||||
// Enable amendment mid-test (if testing mechanism supports it)
|
||||
// Verify state transitions correctly
|
||||
|
||||
// Perform operations in enabled state
|
||||
env(operation2, ter(tesSUCCESS));
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Cache Behavior
|
||||
If amendment affects caching (like fixBatchInnerSigs):
|
||||
- [ ] Test cache behavior without fix
|
||||
- [ ] Test cache behavior with fix
|
||||
- [ ] Document cache invalidation requirements
|
||||
|
||||
### 8. Multi-Amendment Combinations
|
||||
Test interactions with other amendments:
|
||||
|
||||
```cpp
|
||||
void testMultipleAmendments(FeatureBitset features)
|
||||
{
|
||||
// Test all combinations
|
||||
for (bool withFeature1 : {false, true})
|
||||
for (bool withFeature2 : {false, true})
|
||||
{
|
||||
auto amend = features;
|
||||
if (!withFeature1) amend -= feature1;
|
||||
if (!withFeature2) amend -= feature2;
|
||||
|
||||
Env env{*this, amend};
|
||||
// Test interaction behavior
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Performance Considerations
|
||||
- [ ] Minimize runtime checks (cache `rules().enabled()` result if used multiple times)
|
||||
- [ ] Avoid nested feature checks where possible
|
||||
- [ ] Document performance impact
|
||||
|
||||
### 10. Code Review Checklist
|
||||
- [ ] Both enabled/disabled paths are tested
|
||||
- [ ] Backward compatibility is preserved (for fixes)
|
||||
- [ ] Error codes are appropriate
|
||||
- [ ] Documentation is complete
|
||||
- [ ] Security implications are considered
|
||||
- [ ] Cache behavior is correct
|
||||
- [ ] Edge cases are covered
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns Reference
|
||||
|
||||
### Pattern: New Transaction Type
|
||||
```cpp
|
||||
// In transactor code:
|
||||
TER doApply() override
|
||||
{
|
||||
if (!ctx_.view().rules().enabled(feature{Name}))
|
||||
return temDISABLED;
|
||||
|
||||
// New transaction logic here
|
||||
return tesSUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern: New Ledger Entry Type
|
||||
```cpp
|
||||
// In ledger entry creation:
|
||||
if (!view.rules().enabled(feature{Name}))
|
||||
return temDISABLED;
|
||||
|
||||
auto const sle = std::make_shared<SLE>(ltNEW_TYPE, keylet);
|
||||
view.insert(sle);
|
||||
```
|
||||
|
||||
### Pattern: Behavioral Fix
|
||||
```cpp
|
||||
// At decision point:
|
||||
bool const useFix = view.rules().enabled(fix{Name});
|
||||
|
||||
if (useFix)
|
||||
{
|
||||
// Corrected behavior
|
||||
return performCorrectValidation();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy behavior (preserved for compatibility)
|
||||
return performLegacyValidation();
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern: View Selection
|
||||
```cpp
|
||||
// Select which view to use based on amendment:
|
||||
auto& applyView = sb.rules().enabled(feature{Name}) ? newView : legacyView;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example Workflows
|
||||
|
||||
### Workflow 1: Creating a New Feature Amendment
|
||||
|
||||
1. User requests: "Add a new ClaimReward transaction type"
|
||||
2. Skill asks: "What should the amendment be called? (e.g., BalanceRewards - without 'feature' prefix)"
|
||||
3. Add to features.macro:
|
||||
```
|
||||
XRPL_FEATURE(BalanceRewards, Supported::no, VoteBehavior::DefaultNo)
|
||||
```
|
||||
4. Implement transaction with `temDISABLED` gate using `featureBalanceRewards`
|
||||
5. Create test suite with testEnable, testPreflight, testPreclaim
|
||||
6. Run tests with amendment enabled and disabled
|
||||
7. When ready, update to `Supported::yes` in features.macro
|
||||
8. Create specification document
|
||||
9. Review checklist
|
||||
|
||||
### Workflow 2: Creating a Fix Amendment
|
||||
|
||||
1. User requests: "Fix the signature validation bug in batch transactions"
|
||||
2. Skill asks: "What should the fix be called? (e.g., BatchInnerSigs - without 'fix' prefix)"
|
||||
3. Add to features.macro:
|
||||
```
|
||||
XRPL_FIX(BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)
|
||||
```
|
||||
4. Implement fix with if/else using `fixBatchInnerSigs` to preserve old behavior
|
||||
5. Create test demonstrating vulnerability without fix
|
||||
6. Create test showing fix works when enabled
|
||||
7. When ready, update to `Supported::yes` in features.macro
|
||||
8. Document both code paths
|
||||
9. Review checklist
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: File Locations
|
||||
|
||||
- **Amendment definitions (ONLY place to add)**: `include/xrpl/protocol/detail/features.macro`
|
||||
- **Feature.h (auto-generated, DO NOT EDIT)**: `include/xrpl/protocol/Feature.h`
|
||||
- **Feature.cpp (auto-generated, DO NOT EDIT)**: `src/libxrpl/protocol/Feature.cpp`
|
||||
- **Test files**: `src/test/app/` or `src/test/protocol/`
|
||||
- **Specifications**: Project root (e.g., `XLS_SMART_CONTRACTS.md`)
|
||||
- **Test plans**: Project root (e.g., `BATCH_COMPREHENSIVE_TEST_PLAN.md`)
|
||||
|
||||
## How the Macro System Works
|
||||
|
||||
The amendment system uses C preprocessor macros:
|
||||
|
||||
1. **features.macro** - Single source of truth (ONLY file you edit):
|
||||
```
|
||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX(TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
|
||||
```
|
||||
|
||||
2. **Feature.h** - Auto-generated declarations from macro:
|
||||
```cpp
|
||||
extern uint256 const featureBatch;
|
||||
extern uint256 const fixTokenEscrowV1;
|
||||
```
|
||||
|
||||
3. **Feature.cpp** - Auto-generated registrations from macro:
|
||||
```cpp
|
||||
uint256 const featureBatch = registerFeature("Batch", ...);
|
||||
uint256 const fixTokenEscrowV1 = registerFeature("fixTokenEscrowV1", ...);
|
||||
```
|
||||
|
||||
**DO NOT** modify Feature.h or Feature.cpp directly - they process features.macro automatically.
|
||||
|
||||
---
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Invoke this skill when:
|
||||
- Creating a new XRPL amendment
|
||||
- Adding a new transaction type or ledger entry
|
||||
- Fixing existing XRPL functionality
|
||||
- Need guidance on amendment best practices
|
||||
- Setting up amendment tests
|
||||
- Reviewing amendment implementation
|
||||
|
||||
The skill will guide you through the appropriate workflow based on amendment type.
|
||||
99
.claude/skills/index.md
Normal file
99
.claude/skills/index.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# xrpld Codebase Skills Index
|
||||
|
||||
## Description
|
||||
This is the top-level guide for all best-practices skills in this repository. Use this to understand the codebase organization and find the right skill for any task.
|
||||
|
||||
## When to Use Skills
|
||||
Reference a skill whenever you are:
|
||||
- **Writing new code** in a module - check the skill first for established patterns
|
||||
- **Modifying existing code** - verify your changes follow module conventions
|
||||
- **Adding a new transaction type** - see `libxrpl/tx/transactors.md` for the full template
|
||||
- **Debugging** - skills list key files and common pitfalls per module
|
||||
- **Reviewing code** - skills document what "correct" looks like for each module
|
||||
|
||||
## Codebase Architecture
|
||||
|
||||
The codebase is split into two main areas:
|
||||
|
||||
### `src/libxrpl/` — The Library (skills in `.claude/skills/libxrpl/`)
|
||||
Reusable library code: data types, serialization, cryptography, ledger state, transaction processing, and storage. This is the **protocol layer**.
|
||||
|
||||
| Module | Responsibility |
|
||||
|--------|---------------|
|
||||
| `basics` | Foundational types: Buffer, Slice, base_uint, Number, logging, error contracts |
|
||||
| `beast` | Support layer: Journal logging, test framework, instrumentation, IP types |
|
||||
| `conditions` | Crypto-conditions (RFC): fulfillment validation, DER encoding |
|
||||
| `core` | Job queue, load monitoring, hash-based message dedup |
|
||||
| `crypto` | CSPRNG, secure erasure, RFC1751 encoding |
|
||||
| `json` | Json::Value, parsing, serialization, StaticString optimization |
|
||||
| `ledger` | ReadView/ApplyView, state tables, payment sandbox, credit ops |
|
||||
| `net` | HTTP/HTTPS client, SSL certs, async I/O |
|
||||
| `nodestore` | Persistent node storage: RocksDB, NuDB, Memory backends |
|
||||
| `protocol` | STObject hierarchy, SField, Serializer, TER codes, Features, Keylets |
|
||||
| `proto` | Protocol Buffer generated headers (gRPC API definitions) |
|
||||
| `rdb` | SOCI database wrapper, checkpointing |
|
||||
| `resource` | Rate limiting, endpoint tracking, abuse prevention |
|
||||
| `server` | Port config, SSL/TLS, WebSocket, admin networks |
|
||||
| `shamap` | SHA-256 Merkle radix tree (16-way branching, COW) |
|
||||
| `tx` | Transaction pipeline: Transactor base, preflight/preclaim/doApply |
|
||||
|
||||
### `src/xrpld/` — The Server Application (skills in `.claude/skills/xrpld/`)
|
||||
The running rippled server: application lifecycle, consensus, networking, RPC, and peer management. This is the **application layer**.
|
||||
|
||||
| Module | Responsibility |
|
||||
|--------|---------------|
|
||||
| `app` | Application singleton, ledger management, consensus adapters, services |
|
||||
| `app/main` | Application initialization and lifecycle |
|
||||
| `app/ledger` | Ledger storage, retrieval, immutable state management |
|
||||
| `app/consensus` | RCL consensus adapters (bridges generic algorithm to rippled) |
|
||||
| `app/misc` | Fee voting, amendments, SHAMapStore, TxQ, validators, NetworkOPs |
|
||||
| `app/paths` | Payment path finding algorithm, trust line caching |
|
||||
| `app/rdb` | Application-level database operations |
|
||||
| `app/tx` | Application-level transaction handling |
|
||||
| `consensus` | Generic consensus algorithm (CRTP-based, app-independent) |
|
||||
| `core` | Configuration (Config.h), time keeping, network ID |
|
||||
| `overlay` | P2P networking: peer connections, protocol buffers, clustering |
|
||||
| `peerfinder` | Network discovery: bootcache, livecache, slot management |
|
||||
| `perflog` | Performance logging and instrumentation |
|
||||
| `rpc` | RPC handler dispatch, coroutine suspension, 40+ command handlers |
|
||||
| `shamap` | Application-level SHAMap operations (NodeFamily) |
|
||||
|
||||
### `include/xrpl/` — Header Files
|
||||
Headers live in `include/xrpl/` and mirror the `src/libxrpl/` structure. Each skill already references its corresponding headers in the "Key Files" section.
|
||||
|
||||
## Cross-Cutting Conventions
|
||||
|
||||
### Error Handling
|
||||
- **Transaction errors**: Return `TER` enum (tesSUCCESS, tecFROZEN, temBAD_AMOUNT, etc.)
|
||||
- **Logic errors**: `Throw<std::runtime_error>()`, `LogicError()`, `XRPL_ASSERT()`
|
||||
- **I/O errors**: `Status` enum or `boost::system::error_code`
|
||||
- **RPC errors**: Inject via `context.params`
|
||||
|
||||
### Assertions
|
||||
```cpp
|
||||
XRPL_ASSERT(condition, "ClassName::method : description"); // Debug only
|
||||
XRPL_VERIFY(condition, "ClassName::method : description"); // Always enabled
|
||||
```
|
||||
|
||||
### Logging
|
||||
```cpp
|
||||
JLOG(j_.warn()) << "Message"; // Always wrap in JLOG macro
|
||||
```
|
||||
|
||||
### Memory Management
|
||||
- `IntrusiveRefCounts` + `SharedIntrusive` for shared ownership in libxrpl
|
||||
- `std::shared_ptr` for shared ownership in xrpld
|
||||
- `std::unique_ptr` for exclusive ownership
|
||||
- `CountedObject<T>` mixin for instance tracking
|
||||
|
||||
### Feature Gating
|
||||
```cpp
|
||||
if (ctx.rules.enabled(featureMyFeature)) { /* new behavior */ }
|
||||
```
|
||||
|
||||
### Code Organization
|
||||
- Headers in `include/xrpl/`, implementations in `src/libxrpl/` or `src/xrpld/`
|
||||
- `#pragma once` (never `#ifndef` guards)
|
||||
- `namespace xrpl { }` for all code
|
||||
- `detail/` namespace for internal helpers
|
||||
- Factory functions: `make_*()` returning `unique_ptr` or `shared_ptr`
|
||||
79
.claude/skills/libxrpl/basics.md
Normal file
79
.claude/skills/libxrpl/basics.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Basics Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with foundational utilities in `src/libxrpl/basics/` or `include/xrpl/basics/`. Covers data structures, memory management, logging, numeric operations, error handling, and string utilities.
|
||||
|
||||
## Responsibility
|
||||
Provides fundamental building blocks for the entire codebase: memory types (Buffer, Slice, Blob), intrusive smart pointers, arbitrary-precision integers (base_uint), multi-precision decimal arithmetic (Number), logging infrastructure, exception handling contracts, and platform abstractions.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Memory Types
|
||||
- **Slice** - Non-owning view into contiguous bytes (like std::span)
|
||||
- **Buffer** - Owning byte container (like std::vector<uint8_t>)
|
||||
- **Blob** - Alias for std::vector<unsigned char>
|
||||
- Prefer `Slice` for read-only parameters, `Buffer` for owned data
|
||||
|
||||
### Intrusive Smart Pointers
|
||||
```cpp
|
||||
// Prefer intrusive pointers over std::shared_ptr for minimal overhead
|
||||
// Object embeds its own reference count
|
||||
class MyObject : public IntrusiveRefCounts {
|
||||
// ...
|
||||
};
|
||||
// Use SharedIntrusive<MyObject> when weak pointers needed
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
```cpp
|
||||
// Contract-based exceptions (logs call stack then throws)
|
||||
Throw<std::runtime_error>("Invalid source file");
|
||||
LogThrow("exception message");
|
||||
|
||||
// Logic errors for invariant violations
|
||||
LogicError("This should never happen");
|
||||
|
||||
// Assertions (fuzzing-aware)
|
||||
XRPL_ASSERT(condition, "function_name : description");
|
||||
XRPL_VERIFY(condition, "message"); // Always enabled, not just debug
|
||||
```
|
||||
|
||||
### Logging
|
||||
```cpp
|
||||
// Use JLOG macro - short-circuits if level disabled
|
||||
JLOG(debugLog().warn()) << "Message: " << value;
|
||||
JLOG(j_.trace()) << "Verbose detail";
|
||||
// Never: debugLog().warn() << "msg"; // Missing JLOG wastes formatting
|
||||
```
|
||||
|
||||
### Number Precision
|
||||
```cpp
|
||||
// Use Number for multi-precision decimal arithmetic
|
||||
// Always use RAII guard for rounding mode
|
||||
NumberRoundModeGuard mg(Number::towards_zero);
|
||||
auto result = amount * rate;
|
||||
// Guard restores previous mode on scope exit
|
||||
```
|
||||
|
||||
### base_uint Template
|
||||
```cpp
|
||||
// Typed big-endian integers: base_uint<Bits, Tag>
|
||||
// Tag prevents mixing unrelated types of same width
|
||||
using uint256 = base_uint<256, void>;
|
||||
using AccountID = base_uint<160, detail::AccountIDTag>;
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use `std::shared_ptr` when IntrusiveRefCounts is available - it adds a separate allocation
|
||||
- Never format log messages without JLOG wrapper - wastes CPU when level is disabled
|
||||
- Never use raw `assert()` - use `XRPL_ASSERT` for fuzzing instrumentation support
|
||||
- Never mix `Buffer` and `Slice` ownership semantics - Slice does NOT own its data
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/basics/IntrusiveRefCounts.h` - Atomic reference counting
|
||||
- `include/xrpl/basics/IntrusivePointer.h` - Smart pointer using intrusive refs
|
||||
- `include/xrpl/basics/base_uint.h` - Arbitrary-length big-endian integers
|
||||
- `include/xrpl/basics/Buffer.h`, `Blob.h`, `Slice.h` - Memory types
|
||||
- `include/xrpl/basics/Number.h` - Multi-precision decimal arithmetic
|
||||
- `include/xrpl/basics/Log.h` - Logging infrastructure
|
||||
- `include/xrpl/basics/contract.h` - Throw, LogicError, XRPL_ASSERT
|
||||
62
.claude/skills/libxrpl/beast.md
Normal file
62
.claude/skills/libxrpl/beast.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Beast Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with the Beast support layer in `src/libxrpl/beast/` or `include/xrpl/beast/`. Covers networking types, unit testing, Journal logging, and instrumentation.
|
||||
|
||||
## Responsibility
|
||||
Library support layer providing network types (IP addresses, endpoints), unit testing framework, Journal/logging abstractions, instrumentation/assertion macros, and type introspection utilities.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Journal Logging
|
||||
```cpp
|
||||
// Journal wraps a Sink pointer - copy by value is cheap
|
||||
beast::Journal const j_;
|
||||
|
||||
// Severity levels: kTrace, kDebug, kInfo, kWarning, kError, kFatal
|
||||
JLOG(j_.warn()) << "User-facing issue";
|
||||
JLOG(j_.debug()) << "Implementation detail";
|
||||
JLOG(j_.trace()) << "Very verbose diagnostic";
|
||||
JLOG(j_.error()) << "Unexpected failure";
|
||||
```
|
||||
|
||||
### Unit Testing
|
||||
```cpp
|
||||
class MyTest : public beast::unit_test::suite {
|
||||
void run() override {
|
||||
testcase("feature description");
|
||||
BEAST_EXPECT(value == expected); // Non-fatal assertion
|
||||
BEAST_REQUIRE(value == expected); // Fatal - aborts test on failure
|
||||
}
|
||||
};
|
||||
BEAST_DEFINE_TESTSUITE(MyTest, module, ripple);
|
||||
```
|
||||
|
||||
### Instrumentation
|
||||
```cpp
|
||||
// Use XRPL_ASSERT for debug-only assertions (fuzzing-aware)
|
||||
XRPL_ASSERT(ptr != nullptr, "MyClass::method : null pointer");
|
||||
|
||||
// Format: "ClassName::methodName : description"
|
||||
// The string format is important for fuzzing instrumentation
|
||||
```
|
||||
|
||||
### IP Endpoint Types
|
||||
```cpp
|
||||
// Use beast::IP::Endpoint for network addresses
|
||||
beast::IP::Endpoint endpoint;
|
||||
// Supports both IPv4 and IPv6
|
||||
// Includes port information
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use `BEAST_EXPECT` when the test cannot continue on failure - use `BEAST_REQUIRE` instead
|
||||
- Never create a Journal with a dangling Sink pointer - ensure Sink outlives Journal
|
||||
- Always include "ClassName::methodName" prefix in XRPL_ASSERT messages for traceability
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/utility/Journal.h` - Log sink abstraction
|
||||
- `include/xrpl/beast/unit_test/suite.h` - Test framework
|
||||
- `include/xrpl/beast/utility/instrumentation.h` - XRPL_ASSERT macros
|
||||
- `include/xrpl/beast/net/IPEndpoint.h` - Network endpoint types
|
||||
- `include/xrpl/beast/core/SemanticVersion.h` - Version parsing
|
||||
33
.claude/skills/libxrpl/beast/clock.md
Normal file
33
.claude/skills/libxrpl/beast/clock.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Beast Clock Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with clock abstractions in `src/libxrpl/beast/clock/` or `include/xrpl/beast/clock/`. Covers abstract clock interfaces and manual clock implementations for testing.
|
||||
|
||||
## Responsibility
|
||||
Provides clock abstractions that decouple code from system time, enabling deterministic testing with manual clocks and supporting different time granularities.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Abstract Clock Interface
|
||||
```cpp
|
||||
// Use abstract_clock<T> for testable time-dependent code
|
||||
// Production: uses system clock
|
||||
// Testing: uses manual_clock for deterministic control
|
||||
```
|
||||
|
||||
### Manual Clock for Testing
|
||||
```cpp
|
||||
// Advance time manually in tests
|
||||
manual_clock<std::chrono::steady_clock> clock;
|
||||
clock.advance(std::chrono::seconds(30));
|
||||
// Deterministic - no flaky tests from timing issues
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use `std::chrono::system_clock::now()` directly - inject clock dependency
|
||||
- Always use manual_clock in unit tests for deterministic behavior
|
||||
- Be aware of Ripple Epoch vs Unix Epoch when working with ledger timestamps
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/clock/abstract_clock.h` - Abstract clock interface
|
||||
- `include/xrpl/beast/clock/manual_clock.h` - Testable clock implementation
|
||||
29
.claude/skills/libxrpl/beast/core.md
Normal file
29
.claude/skills/libxrpl/beast/core.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Beast Core Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with core beast utilities in `src/libxrpl/beast/core/` or `include/xrpl/beast/core/`. Covers semantic versioning and core type utilities.
|
||||
|
||||
## Responsibility
|
||||
Provides core utilities including semantic version parsing/comparison, system abstractions, and foundational type support.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Semantic Version Parsing
|
||||
```cpp
|
||||
// Parse version strings following semver spec
|
||||
SemanticVersion version;
|
||||
if (version.parse("1.2.3-beta")) {
|
||||
auto major = version.majorVersion;
|
||||
auto minor = version.minorVersion;
|
||||
auto patch = version.patchVersion;
|
||||
}
|
||||
// Supports comparison operators for version ordering
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always validate version strings before using - parse() returns false on invalid input
|
||||
- Remember that pre-release versions have lower precedence than release versions
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/core/SemanticVersion.h` - Version parsing and comparison
|
||||
- `src/libxrpl/beast/core/SemanticVersion.cpp` - Implementation
|
||||
41
.claude/skills/libxrpl/beast/insight.md
Normal file
41
.claude/skills/libxrpl/beast/insight.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Beast Insight Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with metrics and monitoring in `src/libxrpl/beast/insight/` or `include/xrpl/beast/insight/`. Covers counters, gauges, and metrics collection.
|
||||
|
||||
## Responsibility
|
||||
Provides metrics collection infrastructure for monitoring application performance: counters for cumulative values, gauges for point-in-time measurements, and hooks for metrics export.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Metrics Types
|
||||
```cpp
|
||||
// Counter: Monotonically increasing value (e.g., total requests)
|
||||
insight::Counter requests;
|
||||
++requests;
|
||||
|
||||
// Gauge: Point-in-time value (e.g., current connections)
|
||||
insight::Gauge connections;
|
||||
connections = currentCount;
|
||||
|
||||
// Event: Timed operation tracking
|
||||
insight::Event latency;
|
||||
```
|
||||
|
||||
### Null Metrics
|
||||
```cpp
|
||||
// Use NullCollector when metrics disabled
|
||||
// All operations become no-ops with zero overhead
|
||||
auto collector = insight::NullCollector::New();
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Use Counter for cumulative values, Gauge for current state - don't mix them
|
||||
- Always use NullCollector for tests - avoids metrics overhead
|
||||
- Never store raw metric values in long-lived objects - use the insight types
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/insight/Counter.h` - Cumulative counter
|
||||
- `include/xrpl/beast/insight/Gauge.h` - Point-in-time gauge
|
||||
- `include/xrpl/beast/insight/Collector.h` - Metrics collector interface
|
||||
- `include/xrpl/beast/insight/NullCollector.h` - No-op collector
|
||||
46
.claude/skills/libxrpl/beast/net.md
Normal file
46
.claude/skills/libxrpl/beast/net.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Beast Net Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with network types in `src/libxrpl/beast/net/` or `include/xrpl/beast/net/`. Covers IP address and endpoint representations.
|
||||
|
||||
## Responsibility
|
||||
Provides network type abstractions for IP addresses (v4 and v6) and endpoints (address + port), with parsing utilities and comparison operators.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### IP Endpoint Usage
|
||||
```cpp
|
||||
// beast::IP::Endpoint combines address + port
|
||||
beast::IP::Endpoint endpoint(
|
||||
beast::IP::Address::from_string("127.0.0.1"), 51235);
|
||||
|
||||
// Supports both IPv4 and IPv6
|
||||
beast::IP::Endpoint v6endpoint(
|
||||
beast::IP::Address::from_string("::1"), 51235);
|
||||
```
|
||||
|
||||
### Address Parsing
|
||||
```cpp
|
||||
// Parse from string with error handling
|
||||
boost::system::error_code ec;
|
||||
auto address = beast::IP::Address::from_string(input, ec);
|
||||
if (ec) { /* handle invalid address */ }
|
||||
```
|
||||
|
||||
### Comparison and Ordering
|
||||
```cpp
|
||||
// Endpoints support full comparison for use in containers
|
||||
std::set<beast::IP::Endpoint> endpoints;
|
||||
std::map<beast::IP::Endpoint, Consumer> consumers;
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always handle both IPv4 and IPv6 when working with endpoints
|
||||
- Use error_code overload of from_string to handle invalid input gracefully
|
||||
- Never assume address format - always parse and validate
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/net/IPEndpoint.h` - Combined address + port
|
||||
- `include/xrpl/beast/net/IPAddress.h` - IP address types
|
||||
- `include/xrpl/beast/net/IPAddressV4.h` - IPv4 specific
|
||||
- `include/xrpl/beast/net/IPAddressV6.h` - IPv6 specific
|
||||
47
.claude/skills/libxrpl/beast/utility.md
Normal file
47
.claude/skills/libxrpl/beast/utility.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Beast Utility Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with beast utility classes in `src/libxrpl/beast/utility/` or `include/xrpl/beast/utility/`. Covers Journal logging, instrumentation, and type introspection.
|
||||
|
||||
## Responsibility
|
||||
Provides utility classes including the Journal logging abstraction (Sink + Stream), XRPL_ASSERT/XRPL_VERIFY instrumentation macros, and type introspection helpers.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Journal and Sink Architecture
|
||||
```cpp
|
||||
// Sink: abstract base for log message routing
|
||||
class Sink {
|
||||
virtual void write(beast::severities::Severity level, std::string const& text) = 0;
|
||||
void console(bool output); // Enable console output
|
||||
};
|
||||
|
||||
// Journal: lightweight wrapper around Sink* (copy by value)
|
||||
beast::Journal j(sinkPtr);
|
||||
JLOG(j.warn()) << "Message";
|
||||
|
||||
// WrappedSink: adds prefix to all messages
|
||||
beast::WrappedSink wrappedSink(parentSink, "MyModule");
|
||||
```
|
||||
|
||||
### Instrumentation Macros
|
||||
```cpp
|
||||
// XRPL_ASSERT: Debug-only assertion (disabled in release, fuzzing-aware)
|
||||
XRPL_ASSERT(condition, "ClassName::method : description");
|
||||
|
||||
// XRPL_VERIFY: Always-enabled assertion
|
||||
XRPL_VERIFY(condition, "ClassName::method : description");
|
||||
|
||||
// Format convention: "ClassName::methodName : human-readable description"
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always use "ClassName::methodName" prefix in assertion messages
|
||||
- Journal is cheap to copy (just a pointer) - pass by value is fine
|
||||
- WrappedSink must outlive any Journal created from it
|
||||
- XRPL_ASSERT is no-op in release builds - don't put side effects in the condition
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/beast/utility/Journal.h` - Log sink abstraction and Journal
|
||||
- `include/xrpl/beast/utility/instrumentation.h` - XRPL_ASSERT, XRPL_VERIFY
|
||||
- `include/xrpl/beast/utility/WrappedSink.h` - Prefixed log sink
|
||||
63
.claude/skills/libxrpl/conditions.md
Normal file
63
.claude/skills/libxrpl/conditions.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Conditions Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with crypto-conditions in `src/libxrpl/conditions/` or `include/xrpl/conditions/`. Implements the RFC crypto-conditions specification.
|
||||
|
||||
## Responsibility
|
||||
Implements crypto-conditions for conditional payments: condition fingerprints, fulfillment validation, multiple condition types (preimage, prefix, threshold, RSA, Ed25519), and binary DER serialization/deserialization.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Fulfillment Interface
|
||||
```cpp
|
||||
// Abstract base for all fulfillment types
|
||||
struct Fulfillment {
|
||||
virtual ~Fulfillment() = default;
|
||||
virtual Buffer fingerprint() const = 0;
|
||||
virtual Type type() const = 0;
|
||||
virtual bool validate(Slice data) const = 0;
|
||||
virtual std::uint32_t cost() const = 0;
|
||||
virtual Condition condition() const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
### Factory Pattern for Deserialization
|
||||
```cpp
|
||||
// Returns unique_ptr + sets error_code (non-throwing)
|
||||
std::unique_ptr<Fulfillment> deserialize(Slice s, std::error_code& ec);
|
||||
|
||||
// Usage:
|
||||
std::error_code ec;
|
||||
auto fulfillment = Fulfillment::deserialize(data, ec);
|
||||
if (ec) return {}; // Early return on error
|
||||
```
|
||||
|
||||
### Type-Safe Enums
|
||||
```cpp
|
||||
enum class Type : std::uint8_t {
|
||||
preimageSha256 = 0,
|
||||
prefixSha256 = 1,
|
||||
thresholdSha256 = 2,
|
||||
rsaSha256 = 3,
|
||||
ed25519Sha256 = 4
|
||||
};
|
||||
```
|
||||
|
||||
### Size Limits
|
||||
```cpp
|
||||
static constexpr std::size_t maxSerializedCondition = 128;
|
||||
static constexpr std::size_t maxSerializedFulfillment = 256;
|
||||
// Always respect these limits when creating conditions
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never throw exceptions from binary parsing - use `std::error_code` parameter pattern
|
||||
- Always check `ec` after deserialization before using the result
|
||||
- Respect `maxSerializedFulfillment` size limits
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/conditions/Condition.h` - Base condition with type/fingerprint/cost
|
||||
- `include/xrpl/conditions/Fulfillment.h` - Abstract fulfillment interface
|
||||
- `include/xrpl/conditions/detail/PreimageSha256.h` - Preimage implementation
|
||||
- `include/xrpl/conditions/detail/utils.h` - DER encoding/decoding
|
||||
- `include/xrpl/conditions/detail/error.h` - Error codes
|
||||
61
.claude/skills/libxrpl/core.md
Normal file
61
.claude/skills/libxrpl/core.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Core Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with job processing and routing infrastructure in `src/libxrpl/core/` or `include/xrpl/core/`. Covers job queues, load monitoring, and message deduplication.
|
||||
|
||||
## Responsibility
|
||||
Distributed job processing with priority levels, load monitoring for execution tracking, and hash-based message suppression/routing for peer deduplication.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Job Queue Priorities
|
||||
```cpp
|
||||
// Job types ordered by priority (lower enum = lower priority)
|
||||
enum JobType {
|
||||
jtINVALID = -1,
|
||||
jtPACK, // Lowest priority
|
||||
jtCLIENT_WEBSOCKET,
|
||||
// ...
|
||||
jtVALIDATION_t, // Trusted validation (high)
|
||||
jtADMIN // Admin operations (highest)
|
||||
};
|
||||
// Position in enum determines scheduling priority
|
||||
```
|
||||
|
||||
### HashRouter for Deduplication
|
||||
```cpp
|
||||
// Suppress duplicate messages from peers
|
||||
std::optional<std::set<PeerShortID>> shouldRelay(uint256 const& key);
|
||||
// Returns {} if already relayed, set of peers if should relay
|
||||
|
||||
// Track peer that sent a message
|
||||
auto result = router.addSuppressionPeer(key, peer);
|
||||
```
|
||||
|
||||
### RAII Locking
|
||||
```cpp
|
||||
// Always use lock_guard for mutex protection
|
||||
std::lock_guard lock(mutex_);
|
||||
auto result = emplace(key);
|
||||
result.first.addPeer(peer);
|
||||
return result.second; // Return while lock is held
|
||||
```
|
||||
|
||||
### Optional Return Types
|
||||
```cpp
|
||||
// Use std::optional for "maybe" results
|
||||
std::optional<std::set<PeerShortID>> shouldRelay(uint256 const& key);
|
||||
// Caller checks: if (auto peers = shouldRelay(key)) { ... }
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never hold locks longer than necessary - lock_guard scope = critical section
|
||||
- Never ignore job priorities when scheduling work - use appropriate JobType
|
||||
- Always let HashRouter handle message deduplication rather than implementing custom logic
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/core/Job.h` - Job wrapper with type, index, function
|
||||
- `include/xrpl/core/JobTypes.h` - Job type enumerations and metadata
|
||||
- `include/xrpl/core/JobQueue.h` - Priority queue for dispatching jobs
|
||||
- `include/xrpl/core/HashRouter.h` - Duplicate message suppression
|
||||
- `include/xrpl/core/LoadMonitor.h` - Job execution time tracking
|
||||
32
.claude/skills/libxrpl/core/detail.md
Normal file
32
.claude/skills/libxrpl/core/detail.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Core Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with internal core implementation details in `src/libxrpl/core/detail/`. These are private implementation helpers not intended for direct external use.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for the core module, including helper functions and private data structures used by JobQueue, HashRouter, and LoadMonitor.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Detail Namespace Convention
|
||||
```cpp
|
||||
namespace xrpl {
|
||||
namespace detail {
|
||||
// Internal helpers - not part of public API
|
||||
// May change without notice between versions
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Encapsulation
|
||||
- Code in `detail/` should only be included by its parent module
|
||||
- Never include detail headers from outside the core module
|
||||
- If you need functionality from detail, use the public core API instead
|
||||
|
||||
## Common Pitfalls
|
||||
- Never depend on detail namespace types or functions from outside the core module
|
||||
- Detail implementations may change without preserving API compatibility
|
||||
- Always use the public `core/` headers for stable interfaces
|
||||
|
||||
## Key Files
|
||||
- Files in this directory are implementation details of `include/xrpl/core/` headers
|
||||
51
.claude/skills/libxrpl/crypto.md
Normal file
51
.claude/skills/libxrpl/crypto.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Crypto Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with cryptographic operations in `src/libxrpl/crypto/` or `include/xrpl/crypto/`. Covers CSPRNG, secure memory erasure, and RFC1751 encoding.
|
||||
|
||||
## Responsibility
|
||||
Low-level cryptographic operations: cryptographically secure random number generation (CSPRNG), RFC1751 word-based encoding for keys, and secure memory erasure to prevent sensitive data leakage.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### CSPRNG Usage
|
||||
```cpp
|
||||
// Thread-safe PRNG - use the global singleton
|
||||
auto& prng = crypto_prng();
|
||||
|
||||
// Generate random value
|
||||
auto randomValue = prng();
|
||||
|
||||
// Fill buffer with random bytes
|
||||
prng(buffer.data(), buffer.size());
|
||||
|
||||
// NEVER create your own csprng_engine - use crypto_prng()
|
||||
```
|
||||
|
||||
### Secure Memory Erasure
|
||||
```cpp
|
||||
// Use volatile memset to prevent compiler optimization
|
||||
secure_erase(secretKey.data(), secretKey.size());
|
||||
// MUST be called before destroying any buffer containing secrets
|
||||
```
|
||||
|
||||
### Engine Concept Conformance
|
||||
```cpp
|
||||
// csprng_engine meets UniformRandomNumberEngine requirements
|
||||
using result_type = std::uint64_t;
|
||||
static constexpr result_type min();
|
||||
static constexpr result_type max();
|
||||
// Can be used with standard distributions
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never create a local `csprng_engine` instance - always use `crypto_prng()` singleton
|
||||
- Never use `std::rand()` or `std::mt19937` for security-sensitive operations
|
||||
- Always call `secure_erase()` on secret key material before destruction
|
||||
- Never copy or move a `csprng_engine` - it's non-copyable and non-movable by design
|
||||
- Be aware of OpenSSL version differences - locking behavior varies
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/crypto/csprng.h` - Thread-safe PRNG engine
|
||||
- `include/xrpl/crypto/RFC1751.h` - Human-readable key encoding
|
||||
- `include/xrpl/crypto/secure_erase.h` - Volatile memset for secrets
|
||||
68
.claude/skills/libxrpl/json.md
Normal file
68
.claude/skills/libxrpl/json.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# JSON Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with JSON parsing and serialization in `src/libxrpl/json/` or `include/xrpl/json/`. Covers Json::Value, readers, writers, and custom allocators.
|
||||
|
||||
## Responsibility
|
||||
JSON value representation (discriminated union for all JSON types), parsing text to Value objects, serialization from Value to text, and custom string allocation for memory control.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Json::Value Usage
|
||||
```cpp
|
||||
// Discriminated union - supports all JSON types
|
||||
Json::Value obj(Json::objectValue);
|
||||
obj["key"] = "string_value";
|
||||
obj["count"] = 42u;
|
||||
obj["flag"] = true;
|
||||
obj["nested"] = Json::objectValue;
|
||||
|
||||
// Array creation
|
||||
Json::Value arr(Json::arrayValue);
|
||||
arr.append("item");
|
||||
arr.append(123);
|
||||
|
||||
// Type checking
|
||||
if (obj.isObject()) { ... }
|
||||
if (obj.isMember("key")) { ... }
|
||||
```
|
||||
|
||||
### StaticString Optimization
|
||||
```cpp
|
||||
// Use StaticString for compile-time known keys to avoid allocation
|
||||
static const Json::StaticString code("code");
|
||||
static const Json::StaticString message("message");
|
||||
object[code] = 1234; // No dynamic allocation for key
|
||||
object[message] = "ok"; // Key stored as pointer, not copied
|
||||
```
|
||||
|
||||
### Value Type Enum
|
||||
```cpp
|
||||
enum ValueType {
|
||||
nullValue = 0,
|
||||
intValue, uintValue, realValue,
|
||||
stringValue, booleanValue,
|
||||
arrayValue, objectValue
|
||||
};
|
||||
// Check type before accessing to avoid undefined behavior
|
||||
```
|
||||
|
||||
### Lazy Initialization
|
||||
```cpp
|
||||
// Container elements auto-created on access (like JavaScript)
|
||||
Json::Value obj;
|
||||
obj["newKey"]["nested"] = 1; // Creates intermediate objects automatically
|
||||
// Be aware: accessing a non-existent key creates it
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Accessing a non-existent key via `operator[]` creates a null entry - use `isMember()` to check first if you don't want side effects
|
||||
- Use `const` overload of `operator[]` to avoid auto-creation: `obj["key"]` on const ref returns null reference
|
||||
- Prefer `StaticString` for frequently-used keys to avoid repeated allocations
|
||||
- Never assume JSON numeric types - check `isInt()`, `isUInt()`, `isDouble()` explicitly
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/json/json_value.h` - Main Value class
|
||||
- `include/xrpl/json/json_reader.h` - Text-to-Value parser
|
||||
- `include/xrpl/json/json_writer.h` - Value-to-text serializer
|
||||
- `include/xrpl/json/json_forwards.h` - Forward declarations and aliases
|
||||
84
.claude/skills/libxrpl/ledger.md
Normal file
84
.claude/skills/libxrpl/ledger.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Ledger Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with ledger state management in `src/libxrpl/ledger/` or `include/xrpl/ledger/`. Covers views, state tables, payments, and credit operations.
|
||||
|
||||
## Responsibility
|
||||
Manages the state of the distributed ledger: abstractions for viewing, reading, and applying transactions to ledger state. Handles account ownership tracking, trust lines, payment processing, directory management, and credential verification.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### ReadView vs ApplyView
|
||||
```cpp
|
||||
// ReadView: Read-only access to ledger state
|
||||
bool exists = view.exists(keylet::account(accountID));
|
||||
auto sle = view.read(keylet::account(accountID)); // Returns shared_ptr<SLE const>
|
||||
|
||||
// ApplyView: Mutable access for transaction application
|
||||
auto sle = view.peek(keylet::account(accountID)); // Returns shared_ptr<SLE>
|
||||
sle->setFieldAmount(sfBalance, newBalance);
|
||||
view.update(sle); // Commit change
|
||||
view.insert(newSle); // Create new entry
|
||||
view.erase(sle); // Remove entry
|
||||
```
|
||||
|
||||
### Enum-Based Control (No Boolean Blindness)
|
||||
```cpp
|
||||
// NEVER: bool ignoreFreeze = true;
|
||||
// ALWAYS: Use named enums
|
||||
enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN };
|
||||
enum AuthHandling { ahIGNORE_AUTH, ahZERO_IF_UNAUTHORIZED };
|
||||
|
||||
STAmount accountHolds(ReadView const& view, AccountID const& account,
|
||||
Currency const& currency, AccountID const& issuer,
|
||||
FreezeHandling zeroIfFrozen, beast::Journal j);
|
||||
```
|
||||
|
||||
### Asset Variant Handling
|
||||
```cpp
|
||||
// Use std::visit for Asset (Issue or MPTIssue)
|
||||
return std::visit(
|
||||
[&](auto const& issue) {
|
||||
return isIndividualFrozen(view, account, issue);
|
||||
},
|
||||
asset.value());
|
||||
```
|
||||
|
||||
### PaymentSandbox for Isolation
|
||||
```cpp
|
||||
// Test payment effects before committing
|
||||
PaymentSandbox sandbox(&view);
|
||||
// ... apply changes to sandbox ...
|
||||
sandbox.apply(view); // Commit all changes atomically
|
||||
// Or let sandbox destruct to discard
|
||||
```
|
||||
|
||||
### TER Return Codes
|
||||
```cpp
|
||||
// Transaction results are returned as TER, not exceptions
|
||||
TER result = doApply();
|
||||
if (result != tesSUCCESS) return result;
|
||||
// TER categories: tes (success), tec (claimed fee), tef (failure), tel (local), tem (malformed)
|
||||
```
|
||||
|
||||
### Depth Limiting
|
||||
```cpp
|
||||
// Recursive operations use depth parameter to prevent infinite recursion
|
||||
TER checkVaultState(ReadView const& view, AccountID const& id, int depth = 0);
|
||||
if (depth > maxDepth) return tecINTERNAL;
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use `read()` when you need to modify - use `peek()` instead
|
||||
- Never forget to call `view.update(sle)` after modifying a peeked SLE
|
||||
- Never use bare booleans for control flags - use the enum types
|
||||
- Always check for frozen/unauthorized states before operating on trust lines
|
||||
- Never ignore TER return values - propagate them up the call chain
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/ledger/View.h` - Core read/write operations (largest file)
|
||||
- `include/xrpl/ledger/ReadView.h` - Read-only interface
|
||||
- `include/xrpl/ledger/ApplyView.h` - Mutable interface
|
||||
- `src/libxrpl/ledger/PaymentSandbox.cpp` - Isolated payment testing
|
||||
- `src/libxrpl/ledger/ApplyStateTable.cpp` - State change management
|
||||
- `src/libxrpl/ledger/Credit.cpp` - Trust line and IOU operations
|
||||
58
.claude/skills/libxrpl/net.md
Normal file
58
.claude/skills/libxrpl/net.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Net Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with network communication in `src/libxrpl/net/` or `include/xrpl/net/`. Covers HTTP/HTTPS client functionality and SSL certificate management.
|
||||
|
||||
## Responsibility
|
||||
Provides HTTP/HTTPS client functionality for network requests, including SSL certificate registration, asynchronous request handling with boost::asio, and callback-based completion.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Async HTTP with Callbacks
|
||||
```cpp
|
||||
// Callback returns bool indicating success/continuation
|
||||
HTTPClient::get(
|
||||
bSSL, io_context,
|
||||
std::deque<std::string>{"site1.com", "site2.com"}, // Fallback sites
|
||||
443, "/path",
|
||||
maxResponseBytes,
|
||||
timeout,
|
||||
[](boost::system::error_code const& ec, int status, std::string const& body) -> bool {
|
||||
if (ec) return false; // Stop
|
||||
// Process response
|
||||
return true; // Success
|
||||
},
|
||||
headers, journal);
|
||||
```
|
||||
|
||||
### Lifetime Management with shared_from_this
|
||||
```cpp
|
||||
// Async callbacks use intrusive_ptr for safe lifetime
|
||||
class HTTPClientImp : public HTTPClient,
|
||||
public std::enable_shared_from_this<HTTPClientImp> {
|
||||
void startAsync() {
|
||||
auto self = shared_from_this(); // Prevent premature destruction
|
||||
// ... schedule async operations ...
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Deadline Timers
|
||||
```cpp
|
||||
// Always set timeouts for network operations
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> timer_;
|
||||
timer_.expires_after(std::chrono::seconds(timeout));
|
||||
// Cancel pending operation on timeout
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never start async operations without capturing shared_from_this - object may be destroyed before callback
|
||||
- Always set deadline timers on network operations to prevent hanging connections
|
||||
- Always set maximum response size limits to prevent resource exhaustion
|
||||
- Never assume DNS resolution will succeed - handle resolver errors
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/net/HTTPClient.h` - Main HTTP client interface
|
||||
- `src/libxrpl/net/HTTPClient.cpp` - Implementation with async I/O
|
||||
- `src/libxrpl/net/RegisterSSLCerts.cpp` - SSL certificate registration
|
||||
- `include/xrpl/net/HTTPClientSSLContext.h` - SSL context management
|
||||
24
.claude/skills/libxrpl/net/images.md
Normal file
24
.claude/skills/libxrpl/net/images.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Net Images Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with static image assets in `src/libxrpl/net/images/`. Contains embedded image data used by the HTTP server.
|
||||
|
||||
## Responsibility
|
||||
Stores static image assets (favicons, logos) as embedded byte arrays for serving via the built-in HTTP server without external file dependencies.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Embedded Assets
|
||||
```cpp
|
||||
// Images stored as static const byte arrays
|
||||
// Compiled directly into the binary - no file I/O needed at runtime
|
||||
static unsigned char const favicon[] = { /* ... */ };
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Keep embedded images small - they increase binary size
|
||||
- Use appropriate image formats (ICO for favicons, PNG for logos)
|
||||
- Update both the source image and the byte array when changing assets
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/net/images/` - Static image byte arrays embedded in the binary
|
||||
68
.claude/skills/libxrpl/nodestore.md
Normal file
68
.claude/skills/libxrpl/nodestore.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# NodeStore Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with persistent node storage in `src/libxrpl/nodestore/` or `include/xrpl/nodestore/`. Covers the storage abstraction layer, backend implementations, and caching.
|
||||
|
||||
## Responsibility
|
||||
Abstraction layer for persistent storage of ledger nodes (SHAMap leaves and inner nodes). Supports multiple backend implementations (RocksDB, NuDB, Memory, Null) with a plugin architecture, caching, and async operations.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Abstract Factory for Backends
|
||||
```cpp
|
||||
// Backend is pure virtual - concrete implementations selected at runtime
|
||||
class Backend {
|
||||
virtual ~Backend() = default;
|
||||
virtual Status fetch(void const* key, std::shared_ptr<NodeObject>*) = 0;
|
||||
virtual void store(std::shared_ptr<NodeObject> const&) = 0;
|
||||
virtual void storeBatch(Batch const& batch) = 0;
|
||||
};
|
||||
// Backends: RocksDB, NuDB, Memory (testing), Null (disabled)
|
||||
```
|
||||
|
||||
### Batch Operations
|
||||
```cpp
|
||||
// Always prefer batch operations for multiple reads/writes
|
||||
virtual std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) = 0;
|
||||
virtual void storeBatch(Batch const& batch) = 0;
|
||||
// Significantly reduces I/O overhead vs individual operations
|
||||
```
|
||||
|
||||
### Status Enum (Not Exceptions)
|
||||
```cpp
|
||||
enum class Status { ok, notFound, keyTooBig, /* ... */ };
|
||||
// I/O operations return Status, NOT throw exceptions
|
||||
auto [objects, status] = backend->fetchBatch(hashes);
|
||||
if (status != Status::ok) { /* handle */ }
|
||||
```
|
||||
|
||||
### Configuration via Section
|
||||
```cpp
|
||||
// Backend options come from config file sections
|
||||
RocksDBBackend(int keyBytes, Section const& keyValues,
|
||||
Scheduler& scheduler, beast::Journal journal);
|
||||
// Allows runtime tuning without recompilation
|
||||
```
|
||||
|
||||
### Async Fetch with Scheduler
|
||||
```cpp
|
||||
// Non-blocking reads via scheduler integration
|
||||
virtual void asyncFetch(uint256 const& hash,
|
||||
std::function<void(std::shared_ptr<NodeObject>)>&& callback);
|
||||
// Callback invoked on scheduler thread
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use individual fetch/store in tight loops - use batch operations
|
||||
- Never throw exceptions from backend implementations - return Status enum
|
||||
- Always configure appropriate cache sizes for the workload
|
||||
- Never assume a fetch will succeed - always check Status
|
||||
- Use Memory backend for unit tests, never RocksDB
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/nodestore/Database.h` - Main storage interface
|
||||
- `include/xrpl/nodestore/Backend.h` - Abstract backend interface
|
||||
- `include/xrpl/nodestore/Manager.h` - Backend factory
|
||||
- `include/xrpl/nodestore/NodeObject.h` - Individual node wrapper
|
||||
- `src/libxrpl/nodestore/BatchWriter.cpp` - Batch write optimization
|
||||
66
.claude/skills/libxrpl/nodestore/backend.md
Normal file
66
.claude/skills/libxrpl/nodestore/backend.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# NodeStore Backend Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with storage backend implementations in `src/libxrpl/nodestore/backend/`. Covers RocksDB, NuDB, Memory, and Null backend factories.
|
||||
|
||||
## Responsibility
|
||||
Concrete backend implementations for the NodeStore abstraction layer. Each backend provides persistent (or ephemeral) storage with different performance characteristics and use cases.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Backend Factory Registration
|
||||
```cpp
|
||||
// Each backend is a factory that creates Backend instances
|
||||
// Registered by name in the Manager
|
||||
class RocksDBFactory : public Factory {
|
||||
std::string getName() const override { return "RocksDB"; }
|
||||
std::unique_ptr<Backend> createInstance(...) override;
|
||||
};
|
||||
```
|
||||
|
||||
### RocksDB Configuration
|
||||
```cpp
|
||||
// Extensive tuning via config Section
|
||||
// Key options:
|
||||
// open_files - Max open file descriptors
|
||||
// filter_bits - Bloom filter bits per key (default 10)
|
||||
// cache_mb - Block cache size in MB
|
||||
// file_size_mb - Target SST file size
|
||||
// compression - snappy (default), zlib, lz4, none
|
||||
// block_size - Block size in KB (default 4)
|
||||
// num_threads - Background compaction threads
|
||||
```
|
||||
|
||||
### NuDB for Deterministic Storage
|
||||
```cpp
|
||||
// NuDB supports deterministic initialization
|
||||
// Useful for reproducible test databases
|
||||
// Hash-based storage with direct memory-mapped I/O
|
||||
// Lower CPU overhead than RocksDB for write-heavy workloads
|
||||
```
|
||||
|
||||
### Memory Backend for Testing
|
||||
```cpp
|
||||
// In-memory storage - fast but not persistent
|
||||
// Use for unit tests only
|
||||
// Thread-safe with internal mutex
|
||||
```
|
||||
|
||||
### Null Backend for Disabled Storage
|
||||
```cpp
|
||||
// No-op backend - all operations succeed but store nothing
|
||||
// Use when storage feature is disabled in config
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Use Memory backend for tests, never RocksDB (test isolation and speed)
|
||||
- Always tune RocksDB bloom filter bits - default 10 is good for most workloads
|
||||
- NuDB doesn't support range queries - only point lookups by hash
|
||||
- Never use Null backend in production - data loss guaranteed
|
||||
- Always configure appropriate open_files limits for the OS
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/nodestore/backend/RocksDBFactory.cpp` - RocksDB backend (~12.5KB)
|
||||
- `src/libxrpl/nodestore/backend/NuDBFactory.cpp` - NuDB backend (~12KB)
|
||||
- `src/libxrpl/nodestore/backend/MemoryFactory.cpp` - In-memory backend (~5KB)
|
||||
- `src/libxrpl/nodestore/backend/NullFactory.cpp` - No-op backend (~2KB)
|
||||
35
.claude/skills/libxrpl/proto.md
Normal file
35
.claude/skills/libxrpl/proto.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Proto Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with Protocol Buffer definitions in `include/xrpl/proto/`. Covers gRPC API definitions and generated protobuf headers.
|
||||
|
||||
## Responsibility
|
||||
Contains Protocol Buffer generated headers defining the gRPC API for rippled. These define the wire format for RPC communication between clients and the server.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Proto Organization
|
||||
```
|
||||
include/xrpl/proto/
|
||||
└── org/xrpl/rpc/v1/
|
||||
└── *.proto generated headers
|
||||
```
|
||||
|
||||
### Usage
|
||||
```cpp
|
||||
#include <xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
// Use generated types for gRPC request/response
|
||||
```
|
||||
|
||||
### Versioning
|
||||
- API is versioned under `org/xrpl/rpc/v1/`
|
||||
- New versions get a new directory (v2/, etc.)
|
||||
- Never modify generated files directly - modify the .proto source
|
||||
|
||||
## Common Pitfalls
|
||||
- Never hand-edit generated .pb.h files - regenerate from .proto sources
|
||||
- Always use the versioned path (v1/) when including proto headers
|
||||
- Proto types are for serialization only - convert to native types for business logic
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/proto/org/xrpl/rpc/v1/` - Generated gRPC API headers
|
||||
123
.claude/skills/libxrpl/protocol.md
Normal file
123
.claude/skills/libxrpl/protocol.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Protocol Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with serialization and data types in `src/libxrpl/protocol/` or `include/xrpl/protocol/`. Covers STObject hierarchy, SField registry, serialization, TER codes, features, and keylets.
|
||||
|
||||
## Responsibility
|
||||
Defines serialization formats, data types, and protocol constants. Handles conversion between C++ objects and wire format, JSON representation, and database storage. The largest module in libxrpl with 60+ files.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### STObject Hierarchy
|
||||
```cpp
|
||||
// STBase is the abstract root for all serializable types
|
||||
// Concrete types: STInteger<N>, STBlob, STAmount, STArray, STObject, STPathSet, STVector256
|
||||
|
||||
// Access fields type-safely via SField references
|
||||
auto amount = obj[sfAmount]; // Returns STAmount
|
||||
auto flags = obj[sfFlags]; // Returns uint32
|
||||
auto dest = obj[sfDestination]; // Returns AccountID
|
||||
auto has = obj.isFieldPresent(sfMemos); // Check presence
|
||||
```
|
||||
|
||||
### SField Registry
|
||||
```cpp
|
||||
// Fields are statically registered - never create SField at runtime
|
||||
// SField carries type information and field ID
|
||||
extern SField const sfAmount; // STAmount type
|
||||
extern SField const sfFlags; // STInteger<uint32> type
|
||||
extern SField const sfDestination; // STAccount type
|
||||
|
||||
// Field IDs are protocol-defined and must not change
|
||||
```
|
||||
|
||||
### Serializer for Binary Format
|
||||
```cpp
|
||||
// Deterministic binary serialization
|
||||
Serializer s;
|
||||
obj.add(s); // Append binary representation
|
||||
auto blob = s.peekData(); // Get bytes
|
||||
|
||||
// Deserialization
|
||||
SerialIter sit(blob.data(), blob.size());
|
||||
auto obj = std::make_shared<STObject>(sit, sfTransaction);
|
||||
```
|
||||
|
||||
### Bidirectional JSON/Binary Conversion
|
||||
```cpp
|
||||
// Object to JSON
|
||||
Json::Value json = obj.getJson(JsonOptions::none);
|
||||
|
||||
// JSON to Object
|
||||
STParsedJSONObject parsed("tx_json", json);
|
||||
if (parsed.object) { /* use parsed.object */ }
|
||||
```
|
||||
|
||||
### TER (Transaction Error Result) Codes
|
||||
```cpp
|
||||
// Categories:
|
||||
// tes - success (tesSUCCESS)
|
||||
// tec - claimed fee, no effect (tecNO_DST, tecFROZEN, tecINSUFFICIENT_RESERVE)
|
||||
// tef - failure (tefFAILURE)
|
||||
// tel - local error (telNETWORK_ID_MAKES_TX_NON_CANONICAL)
|
||||
// tem - malformed (temINVALID, temBAD_AMOUNT, temDISABLED)
|
||||
|
||||
// Check categories:
|
||||
isTesSuccess(ter) // ter == tesSUCCESS
|
||||
isTecClaim(ter) // tec range
|
||||
isTemMalformed(ter) // tem range
|
||||
```
|
||||
|
||||
### Feature/Amendment Flags
|
||||
```cpp
|
||||
// Gate new behavior on amendments
|
||||
if (ctx.rules.enabled(featureMyFeature)) {
|
||||
// New behavior
|
||||
} else {
|
||||
// Legacy behavior
|
||||
}
|
||||
// Register features in Feature.cpp
|
||||
```
|
||||
|
||||
### Keylet for Ledger Entry Keys
|
||||
```cpp
|
||||
// Type-safe ledger key generation
|
||||
auto key = keylet::account(accountID); // Account root
|
||||
auto key = keylet::line(a, b, currency); // Trust line
|
||||
auto key = keylet::offer(account, seq); // Offer
|
||||
auto key = keylet::nftoken(tokenID); // NFT
|
||||
// Keylet carries both the key (uint256) and the expected ledger entry type
|
||||
```
|
||||
|
||||
### SOTemplate for Schema Validation
|
||||
```cpp
|
||||
// Define expected fields for a ledger entry type
|
||||
SOTemplate const ltACCOUNT_ROOT = {
|
||||
{sfAccount, soeREQUIRED},
|
||||
{sfBalance, soeREQUIRED},
|
||||
{sfFlags, soeREQUIRED},
|
||||
{sfSequence, soeREQUIRED},
|
||||
{sfOwnerCount, soeDEFAULT},
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never create SField instances at runtime - they are static protocol definitions
|
||||
- Never modify field IDs - they are part of the binary protocol
|
||||
- Always use `isFieldPresent()` before accessing optional fields
|
||||
- Never ignore TER return values - they carry critical error information
|
||||
- Always gate new fields/behavior on feature amendments for consensus safety
|
||||
- Respect JSON parsing depth limit of 10 to prevent stack overflow
|
||||
- Use `[[nodiscard]]` on functions returning TER
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/protocol/STObject.h` - Generic structured object container
|
||||
- `include/xrpl/protocol/STAmount.h` - XRP and IOU amounts
|
||||
- `include/xrpl/protocol/SField.h` - Field definitions
|
||||
- `include/xrpl/protocol/TER.h` - Transaction result codes
|
||||
- `include/xrpl/protocol/Feature.h` - Amendment flags
|
||||
- `include/xrpl/protocol/Indexes.h` - Ledger entry key generation
|
||||
- `include/xrpl/protocol/Keylet.h` - Type-safe ledger keys
|
||||
- `include/xrpl/protocol/SOTemplate.h` - Object schema definitions
|
||||
- `src/libxrpl/protocol/STParsedJSON.cpp` - JSON to object conversion
|
||||
60
.claude/skills/libxrpl/rdb.md
Normal file
60
.claude/skills/libxrpl/rdb.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# RDB Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with relational database access in `src/libxrpl/rdb/` or `include/xrpl/rdb/`. Covers SOCI wrapper, database configuration, and checkpointing.
|
||||
|
||||
## Responsibility
|
||||
Provides a C++ wrapper around SOCI (SQLite/PostgreSQL abstraction) for relational data access, configuration management, blob type conversions, and periodic WAL checkpoint management.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### DBConfig Lazy Initialization
|
||||
```cpp
|
||||
// Construct config without opening connection
|
||||
DBConfig config(basicConfig, "my_database");
|
||||
|
||||
// Open session later when needed
|
||||
soci::session session;
|
||||
config.open(session);
|
||||
// Allows config parsing separate from database I/O
|
||||
```
|
||||
|
||||
### Blob Conversions
|
||||
```cpp
|
||||
// Convert between SOCI blobs and standard types
|
||||
soci::blob blob(session);
|
||||
std::vector<std::uint8_t> bytes;
|
||||
convert(blob, bytes); // blob -> vector
|
||||
|
||||
std::string str;
|
||||
convert(blob, str); // blob -> string
|
||||
```
|
||||
|
||||
### Checkpointer with Weak Pointer Safety
|
||||
```cpp
|
||||
// Checkpointer uses weak_ptr to detect session destruction
|
||||
auto checkpointer = makeCheckpointer(
|
||||
id,
|
||||
std::weak_ptr<soci::session>(sessionPtr),
|
||||
jobQueue,
|
||||
logs);
|
||||
checkpointer->schedule(); // Periodic WAL checkpoints
|
||||
// If session is destroyed, checkpointer safely no-ops
|
||||
```
|
||||
|
||||
### Thread-Safe Sessions
|
||||
```cpp
|
||||
// Each thread gets its own soci::session from the pool
|
||||
// Never share a soci::session across threads
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never share a soci::session across threads - each thread needs its own
|
||||
- Always use `std::weak_ptr` for session references in long-lived objects (like Checkpointer)
|
||||
- Be aware of SOCI include warnings - use pragma diagnostic push/pop
|
||||
- Always convert blobs to standard types before processing
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/rdb/SociDB.h` - Main wrapper interface
|
||||
- `src/libxrpl/rdb/SociDB.cpp` - Implementation
|
||||
- `src/libxrpl/rdb/DatabaseCon.cpp` - Database connection setup
|
||||
64
.claude/skills/libxrpl/resource.md
Normal file
64
.claude/skills/libxrpl/resource.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Resource Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with rate limiting and resource management in `src/libxrpl/resource/` or `include/xrpl/resource/`. Covers endpoint tracking, charge/fee management, and abuse prevention.
|
||||
|
||||
## Responsibility
|
||||
Tracks resource consumption by network endpoints (inbound/outbound connections) to prevent abuse and ensure fair resource allocation. Manages consumer lifecycle, charge accounting, and gossip-based reputation sharing.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Manager/Impl Pattern
|
||||
```cpp
|
||||
// Abstract Manager interface with factory function
|
||||
class Manager { virtual ~Manager() = 0; };
|
||||
std::unique_ptr<Manager> make_Manager(beast::Journal journal);
|
||||
|
||||
// Implementation hidden in cpp
|
||||
class ManagerImp : public Manager { /* ... */ };
|
||||
```
|
||||
|
||||
### Consumer Factory
|
||||
```cpp
|
||||
// Different consumer types for different connection sources
|
||||
Consumer newInboundEndpoint(beast::IP::Endpoint const& address);
|
||||
Consumer newOutboundEndpoint(beast::IP::Endpoint const& address);
|
||||
Consumer newUnlimitedEndpoint(beast::IP::Endpoint const& address);
|
||||
```
|
||||
|
||||
### Background Thread Shutdown
|
||||
```cpp
|
||||
// Clean shutdown pattern with condition variable
|
||||
~ManagerImp() {
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
stop_ = true;
|
||||
cond_.notify_one();
|
||||
}
|
||||
thread_.join(); // Wait for thread to finish
|
||||
}
|
||||
```
|
||||
|
||||
### Proxy-Aware Endpoint Detection
|
||||
```cpp
|
||||
// Handle forwarded-for headers safely
|
||||
boost::system::error_code ec;
|
||||
auto proxiedIp = boost::asio::ip::make_address(forwardedFor, ec);
|
||||
if (ec) {
|
||||
journal_.warn() << "Invalid IP: " << ec.message();
|
||||
return newInboundEndpoint(address); // Fallback to socket IP
|
||||
}
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never trust forwarded-for headers without proxy flag validation
|
||||
- Always use the factory methods - never construct Consumer directly
|
||||
- Always join background threads in destructor
|
||||
- Use separate consumer types for different connection trust levels
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/resource/ResourceManager.h` - Manager interface
|
||||
- `src/libxrpl/resource/ResourceManager.cpp` - Implementation
|
||||
- `include/xrpl/resource/Consumer.h` - Per-endpoint tracking
|
||||
- `src/libxrpl/resource/Charge.cpp` - Cost definitions
|
||||
- `src/libxrpl/resource/Fees.cpp` - Fee calculations
|
||||
68
.claude/skills/libxrpl/server.md
Normal file
68
.claude/skills/libxrpl/server.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Server Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with server configuration in `src/libxrpl/server/` or `include/xrpl/server/`. Covers port configuration, SSL/TLS, WebSocket options, and authentication.
|
||||
|
||||
## Responsibility
|
||||
Manages server listening ports, WebSocket configuration, SSL/TLS setup, authentication credentials, and admin network restrictions. Handles parsing configuration into validated port structures.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Dual ParsedPort/Port Pattern
|
||||
```cpp
|
||||
// ParsedPort: intermediate parsing result (may be incomplete)
|
||||
struct ParsedPort { /* partially validated fields */ };
|
||||
|
||||
// Port: final validated configuration (ready to use)
|
||||
struct Port {
|
||||
std::string name;
|
||||
boost::asio::ip::address ip;
|
||||
std::uint16_t port = 0;
|
||||
std::set<std::string, iless> protocol;
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### Configuration Section Parsing
|
||||
```cpp
|
||||
// Parse from config file section, log errors to stream
|
||||
void parse_Port(ParsedPort& port, Section const& section, std::ostream& log);
|
||||
// Does NOT throw - logs issues and sets defaults
|
||||
```
|
||||
|
||||
### CIDR Admin Networks
|
||||
```cpp
|
||||
// IP-based admin access control with CIDR support
|
||||
std::vector<boost::asio::ip::network_v4> admin_nets_v4;
|
||||
std::vector<boost::asio::ip::network_v6> admin_nets_v6;
|
||||
// Supports both IPv4 and IPv6 ranges
|
||||
```
|
||||
|
||||
### WebSocket Options
|
||||
```cpp
|
||||
// Fine-grained compression control
|
||||
boost::beast::websocket::permessage_deflate pmd_options;
|
||||
// Queue limits prevent memory exhaustion
|
||||
std::optional<std::uint16_t> ws_queue_limit;
|
||||
// limit=0 means unlimited (not -1)
|
||||
```
|
||||
|
||||
### SSL Context Lazy Creation
|
||||
```cpp
|
||||
// SSL context created only when needed
|
||||
std::shared_ptr<boost::asio::ssl::context> context;
|
||||
// Initialized when first SSL connection established
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never use port-only access control - always use CIDR network restrictions for admin
|
||||
- Use `iless` comparator for protocol names (case-insensitive)
|
||||
- Remember that `limit=0` means unlimited, not disabled
|
||||
- Always log parsing errors rather than throwing
|
||||
- Separate user/admin credentials - don't reuse
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/server/Port.h` - Port configuration structure
|
||||
- `src/libxrpl/server/Port.cpp` - Parsing and validation
|
||||
- `src/libxrpl/server/JSONRPCUtil.cpp` - RPC utility functions
|
||||
- `src/libxrpl/server/LoadFeeTrack.cpp` - Load and fee tracking
|
||||
83
.claude/skills/libxrpl/shamap.md
Normal file
83
.claude/skills/libxrpl/shamap.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# SHAMap Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with the Merkle tree implementation in `src/libxrpl/shamap/` or `include/xrpl/shamap/`. Covers the SHA-256 based radix tree used for ledger state representation.
|
||||
|
||||
## Responsibility
|
||||
Implements a SHA-256 based Merkle radix tree with 16-way branching (hexadecimal). Provides efficient ledger state representation with O(log N) proof-of-inclusion, copy-on-write snapshots, synchronization, and delta calculation.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### State Machine Lifecycle
|
||||
```cpp
|
||||
enum class SHAMapState { Modifying, Immutable, Synching, Invalid };
|
||||
// Modifying: Can add/remove/modify entries
|
||||
// Immutable: Snapshot - no modifications allowed
|
||||
// Synching: Being synchronized from peers
|
||||
// Invalid: Corrupted or destroyed
|
||||
// Transitions are one-way: Modifying -> Immutable (via snapshot)
|
||||
```
|
||||
|
||||
### Copy-on-Write via COWID
|
||||
```cpp
|
||||
std::uint32_t cowid_ = 1;
|
||||
// Each snapshot gets a new COWID
|
||||
// Children are only copied when modified (lazy copy)
|
||||
// Immutable snapshots share nodes with the active map
|
||||
auto snapshot = map.snapShot(true); // Creates immutable copy
|
||||
```
|
||||
|
||||
### 16-Way Radix Branching
|
||||
```cpp
|
||||
static inline constexpr unsigned int branchFactor = 16;
|
||||
static inline constexpr unsigned int leafDepth = 64;
|
||||
// 256-bit key / 4 bits per nibble = 64 levels max
|
||||
// Each inner node has up to 16 children
|
||||
```
|
||||
|
||||
### Node Type Hierarchy
|
||||
```cpp
|
||||
// SHAMapTreeNode (base) -> SHAMapInnerNode (16 children)
|
||||
// -> SHAMapLeafNode (data + key)
|
||||
// Use dynamic_pointer_cast for safe downcasting
|
||||
auto inner = intr_ptr::dynamic_pointer_cast<SHAMapInnerNode>(node);
|
||||
if (inner) { /* process inner node */ }
|
||||
```
|
||||
|
||||
### Walk-Up for Modifications (dirtyUp)
|
||||
```cpp
|
||||
// After modifying a leaf, propagate hash changes to root
|
||||
void dirtyUp(SharedPtrNodeStack& stack, uint256 const& target, ...);
|
||||
// Updates hashes from leaf -> root through the stack
|
||||
```
|
||||
|
||||
### Lazy Traversal
|
||||
```cpp
|
||||
// Navigate to a leaf by key
|
||||
SHAMapLeafNode* walkTowardsKey(uint256 const& id,
|
||||
SharedPtrNodeStack* stack = nullptr);
|
||||
// Returns leaf or nullptr; optionally records path for dirtyUp
|
||||
```
|
||||
|
||||
### Intrusive Pointers for Nodes
|
||||
```cpp
|
||||
// Nodes use intrusive reference counting (not std::shared_ptr)
|
||||
intr_ptr::SharedPtr<SHAMapTreeNode> root_;
|
||||
// Minimal overhead - reference count embedded in node
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never modify an Immutable map - check state before mutations
|
||||
- Always call dirtyUp after modifying a leaf to maintain hash integrity
|
||||
- Never assume node type without dynamic_pointer_cast check
|
||||
- Remember that snapshots share nodes - COW means nodes are only copied on write
|
||||
- Always use the provided iterators for safe traversal, not manual tree walking
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/shamap/SHAMap.h` - Main map implementation
|
||||
- `include/xrpl/shamap/SHAMapTreeNode.h` - Base node class
|
||||
- `include/xrpl/shamap/SHAMapInnerNode.h` - Interior nodes (16-way)
|
||||
- `include/xrpl/shamap/SHAMapLeafNode.h` - Leaf nodes with data
|
||||
- `include/xrpl/shamap/SHAMapNodeID.h` - Tree position identifier
|
||||
- `src/libxrpl/shamap/SHAMapDelta.cpp` - Difference between maps
|
||||
- `src/libxrpl/shamap/SHAMapSync.cpp` - Synchronization algorithm
|
||||
137
.claude/skills/libxrpl/tx.md
Normal file
137
.claude/skills/libxrpl/tx.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Transaction (tx) Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with transaction processing in `src/libxrpl/tx/` or `include/xrpl/tx/`. Covers the Transactor base class, transaction pipeline, invariant checks, and apply context.
|
||||
|
||||
## Responsibility
|
||||
Implements the transaction processing pipeline: static validation (preflight), fee-claim checks (preclaim), transaction execution (doApply), and post-apply invariant verification. All transaction types derive from the Transactor base class.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Transaction Pipeline (3 Phases)
|
||||
```cpp
|
||||
// Phase 1: Preflight - Static validation, NO ledger access
|
||||
static NotTEC preflight(PreflightContext const& ctx) {
|
||||
if (ctx.tx[sfAmount] <= beast::zero)
|
||||
return temBAD_AMOUNT;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// Phase 2: Preclaim - Ledger read-only checks
|
||||
static TER preclaim(PreclaimContext const& ctx) {
|
||||
auto sle = ctx.view.read(keylet::account(ctx.tx[sfAccount]));
|
||||
if (!sle) return tecNO_DST;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// Phase 3: doApply - Actual ledger mutations
|
||||
TER doApply() override {
|
||||
auto sle = view().peek(keylet::account(account_));
|
||||
sle->setFieldAmount(sfBalance, newBalance);
|
||||
view().update(sle);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
### Transactor Base Class
|
||||
```cpp
|
||||
class MyTransaction : public Transactor {
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit MyTransaction(ApplyContext& ctx) : Transactor(ctx) {}
|
||||
|
||||
// Optional: Gate on amendment
|
||||
static bool checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
// Optional: Custom flag mask
|
||||
static std::uint32_t getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
// Required
|
||||
static NotTEC preflight(PreflightContext const& ctx);
|
||||
static TER preclaim(PreclaimContext const& ctx);
|
||||
TER doApply() override;
|
||||
|
||||
// Optional: Custom fee calculation
|
||||
static XRPAmount calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
};
|
||||
```
|
||||
|
||||
### Feature Gating
|
||||
```cpp
|
||||
static bool checkExtraFeatures(PreflightContext const& ctx) {
|
||||
// Return false to disable when amendment not enabled
|
||||
return ctx.rules.enabled(featureMyFeature);
|
||||
}
|
||||
```
|
||||
|
||||
### Flag Validation
|
||||
```cpp
|
||||
static std::uint32_t getFlagsMask(PreflightContext const& ctx) {
|
||||
return tfMyTransactionMask; // Allowed flags
|
||||
}
|
||||
// Base class validates: (tx.getFlags() & ~getFlagsMask()) == 0
|
||||
```
|
||||
|
||||
### ConsequencesFactory Types
|
||||
```cpp
|
||||
// Normal: Standard transaction
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
// Blocker: Affects subsequent transactions' ability to claim fees
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Blocker};
|
||||
// Custom: Override makeTxConsequences() static method
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
```
|
||||
|
||||
### TER Error Code Progression
|
||||
```
|
||||
tem* (malformed): temINVALID, temBAD_AMOUNT, temDISABLED - preflight errors
|
||||
tef* (failure): tefFAILURE, tefNESTED_FAILURE - infrastructure errors
|
||||
tel* (local): telNETWORK_ID_MAKES_TX_NON_CANONICAL - local-only errors
|
||||
tec* (claimed): tecNO_DST, tecFROZEN, tecINSUFFICIENT_RESERVE - fee claimed, no effect
|
||||
tes (success): tesSUCCESS - transaction applied
|
||||
```
|
||||
|
||||
### Logging Convention
|
||||
```cpp
|
||||
JLOG(ctx.j.warn()) << "User error message"; // User-facing issues
|
||||
JLOG(ctx.j.debug()) << "Detailed diagnostic"; // Implementation details
|
||||
JLOG(ctx.j.trace()) << "Very verbose info"; // Deep debugging
|
||||
JLOG(ctx.j.error()) << "Unexpected failure"; // Should not happen
|
||||
```
|
||||
|
||||
### View Operations in doApply
|
||||
```cpp
|
||||
// Read-only (returns const SLE)
|
||||
auto sle = view().read(keylet::account(accountID));
|
||||
|
||||
// Mutable (returns non-const SLE)
|
||||
auto sle = view().peek(keylet::account(accountID));
|
||||
sle->setFieldAmount(sfBalance, newBalance);
|
||||
view().update(sle); // MUST call after modification
|
||||
|
||||
// Create new entry
|
||||
auto sle = std::make_shared<SLE>(keylet::myEntry(id));
|
||||
sle->setFieldText(sfData, data);
|
||||
view().insert(sle);
|
||||
|
||||
// Remove entry
|
||||
view().erase(sle);
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never access ledger state in preflight - it only has PreflightContext (no view)
|
||||
- Never mutate ledger state in preclaim - it has ReadView only
|
||||
- Always call `view().update(sle)` after modifying a peeked SLE
|
||||
- Never return `tesSUCCESS` from preclaim/preflight if validation failed
|
||||
- Always gate new transaction types on feature amendments
|
||||
- Use `NotTEC` return type for preflight (not TER) - prevents returning tec codes from static checks
|
||||
- Never forget to register new transaction types in `transactions.macro` and `applySteps.cpp`
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/tx/Transactor.h` - Base class with static method signatures
|
||||
- `src/libxrpl/tx/Transactor.cpp` - Base implementation (41KB)
|
||||
- `src/libxrpl/tx/apply.cpp` - Transaction application entry point
|
||||
- `src/libxrpl/tx/ApplyContext.cpp` - Context management
|
||||
- `src/libxrpl/tx/InvariantCheck.cpp` - Post-apply invariant validation (117KB)
|
||||
- `src/libxrpl/tx/applySteps.cpp` - Step-by-step dispatch
|
||||
72
.claude/skills/libxrpl/tx/paths.md
Normal file
72
.claude/skills/libxrpl/tx/paths.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Transaction Paths Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with payment path finding and execution in `src/libxrpl/tx/paths/` or `include/xrpl/tx/paths/`. Covers the flow engine, ripple calculation, and offer stream processing.
|
||||
|
||||
## Responsibility
|
||||
Implements payment path finding and execution for cross-currency payments. Handles the flow engine for executing payments across multiple paths (strands), offer book management, and amount calculation.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Flow Engine Entry Point
|
||||
```cpp
|
||||
path::RippleCalc::Output flow(
|
||||
PaymentSandbox& view,
|
||||
STAmount const& deliver,
|
||||
AccountID const& src,
|
||||
AccountID const& dst,
|
||||
STPathSet const& paths,
|
||||
bool defaultPaths,
|
||||
bool partialPayment,
|
||||
bool ownerPaysTransferFee,
|
||||
OfferCrossing offerCrossing,
|
||||
std::optional<Quality> const& limitQuality,
|
||||
std::optional<STAmount> const& sendMax,
|
||||
std::optional<uint256> const& domainID,
|
||||
beast::Journal j,
|
||||
path::detail::FlowDebugInfo* flowDebugInfo = nullptr);
|
||||
```
|
||||
|
||||
### Strand-Based Execution
|
||||
```cpp
|
||||
// A "strand" is a single payment path through the DEX
|
||||
// Multiple strands can be tried to find the best rate
|
||||
// StrandFlow executes a single strand
|
||||
// Flow tries all strands and picks the best result
|
||||
```
|
||||
|
||||
### OfferStream for Order Book Processing
|
||||
```cpp
|
||||
// Iterates through offers in an order book
|
||||
// Handles expired offers, unfunded offers, and self-crossing
|
||||
// Automatically cleans up stale offers during traversal
|
||||
```
|
||||
|
||||
### Quality-Based Routing
|
||||
```cpp
|
||||
// Quality = exchange rate between input and output
|
||||
// Lower quality number = better rate
|
||||
// limitQuality prevents accepting rates worse than threshold
|
||||
```
|
||||
|
||||
### PaymentSandbox Isolation
|
||||
```cpp
|
||||
// All path calculations happen in a PaymentSandbox
|
||||
// Changes are only committed if the payment succeeds
|
||||
// Allows trying multiple paths without side effects
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never modify the ledger directly during path calculation - use PaymentSandbox
|
||||
- Always respect limitQuality to prevent unfavorable exchange rates
|
||||
- Be aware that offer traversal may clean up stale offers as a side effect
|
||||
- FlowDebugInfo is optional and only for debugging - never rely on it in production logic
|
||||
- Path finding is computationally expensive - respect depth and complexity limits
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/tx/paths/Flow.h` - Main flow engine entry point
|
||||
- `include/xrpl/tx/paths/RippleCalc.h` - Payment amount calculation
|
||||
- `src/libxrpl/tx/paths/OfferStream.cpp` - Order book traversal (~12KB)
|
||||
- `src/libxrpl/tx/paths/BookTip.cpp` - Order book tip management
|
||||
- `src/libxrpl/tx/paths/detail/Steps.h` - Step-by-step calculation
|
||||
- `src/libxrpl/tx/paths/detail/StrandFlow.h` - Single path execution
|
||||
164
.claude/skills/libxrpl/tx/transactors.md
Normal file
164
.claude/skills/libxrpl/tx/transactors.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Transactors Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when adding or modifying transaction types in `src/libxrpl/tx/transactors/`. This is the guide for implementing new transactors following the established patterns.
|
||||
|
||||
## Responsibility
|
||||
Contains all concrete transaction type implementations. Each transactor follows the Transactor base class pattern with preflight/preclaim/doApply phases. Transaction types are organized by feature area in subdirectories.
|
||||
|
||||
## Template for New Transactors
|
||||
|
||||
### Header File (`include/xrpl/tx/transactors/MyTx.h`)
|
||||
```cpp
|
||||
#pragma once
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class MyTransaction : public Transactor {
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit MyTransaction(ApplyContext& ctx) : Transactor(ctx) {}
|
||||
|
||||
static bool checkExtraFeatures(PreflightContext const& ctx);
|
||||
static std::uint32_t getFlagsMask(PreflightContext const& ctx);
|
||||
static NotTEC preflight(PreflightContext const& ctx);
|
||||
static TER preclaim(PreclaimContext const& ctx);
|
||||
TER doApply() override;
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation File (`src/libxrpl/tx/transactors/MyFeature/MyTx.cpp`)
|
||||
```cpp
|
||||
#include <xrpl/tx/transactors/MyTx.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
bool
|
||||
MyTransaction::checkExtraFeatures(PreflightContext const& ctx)
|
||||
{
|
||||
return ctx.rules.enabled(featureMyFeature);
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
MyTransaction::getFlagsMask(PreflightContext const& ctx)
|
||||
{
|
||||
return tfUniversalMask; // Or custom mask
|
||||
}
|
||||
|
||||
NotTEC
|
||||
MyTransaction::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
// Static validation - NO ledger access
|
||||
auto const& tx = ctx.tx;
|
||||
|
||||
if (tx[sfAmount] <= beast::zero)
|
||||
{
|
||||
JLOG(ctx.j.warn()) << "Bad amount.";
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
MyTransaction::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
// Ledger read-only checks
|
||||
auto const sle = ctx.view.read(
|
||||
keylet::account(ctx.tx[sfAccount]));
|
||||
if (!sle)
|
||||
return terNO_ACCOUNT;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
MyTransaction::doApply()
|
||||
{
|
||||
// Mutate ledger state
|
||||
auto sle = view().peek(keylet::account(account_));
|
||||
if (!sle)
|
||||
return tefINTERNAL;
|
||||
|
||||
sle->setFieldAmount(sfBalance, newBalance);
|
||||
view().update(sle);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Registration Checklist
|
||||
1. Add transaction type to `include/xrpl/protocol/detail/transactions.macro`
|
||||
2. Add dispatch case to `src/libxrpl/tx/applySteps.cpp`
|
||||
3. Add feature flag to `include/xrpl/protocol/Feature.h` and `src/libxrpl/protocol/Feature.cpp`
|
||||
4. Add invariant checks if needed in `src/libxrpl/tx/InvariantCheck.cpp`
|
||||
5. Add to `disabledTxTypes` in Batch.cpp if not batch-compatible
|
||||
|
||||
## Key Patterns Across All Transactors
|
||||
|
||||
### Feature Gating
|
||||
```cpp
|
||||
static bool checkExtraFeatures(PreflightContext const& ctx) {
|
||||
return ctx.rules.enabled(featureMyFeature);
|
||||
}
|
||||
```
|
||||
|
||||
### Variant-Aware Validation
|
||||
```cpp
|
||||
// When handling Asset (Issue or MPTIssue):
|
||||
if (auto const ret = std::visit(
|
||||
[&]<typename T>(T const&) { return preflightHelper<T>(ctx); },
|
||||
ctx.tx[sfAmount].asset().value()); !isTesSuccess(ret))
|
||||
return ret;
|
||||
```
|
||||
|
||||
### Ledger Entry CRUD in doApply
|
||||
```cpp
|
||||
// Create
|
||||
auto sle = std::make_shared<SLE>(keylet::myEntry(id));
|
||||
view().insert(sle);
|
||||
|
||||
// Read (mutable)
|
||||
auto sle = view().peek(keylet::myEntry(id));
|
||||
|
||||
// Update
|
||||
sle->setFieldU32(sfFlags, newFlags);
|
||||
view().update(sle);
|
||||
|
||||
// Delete
|
||||
view().erase(sle);
|
||||
```
|
||||
|
||||
### Helper/Utils Files
|
||||
```cpp
|
||||
// Complex features use a separate Helpers/Utils file:
|
||||
// AMM -> AMMHelpers.h, AMMUtils.h
|
||||
// NFT -> NFTokenUtils.h
|
||||
// Lending -> LendingHelpers.h
|
||||
// Keep reusable logic in helpers, transaction-specific logic in transactors
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never forget to register in `transactions.macro` and `applySteps.cpp`
|
||||
- Never access ledger state in preflight (no view available)
|
||||
- Never mutate state in preclaim (read-only view)
|
||||
- Always call `view().update(sle)` after modifying a peeked entry
|
||||
- Always gate on feature amendment for consensus safety
|
||||
- Use `NotTEC` return type from preflight, `TER` from preclaim/doApply
|
||||
- Put shared logic in a *Helpers.h file, not duplicated across transactors
|
||||
|
||||
## Key Files
|
||||
- `include/xrpl/tx/Transactor.h` - Base class definition
|
||||
- `src/libxrpl/tx/applySteps.cpp` - Transaction type dispatch
|
||||
- `include/xrpl/protocol/detail/transactions.macro` - Transaction type registry
|
||||
- `src/libxrpl/tx/InvariantCheck.cpp` - Post-apply validation
|
||||
68
.claude/skills/libxrpl/tx/transactors/AMM.md
Normal file
68
.claude/skills/libxrpl/tx/transactors/AMM.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# AMM (Automated Market Maker) Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with AMM transaction types in `src/libxrpl/tx/transactors/AMM/`. Covers pool creation, deposits, withdrawals, voting, bidding, deletion, and clawback.
|
||||
|
||||
## Responsibility
|
||||
Implements decentralized trading pools with liquidity provider (LP) tokens. Allows users to create AMM pools, deposit/withdraw liquidity, vote on trading fees, bid on auction slots, and manage pool lifecycle.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### AMM Transaction Types
|
||||
- **AMMCreate** - Create a new AMM pool with two assets
|
||||
- **AMMDeposit** - Add liquidity to a pool, receive LP tokens
|
||||
- **AMMWithdraw** - Remove liquidity, burn LP tokens
|
||||
- **AMMVote** - Vote on trading fee percentage
|
||||
- **AMMBid** - Bid on the auction slot for discounted trading
|
||||
- **AMMDelete** - Remove an empty AMM pool
|
||||
- **AMMClawback** - Issuer clawback of assets from AMM
|
||||
|
||||
### Precision Arithmetic
|
||||
```cpp
|
||||
// AMM calculations require controlled rounding
|
||||
// ALWAYS use NumberRoundModeGuard for rounding control
|
||||
NumberRoundModeGuard mg(Number::towards_zero);
|
||||
auto lpTokens = ammLPTokens(amount1, amount2, lptIssue);
|
||||
|
||||
// Or explicit mode changes with RAII save
|
||||
{
|
||||
saveNumberRoundMode _{Number::getround()};
|
||||
Number::setround(Number::upward);
|
||||
auto value = calculation;
|
||||
}
|
||||
```
|
||||
|
||||
### Helper Functions (AMMHelpers.h)
|
||||
```cpp
|
||||
ammLPTokens() // Calculate LP tokens from pool reserves
|
||||
lpTokensOut() // LP tokens from deposit
|
||||
ammAssetIn() / ammAssetOut() // Calculate swap amounts
|
||||
withinRelativeDistance() // Quality tolerance checks
|
||||
changeSpotPriceQuality() // Quote generation algorithm
|
||||
// Quadratic equation solving for pricing
|
||||
```
|
||||
|
||||
### Feature Gates
|
||||
```cpp
|
||||
// Multiple amendment versions
|
||||
ammEnabled(ctx.rules) // Base AMM feature
|
||||
fixAMMv1_1 // First fix amendment
|
||||
fixAMMv1_3 // Third fix amendment
|
||||
// Always check which amendments are active
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never perform AMM math without setting the rounding mode first
|
||||
- Always use `NumberRoundModeGuard` (RAII) - never manually set/restore rounding
|
||||
- Be aware that AMM calculations involve quadratic equations - precision matters
|
||||
- AMMClawback has different authorization requirements than regular clawback
|
||||
- Check `withinRelativeDistance` for quality tolerance rather than exact equality
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/AMM/AMMCreate.cpp` - Pool creation
|
||||
- `src/libxrpl/tx/transactors/AMM/AMMDeposit.cpp` - Liquidity deposit (~887 lines)
|
||||
- `src/libxrpl/tx/transactors/AMM/AMMWithdraw.cpp` - Liquidity withdrawal (~911 lines)
|
||||
- `src/libxrpl/tx/transactors/AMM/AMMVote.cpp` - Fee voting
|
||||
- `src/libxrpl/tx/transactors/AMM/AMMBid.cpp` - Auction slot bidding
|
||||
- `include/xrpl/tx/transactors/AMM/AMMHelpers.h` - Shared math utilities
|
||||
- `include/xrpl/tx/transactors/AMM/AMMUtils.h` - AMM state utilities
|
||||
44
.claude/skills/libxrpl/tx/transactors/Check.md
Normal file
44
.claude/skills/libxrpl/tx/transactors/Check.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Check Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with Check transaction types in `src/libxrpl/tx/transactors/Check/`. Covers check creation, cashing, and cancellation.
|
||||
|
||||
## Responsibility
|
||||
Implements a check-like payment mechanism (delayed payment authorization). A sender creates a check, the recipient cashes it, and either party can cancel it (with expiration support).
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Check Lifecycle
|
||||
```cpp
|
||||
// 1. CreateCheck - Sender authorizes payment
|
||||
// Validates: destination exists, amount valid, expiration future
|
||||
// Creates: Check ledger entry with sender, destination, amount
|
||||
|
||||
// 2. CashCheck - Recipient claims payment
|
||||
// Validates: caller is destination, check not expired
|
||||
// Executes: transfers funds from sender to destination
|
||||
|
||||
// 3. CancelCheck - Either party cancels
|
||||
// Validates: caller is sender or destination, or check expired
|
||||
// Removes: Check ledger entry
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
```cpp
|
||||
tecNO_DST // Destination account doesn't exist
|
||||
temREDUNDANT // Check to self
|
||||
temBAD_AMOUNT // Invalid amount
|
||||
temBAD_EXPIRATION // Expiration in the past
|
||||
tecEXPIRED // Check has expired (for CashCheck)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Checks can be cancelled by either sender or destination
|
||||
- Expired checks can be cancelled by anyone
|
||||
- CashCheck must handle both exact amount and "deliver minimum" modes
|
||||
- Always validate expiration against the parent ledger close time
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/Check/CreateCheck.cpp` - Check creation
|
||||
- `src/libxrpl/tx/transactors/Check/CashCheck.cpp` - Check fulfillment (~440 lines)
|
||||
- `src/libxrpl/tx/transactors/Check/CancelCheck.cpp` - Check cancellation
|
||||
43
.claude/skills/libxrpl/tx/transactors/Delegate.md
Normal file
43
.claude/skills/libxrpl/tx/transactors/Delegate.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Delegate Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with delegation transaction types in `src/libxrpl/tx/transactors/Delegate/`. Covers delegate set and utilities.
|
||||
|
||||
## Responsibility
|
||||
Manages transaction signing delegation, allowing accounts to authorize other accounts to sign transactions on their behalf without exposing the master key.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Delegate Operations
|
||||
```cpp
|
||||
// DelegateSet - Create or modify a delegation
|
||||
// Validates: delegate account exists, permissions valid
|
||||
// Creates/Updates: Delegate ledger entry
|
||||
|
||||
// DelegateUtils - Shared utilities
|
||||
// deleteDelegate() - Public cleanup interface, used by DeleteAccount
|
||||
```
|
||||
|
||||
### Feature Gates
|
||||
```cpp
|
||||
// fixDelegateV1_1 - Added data existence checks
|
||||
if (ctx.rules.enabled(fixDelegateV1_1)) {
|
||||
// Perform additional validation
|
||||
}
|
||||
```
|
||||
|
||||
### Integration with DeleteAccount
|
||||
```cpp
|
||||
// DelegateUtils::deleteDelegate() is called by DeleteAccount
|
||||
// for cleanup when an account is being deleted
|
||||
// Must handle all delegation-related ledger entries
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always check feature gate `fixDelegateV1_1` for data existence validation
|
||||
- Delegate cleanup must be thorough - used by DeleteAccount
|
||||
- Never allow self-delegation
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/Delegate/DelegateSet.cpp` - Delegation management
|
||||
- `include/xrpl/tx/transactors/Delegate/DelegateUtils.h` - Shared utilities
|
||||
69
.claude/skills/libxrpl/tx/transactors/Lending.md
Normal file
69
.claude/skills/libxrpl/tx/transactors/Lending.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Lending Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with lending protocol transaction types in `src/libxrpl/tx/transactors/Lending/`. Covers loan management, broker operations, and payment calculation.
|
||||
|
||||
## Responsibility
|
||||
Implements a complex loan protocol with amortization schedules, interest calculation, broker management, and collateral handling. The largest transactor feature area by code volume.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Loan Lifecycle
|
||||
```cpp
|
||||
// LoanSet - Create or configure a loan
|
||||
// LoanPay - Make loan payments (principal + interest)
|
||||
// LoanManage - Manage loan state transitions
|
||||
// LoanDelete - Remove a completed/cancelled loan
|
||||
```
|
||||
|
||||
### Broker Operations
|
||||
```cpp
|
||||
// LoanBrokerSet - Create/configure a broker
|
||||
// LoanBrokerDelete - Remove a broker
|
||||
// LoanBrokerCoverDeposit - Deposit collateral
|
||||
// LoanBrokerCoverWithdraw - Withdraw collateral
|
||||
// LoanBrokerCoverClawback - Clawback broker assets
|
||||
```
|
||||
|
||||
### Payment Calculation (LendingHelpers.h)
|
||||
```cpp
|
||||
struct LoanPaymentParts {
|
||||
Number principalPaid; // Reduces loan balance
|
||||
Number interestPaid; // Goes to Vault
|
||||
Number valueChange; // Loan value adjustment
|
||||
Number feePaid; // Goes to Broker
|
||||
};
|
||||
|
||||
// Key helper functions:
|
||||
checkLendingProtocolDependencies() // Validate feature gates
|
||||
loanPeriodicRate() // Interest with secondsInYear
|
||||
roundPeriodicPayment() // Consistent rounding
|
||||
```
|
||||
|
||||
### Feature Gate
|
||||
```cpp
|
||||
// All lending operations gated on single feature
|
||||
ctx.rules.enabled(featureLendingProtocol)
|
||||
```
|
||||
|
||||
### Batch Transaction Restriction
|
||||
```cpp
|
||||
// Lending transactions are DISABLED in batch transactions
|
||||
// Listed in Batch::disabledTxTypes
|
||||
// Cannot be included in atomic batch operations
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Lending is disabled in Batch transactions - do not try to batch lending ops
|
||||
- Payment calculations require precise rounding - use LendingHelpers functions
|
||||
- Always validate lending protocol dependencies before operations
|
||||
- Interest calculation uses `secondsInYear` constant - be aware of leap year handling
|
||||
- LendingHelpers.h is ~1800 lines - the most complex helper file in the codebase
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/Lending/LoanSet.cpp` - Loan configuration (~585 lines)
|
||||
- `src/libxrpl/tx/transactors/Lending/LoanPay.cpp` - Payment processing (~548 lines)
|
||||
- `src/libxrpl/tx/transactors/Lending/LoanManage.cpp` - State management
|
||||
- `src/libxrpl/tx/transactors/Lending/LoanDelete.cpp` - Loan removal
|
||||
- `src/libxrpl/tx/transactors/Lending/LoanBrokerSet.cpp` - Broker setup
|
||||
- `include/xrpl/tx/transactors/Lending/LendingHelpers.h` - Shared calculations (~1799 lines)
|
||||
53
.claude/skills/libxrpl/tx/transactors/MPT.md
Normal file
53
.claude/skills/libxrpl/tx/transactors/MPT.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# MPT (Multi-Purpose Token) Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with MPT transaction types in `src/libxrpl/tx/transactors/MPT/`. Covers token issuance creation, configuration, destruction, and authorization.
|
||||
|
||||
## Responsibility
|
||||
Implements Multi-Purpose Token (MPT) operations - a fungible token system simpler than full IOU trust lines. Handles token issuance lifecycle and holder authorization.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### MPT Transaction Types
|
||||
```cpp
|
||||
// MPTokenIssuanceCreate - Create a new token issuance
|
||||
// MPTokenIssuanceSet - Modify issuance settings
|
||||
// MPTokenIssuanceDestroy - Destroy an issuance (if no holders)
|
||||
// MPTokenAuthorize - Authorize/deauthorize a holder
|
||||
```
|
||||
|
||||
### MPT vs IOU Trust Lines
|
||||
```cpp
|
||||
// MPT is simpler than IOU trust lines:
|
||||
// - No rippling mechanics
|
||||
// - No transfer fees between holders (only issuer)
|
||||
// - Simpler authorization model
|
||||
// - Uses MPTIssue instead of Issue
|
||||
// - Uses MPTAmount instead of IOUAmount
|
||||
```
|
||||
|
||||
### Feature Gate
|
||||
```cpp
|
||||
ctx.rules.enabled(featureMPTokensV1)
|
||||
```
|
||||
|
||||
### Asset Variant Handling
|
||||
```cpp
|
||||
// MPTIssue is part of the Asset variant (Issue | MPTIssue)
|
||||
// Use std::visit when handling Asset generically:
|
||||
std::visit([&](auto const& issue) {
|
||||
// Works for both Issue and MPTIssue
|
||||
}, asset.value());
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- MPT issuances cannot be destroyed if any holders exist
|
||||
- Authorization is per-holder, not per-token
|
||||
- Don't confuse MPTIssue with Issue - they have different keylet types
|
||||
- Always check `featureMPTokensV1` before MPT operations
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/MPT/MPTokenIssuanceCreate.cpp` - Create issuance
|
||||
- `src/libxrpl/tx/transactors/MPT/MPTokenIssuanceSet.cpp` - Modify settings
|
||||
- `src/libxrpl/tx/transactors/MPT/MPTokenIssuanceDestroy.cpp` - Destroy issuance
|
||||
- `src/libxrpl/tx/transactors/MPT/MPTokenAuthorize.cpp` - Holder authorization
|
||||
76
.claude/skills/libxrpl/tx/transactors/NFT.md
Normal file
76
.claude/skills/libxrpl/tx/transactors/NFT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# NFT (Non-Fungible Token) Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with NFT transaction types in `src/libxrpl/tx/transactors/NFT/`. Covers minting, burning, offer management, and token modification.
|
||||
|
||||
## Responsibility
|
||||
Implements NFT creation, trading, and lifecycle management. Handles token minting, burning, buy/sell offer creation and acceptance, offer cancellation, and dynamic NFT modification.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### NFT Transaction Types
|
||||
```cpp
|
||||
// NFTokenMint - Create a new NFT
|
||||
// NFTokenBurn - Destroy an NFT
|
||||
// NFTokenCreateOffer - Create a buy or sell offer
|
||||
// NFTokenCancelOffer - Cancel an existing offer
|
||||
// NFTokenAcceptOffer - Accept a buy or sell offer (execute trade)
|
||||
// NFTokenModify - Modify NFT metadata (dynamic NFTs)
|
||||
```
|
||||
|
||||
### NFTokenUtils - Shared Utilities (~1025 lines)
|
||||
```cpp
|
||||
// Key utility functions:
|
||||
findToken() // Find an NFT in owner's token pages
|
||||
insertToken() // Add NFT to owner's directory
|
||||
removeToken() // Remove NFT from owner's directory
|
||||
deleteTokenOffer() // Clean up a single offer
|
||||
removeTokenOffersWithLimit() // Batch cleanup with limit
|
||||
notTooManyOffers() // Check offer count limits
|
||||
changeTokenURI() // Update NFT URI (dynamic NFTs)
|
||||
|
||||
struct TokenAndPage {
|
||||
STObject token;
|
||||
std::shared_ptr<SLE> page;
|
||||
};
|
||||
```
|
||||
|
||||
### Token Storage in Pages
|
||||
```cpp
|
||||
// NFTs are stored in paginated directories
|
||||
// Each page holds multiple tokens
|
||||
// Pages are linked as a doubly-linked list
|
||||
// insertToken/removeToken manage page splits and merges
|
||||
```
|
||||
|
||||
### Feature Gates
|
||||
```cpp
|
||||
featureNFTokenMintOffer // Combined mint + offer
|
||||
fixRemoveNFTokenAutoTrustLine // Fix for auto trust line removal
|
||||
featureDynamicNFT // NFTokenModify support
|
||||
```
|
||||
|
||||
### Offer Directory Structure
|
||||
```cpp
|
||||
// Buy offers and sell offers stored in separate directories
|
||||
// Indexed by token ID
|
||||
// Offers can have expiration times
|
||||
// Offers can specify a destination (private offers)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Token page management is complex - always use NFTokenUtils functions
|
||||
- Offer cleanup has limits (`removeTokenOffersWithLimit`) - don't assume all offers removed
|
||||
- `notTooManyOffers()` must be checked before creating new offers
|
||||
- Dynamic NFT modification requires `featureDynamicNFT` amendment
|
||||
- Transfer fees only apply when the NFT issuer is not a party to the trade
|
||||
- Burning an NFT with outstanding offers requires offer cleanup
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenMint.cpp` - Token minting
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenBurn.cpp` - Token destruction
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenCreateOffer.cpp` - Offer creation
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenAcceptOffer.cpp` - Offer acceptance (trade)
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenCancelOffer.cpp` - Offer cancellation
|
||||
- `src/libxrpl/tx/transactors/NFT/NFTokenModify.cpp` - Dynamic NFT changes
|
||||
- `include/xrpl/tx/transactors/NFT/NFTokenUtils.h` - Shared utilities (~1025 lines)
|
||||
56
.claude/skills/libxrpl/tx/transactors/Offer.md
Normal file
56
.claude/skills/libxrpl/tx/transactors/Offer.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Offer Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with DEX offer transaction types in `src/libxrpl/tx/transactors/Offer/`. Covers order creation and cancellation on the native decentralized exchange.
|
||||
|
||||
## Responsibility
|
||||
Implements decentralized exchange order management for the native XRPL order book. Handles offer creation (with matching/crossing), cancellation, and order book management.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Offer Transaction Types
|
||||
```cpp
|
||||
// CreateOffer (~854 lines) - Create a new DEX order
|
||||
// - Validates amounts, currency pairs, account state
|
||||
// - Attempts to cross with existing offers (matching engine)
|
||||
// - Remaining amount becomes a standing order if not fully filled
|
||||
// - Handles self-crossing, expired offers, unfunded offers
|
||||
|
||||
// CancelOffer - Remove an existing order
|
||||
// - Validates caller owns the offer
|
||||
// - Removes offer from order book directory
|
||||
```
|
||||
|
||||
### Offer Crossing (Matching Engine)
|
||||
```cpp
|
||||
// CreateOffer performs offer crossing inline:
|
||||
// 1. Look up existing offers on the opposite side
|
||||
// 2. Match at the offer's quality (exchange rate)
|
||||
// 3. Consume matched offers (partial or full)
|
||||
// 4. Place remaining amount as standing order
|
||||
// This is the core DEX matching engine
|
||||
```
|
||||
|
||||
### Quality and Order Books
|
||||
```cpp
|
||||
// Quality = exchange rate between TakerPays and TakerGets
|
||||
// Order books indexed by currency pair and sorted by quality
|
||||
// Lower quality number = better rate for taker
|
||||
```
|
||||
|
||||
### Ticket Support
|
||||
```cpp
|
||||
// Offers can use tickets for sequence management
|
||||
// Feature gate: featureTickets
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- CreateOffer is one of the most complex transactors (~854 lines) - be thorough with changes
|
||||
- Offer crossing modifies multiple ledger entries atomically
|
||||
- Self-crossing (same account on both sides) has special handling
|
||||
- Expired and unfunded offers are cleaned up during crossing
|
||||
- Always validate that TakerPays and TakerGets are different assets
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/Offer/CreateOffer.cpp` - Order creation and matching (~854 lines)
|
||||
- `src/libxrpl/tx/transactors/Offer/CancelOffer.cpp` - Order cancellation
|
||||
36
.claude/skills/libxrpl/tx/transactors/PermissionedDomain.md
Normal file
36
.claude/skills/libxrpl/tx/transactors/PermissionedDomain.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# PermissionedDomain Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with permissioned domain transaction types in `src/libxrpl/tx/transactors/PermissionedDomain/`. Covers domain-based access control for the DEX.
|
||||
|
||||
## Responsibility
|
||||
Implements domain-based access control for permissioned DEX operations. Allows creating and deleting permissioned domains that gate who can participate in certain trading activities.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### PermissionedDomain Transaction Types
|
||||
```cpp
|
||||
// PermissionedDomainSet - Create or update a permissioned domain
|
||||
// PermissionedDomainDelete - Remove a permissioned domain
|
||||
```
|
||||
|
||||
### Integration with Payments
|
||||
```cpp
|
||||
// Payments can reference a domain via sfDomainID field
|
||||
// The domain gates which accounts can participate
|
||||
// Used for regulated/permissioned trading environments
|
||||
```
|
||||
|
||||
### Feature Gate
|
||||
```cpp
|
||||
ctx.rules.enabled(featurePermissionedDEX)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Domains are referenced by other transactions (Payments) - deletion must check for references
|
||||
- Always validate the feature gate before domain operations
|
||||
- Domain ID matching is exact - no partial matches
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/PermissionedDomain/PermissionedDomainSet.cpp` - Create/update domain
|
||||
- `src/libxrpl/tx/transactors/PermissionedDomain/PermissionedDomainDelete.cpp` - Remove domain
|
||||
61
.claude/skills/libxrpl/tx/transactors/Vault.md
Normal file
61
.claude/skills/libxrpl/tx/transactors/Vault.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Vault Transactors Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with vault transaction types in `src/libxrpl/tx/transactors/Vault/`. Covers vault creation, configuration, deposits, withdrawals, deletion, and clawback.
|
||||
|
||||
## Responsibility
|
||||
Implements the vault mechanism for asset holding and loan collateral management. Allows creating vaults, depositing/withdrawing assets, configuring vault parameters, and managing vault lifecycle.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Vault Transaction Types
|
||||
```cpp
|
||||
// VaultCreate - Create a new vault
|
||||
// VaultSet - Configure vault parameters
|
||||
// VaultDelete - Remove an empty vault
|
||||
// VaultDeposit - Deposit assets into a vault
|
||||
// VaultWithdraw - Withdraw assets from a vault
|
||||
// VaultClawback - Issuer clawback from vault
|
||||
```
|
||||
|
||||
### Feature Gate
|
||||
```cpp
|
||||
ctx.rules.enabled(featureSingleAssetVault)
|
||||
```
|
||||
|
||||
### Batch Transaction Restriction
|
||||
```cpp
|
||||
// Vault transactions are DISABLED in batch transactions
|
||||
// Listed in Batch::disabledTxTypes alongside Lending
|
||||
// Cannot be included in atomic batch operations
|
||||
```
|
||||
|
||||
### Depth Limiting for Recursive Operations
|
||||
```cpp
|
||||
// Vault operations may involve recursive state checks
|
||||
// Use depth parameter to prevent infinite recursion
|
||||
TER checkVaultState(ReadView const& view, AccountID const& id, int depth = 0);
|
||||
if (depth > maxDepth) return tecINTERNAL;
|
||||
```
|
||||
|
||||
### Integration with Lending
|
||||
```cpp
|
||||
// Vaults serve as collateral for the lending protocol
|
||||
// VaultDeposit/Withdraw affect loan collateralization
|
||||
// Vault state changes may trigger loan state recalculation
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Vault operations are disabled in batch transactions
|
||||
- Vaults can only be deleted when empty
|
||||
- Clawback has different authorization requirements than regular withdrawal
|
||||
- Always respect depth limits in recursive vault state checks
|
||||
- Vault operations may interact with lending protocol state
|
||||
|
||||
## Key Files
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultCreate.cpp` - Vault creation
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultSet.cpp` - Configuration
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultDelete.cpp` - Deletion
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultDeposit.cpp` - Asset deposit
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultWithdraw.cpp` - Asset withdrawal
|
||||
- `src/libxrpl/tx/transactors/Vault/VaultClawback.cpp` - Issuer clawback
|
||||
228
.claude/skills/merge-conflicts.md
Normal file
228
.claude/skills/merge-conflicts.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# Merge Conflict Resolution Guide
|
||||
|
||||
## Description
|
||||
Use when resolving merge conflicts after merging `develop` into a feature branch. Covers the key files that commonly conflict, field number allocation, namespace conventions, and the correct resolution strategy for each file type.
|
||||
|
||||
## General Principles
|
||||
|
||||
### Namespace
|
||||
- All code uses `namespace xrpl { }` (not `ripple`). If a conflict shows `namespace ripple`, take the `xrpl` version.
|
||||
- Qualified references: `xrpl::sign(...)`, `xrpl::sha256_hasher`, etc. Never `ripple::`.
|
||||
|
||||
### Header Guards
|
||||
- Always `#pragma once`. Never `#ifndef` include guards. If a conflict shows old-style guards, take the `#pragma once` version.
|
||||
|
||||
### Copyright Headers
|
||||
- The `develop` branch has removed copyright/license comment blocks from source files. If a conflict is just about the copyright header, take `develop`'s version (no header).
|
||||
|
||||
### File Moves
|
||||
- Many files have been moved from `src/xrpld/` to `src/libxrpl/` or from `src/xrpld/` headers to `include/xrpl/`. If git shows a file as "deleted in develop" but it exists at a new path, delete the old-path file (`git rm`) and keep the new-path version.
|
||||
- Common moves:
|
||||
- `src/xrpld/app/tx/detail/*.h` → `include/xrpl/tx/transactors/*.h`
|
||||
- `src/xrpld/app/tx/detail/*.cpp` → `src/libxrpl/tx/*.cpp` or `src/libxrpl/tx/transactors/*.cpp`
|
||||
- `src/xrpld/app/tx/detail/InvariantCheck.cpp` → `src/libxrpl/tx/invariants/InvariantCheck.cpp`
|
||||
|
||||
### Transactor Migration
|
||||
When merging transactors from `src/xrpld/app/tx/detail/` into `develop`, they must be fully migrated to the new libxrpl structure:
|
||||
|
||||
**File locations:**
|
||||
- Header: `src/xrpld/app/tx/detail/Foo.h` → `include/xrpl/tx/transactors/Foo.h`
|
||||
- Source: `src/xrpld/app/tx/detail/Foo.cpp` → `src/libxrpl/tx/transactors/Foo.cpp`
|
||||
- Delete the old `.cpp` (both `src/xrpld/` and `src/libxrpl/` are GLOB_RECURSE discovered — duplicates cause linker errors)
|
||||
- Optionally leave a forwarding header at the old `.h` location: `#include <xrpl/tx/transactors/Foo.h>`
|
||||
|
||||
**Header changes:**
|
||||
- `#pragma once` (not `#ifndef` guards)
|
||||
- `namespace xrpl` (not `ripple`)
|
||||
- `#include <xrpl/tx/Transactor.h>` (not `<xrpld/app/tx/detail/Transactor.h>`)
|
||||
|
||||
**Source changes:**
|
||||
- `namespace xrpl` (not `ripple`)
|
||||
- `#include <xrpl/tx/transactors/Foo.h>` (not `<xrpld/app/tx/detail/Foo.h>`)
|
||||
- `#include <xrpl/ledger/ApplyView.h>` (not `<xrpld/ledger/ApplyView.h>`)
|
||||
- `#include <xrpl/ledger/View.h>` for `describeOwnerDir`
|
||||
|
||||
**API changes in the new Transactor:**
|
||||
- `preflight1()` and `preflight2()` are **private** — transactor `preflight()` must NOT call them. The framework calls them automatically.
|
||||
- Flag checking (`tfUniversalMask`) is handled by the framework via `getFlagsMask()`. Override `getFlagsMask()` only if custom flag handling is needed; otherwise the default handles `tfUniversalMask`.
|
||||
- A simple `preflight()` that only did flag checks + preflight1/preflight2 should just `return tesSUCCESS;`
|
||||
- `ctx_.app.journal(...)` → `ctx_.registry.journal(...)`
|
||||
- `ctx_.app` does not exist in the new `ApplyContext`; use `ctx_.registry` for service access
|
||||
|
||||
**transactions.macro entry:**
|
||||
Every transactor must have a `#if TRANSACTION_INCLUDE` block:
|
||||
```cpp
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/Foo.h>
|
||||
#endif
|
||||
TRANSACTION(ttFOO, <number>, Foo, ...)
|
||||
```
|
||||
|
||||
### Include Paths
|
||||
- `develop` uses the new macro-based transactor include system via `transactions.macro` with `TRANSACTION_INCLUDE`. Old-style explicit `#include <xrpld/app/tx/detail/*.h>` lists should be replaced with the macro approach.
|
||||
|
||||
## File-Specific Resolution Rules
|
||||
|
||||
### `include/xrpl/protocol/detail/features.macro`
|
||||
|
||||
New feature amendments go **at the top** of the active list (below the macro guard checks and `// clang-format off`), in reverse chronological order.
|
||||
|
||||
```
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(MyNewFeature, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExistingFix, Supported::yes, VoteBehavior::DefaultNo)
|
||||
...
|
||||
```
|
||||
|
||||
Resolution: Keep both sides' new amendments. Place your feature branch's new amendments at the very top.
|
||||
|
||||
### `include/xrpl/protocol/detail/sfields.macro`
|
||||
|
||||
Fields are grouped by type (UINT32, UINT64, UINT128, etc.) with common and uncommon sections. Each field has a unique **type + field number** pair.
|
||||
|
||||
**Resolution strategy:**
|
||||
1. Keep both sides' new fields.
|
||||
2. Check for field number collisions within each type. Use the next available number for your feature's fields.
|
||||
3. Common fields come first, uncommon fields after (there's a comment separator).
|
||||
|
||||
To find the next available field number for a type:
|
||||
```bash
|
||||
grep "TYPED_SFIELD.*UINT32" include/xrpl/protocol/detail/sfields.macro | sed 's/.*UINT32, *//;s/).*//' | sort -n
|
||||
```
|
||||
|
||||
Similarly for OBJECT and ARRAY types (using `UNTYPED_SFIELD`):
|
||||
```bash
|
||||
grep "UNTYPED_SFIELD.*OBJECT" include/xrpl/protocol/detail/sfields.macro | sed 's/.*OBJECT, *//;s/).*//' | sort -n
|
||||
grep "UNTYPED_SFIELD.*ARRAY" include/xrpl/protocol/detail/sfields.macro | sed 's/.*ARRAY, *//;s/).*//' | sort -n
|
||||
```
|
||||
|
||||
### `include/xrpl/protocol/detail/transactions.macro`
|
||||
|
||||
Transaction types have a unique **transaction type number**. New feature transactions go **at the bottom** of the active transaction list (before the system transactions starting at 100+).
|
||||
|
||||
**Resolution strategy:**
|
||||
1. Keep all of `develop`'s transactions.
|
||||
2. Add your feature's transactions at the bottom with the next available number.
|
||||
3. Use the new 7-argument `TRANSACTION` macro format:
|
||||
|
||||
```cpp
|
||||
/** Description of the transaction */
|
||||
#if TRANSACTION_INCLUDE
|
||||
# include <xrpl/tx/transactors/MyTransactor.h>
|
||||
#endif
|
||||
TRANSACTION(ttMY_TX, <next_number>, MyTx,
|
||||
Delegation::delegable,
|
||||
featureMyFeature,
|
||||
noPriv, ({
|
||||
{sfSomeField, soeREQUIRED},
|
||||
}))
|
||||
```
|
||||
|
||||
To find the next available transaction number:
|
||||
```bash
|
||||
grep "^TRANSACTION(" include/xrpl/protocol/detail/transactions.macro | sed 's/.*,\s*\([0-9]*\),.*/\1/' | sort -n
|
||||
```
|
||||
|
||||
Note: Transaction numbers 100+ are reserved for system transactions (amendments, fees, UNL).
|
||||
|
||||
### `include/xrpl/protocol/detail/ledger_entries.macro`
|
||||
|
||||
Ledger entry types have a unique **ledger type number** (hex). New entries go **at the bottom** of the active list.
|
||||
|
||||
**Resolution strategy:**
|
||||
1. Keep all of `develop`'s entries.
|
||||
2. Add your feature's entries at the bottom with the next available hex number.
|
||||
3. Check for collisions:
|
||||
|
||||
```bash
|
||||
grep "^LEDGER_ENTRY(" include/xrpl/protocol/detail/ledger_entries.macro | grep -o '0x[0-9a-fA-F]*' | sort
|
||||
```
|
||||
|
||||
### `src/libxrpl/protocol/Indexes.cpp`
|
||||
|
||||
The `LedgerNameSpace` enum assigns a unique single character to each ledger entry type for index hashing.
|
||||
|
||||
**Resolution strategy:**
|
||||
1. Keep both sides' entries.
|
||||
2. Check for character collisions. Each entry needs a unique char.
|
||||
3. Find used characters:
|
||||
|
||||
```bash
|
||||
grep -E "^\s+[A-Z_]+ = " src/libxrpl/protocol/Indexes.cpp | sed "s/.*= '//;s/'.*//" | sort | tr -d '\n'
|
||||
```
|
||||
|
||||
Also check the deprecated chars (reserved, cannot reuse):
|
||||
```bash
|
||||
grep "deprecated" src/libxrpl/protocol/Indexes.cpp | sed "s/.*= '//;s/'.*//"
|
||||
```
|
||||
|
||||
### `src/libxrpl/protocol/InnerObjectFormats.cpp`
|
||||
|
||||
Inner object formats define the fields allowed inside array elements (e.g., `sfSigners`, `sfPasskeys`).
|
||||
|
||||
**Resolution:** Keep both sides' `add(...)` calls. No numbering conflicts here — just ensure no duplicate registrations.
|
||||
|
||||
### `src/libxrpl/protocol/STTx.cpp`
|
||||
|
||||
The `singleSignHelper` function was refactored in `develop`:
|
||||
- Parameter name: `sigObject` (not `signer`)
|
||||
- Signature retrieval: `sigObject.getFieldVL(sfTxnSignature)` (not `getSignature(signer)`)
|
||||
- No `fullyCanonical` parameter — canonical sig checking was simplified
|
||||
|
||||
**Resolution:** Take `develop`'s function signatures and patterns. Adapt any feature-specific logic to match.
|
||||
|
||||
### `src/libxrpl/protocol/SecretKey.cpp`
|
||||
|
||||
**Resolution:** Use `namespace xrpl`. Keep any additional `#include` directives your feature needs (e.g., OpenSSL headers for new key types).
|
||||
|
||||
### `src/libxrpl/tx/Transactor.cpp`
|
||||
|
||||
The `checkSign` / `checkSingleSign` / `checkMultiSign` functions were refactored in `develop`:
|
||||
- `checkSingleSign` no longer takes a `Rules` parameter
|
||||
- `checkSign` has a new overload taking `PreclaimContext`
|
||||
- `checkBatchSign` uses the simplified `checkSingleSign` call
|
||||
|
||||
**Resolution:** Take `develop`'s function signatures. Add any new authentication checks (e.g., passkey verification) into `checkSingleSign` before the final `return tefBAD_AUTH`, using `view.read(...)` to check ledger state.
|
||||
|
||||
### `src/libxrpl/tx/applySteps.cpp`
|
||||
|
||||
**Resolution:** Always take `develop`'s macro-based include approach:
|
||||
```cpp
|
||||
#include <xrpl/tx/applySteps.h>
|
||||
#pragma push_macro("TRANSACTION")
|
||||
#undef TRANSACTION
|
||||
|
||||
#define TRANSACTION(...)
|
||||
#define TRANSACTION_INCLUDE 1
|
||||
|
||||
#include <xrpl/protocol/detail/transactions.macro>
|
||||
|
||||
#undef TRANSACTION
|
||||
#pragma pop_macro("TRANSACTION")
|
||||
```
|
||||
|
||||
Never use the old explicit `#include <xrpld/app/tx/detail/*.h>` list.
|
||||
|
||||
### `src/test/jtx/impl/utility.cpp`
|
||||
|
||||
The `sign` function was refactored in `develop`:
|
||||
- Takes `sigObject` parameter: `sign(Json::Value& jv, Account const& account, Json::Value& sigObject)`
|
||||
- Has an overload: `sign(Json::Value& jv, Account const& account)` that calls `sign(jv, account, jv)`
|
||||
- Uses `xrpl::sign(...)` not `ripple::sign(...)`
|
||||
|
||||
**Resolution:** Take `develop`'s function signatures. Adapt feature-specific signing logic to the new pattern.
|
||||
|
||||
## Conflict Resolution Checklist
|
||||
|
||||
1. List all conflicted files: `git diff --name-only --diff-filter=U`
|
||||
2. Check which have actual conflict markers vs just unmerged: `grep -l "<<<<<<< HEAD" <file>`
|
||||
3. For files without markers: stage them or `git rm` if they were moved
|
||||
4. For each file with markers:
|
||||
- Take `develop`'s structural changes (namespace, function signatures, macro formats)
|
||||
- Preserve your feature's additions (new fields, entries, transactions, logic)
|
||||
- Resolve any numbering collisions by incrementing to the next available number
|
||||
5. Stage resolved files: `git add <file>`
|
||||
6. Verify no remaining markers: `grep -r "<<<<<<< " --include="*.cpp" --include="*.h" --include="*.macro"`
|
||||
7. Verify no remaining unmerged: `git diff --name-only --diff-filter=U`
|
||||
57
.claude/skills/xrpld/app.md
Normal file
57
.claude/skills/xrpld/app.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# App Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with the main application layer in `src/xrpld/app/`. Covers the Application singleton, ledger management, consensus adapters, services, and runtime coordination.
|
||||
|
||||
## Responsibility
|
||||
Contains the main application logic and runtime coordination for the rippled server. The Application singleton provides access to all services. Sub-modules handle ledger management, consensus, fee voting, amendments, path finding, and transaction queuing.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Application Singleton
|
||||
```cpp
|
||||
// Application is the master interface - access all services through it
|
||||
class Application {
|
||||
virtual Config& config() = 0;
|
||||
virtual Logs& logs() = 0;
|
||||
virtual JobQueue& getJobQueue() = 0;
|
||||
virtual LedgerMaster& getLedgerMaster() = 0;
|
||||
virtual NetworkOPs& getOPs() = 0;
|
||||
virtual NodeStore::Database& getNodeStore() = 0;
|
||||
// ... many more service accessors
|
||||
};
|
||||
// Implemented by ApplicationImp (hidden in .cpp)
|
||||
```
|
||||
|
||||
### ServiceRegistry Pattern
|
||||
```cpp
|
||||
// Services are injected via ServiceRegistry from libxrpl
|
||||
// Application provides centralized access to all registered services
|
||||
```
|
||||
|
||||
### Master Mutex
|
||||
```cpp
|
||||
// Recursive mutex protects shared state:
|
||||
using MutexType = std::recursive_mutex;
|
||||
// Protects: open ledger, server state, consensus engine
|
||||
// Use std::lock_guard<Application::MutexType> for access
|
||||
```
|
||||
|
||||
### Module Interface Pattern
|
||||
```cpp
|
||||
// Public interface: Module.h (abstract)
|
||||
// Implementation: ModuleImp.h/cpp (hidden)
|
||||
// Factory: make_Module() returns unique_ptr
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never access Application services before setup() completes
|
||||
- Always acquire master mutex when modifying open ledger or consensus state
|
||||
- Use `std::recursive_mutex` (not plain mutex) - multiple services may lock re-entrantly
|
||||
- Never create a second Application instance
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/main/Application.h` - Core application interface
|
||||
- `src/xrpld/app/main/Application.cpp` - Implementation (150+ includes)
|
||||
- `src/xrpld/app/main/BasicApp.h` - Base application services
|
||||
- `src/xrpld/app/main/GRPCServer.h` - gRPC server integration
|
||||
47
.claude/skills/xrpld/app/consensus.md
Normal file
47
.claude/skills/xrpld/app/consensus.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# App Consensus Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with RCL consensus adapters in `src/xrpld/app/consensus/`. Bridges the generic consensus algorithm to rippled-specific types.
|
||||
|
||||
## Responsibility
|
||||
Adapts the generic consensus algorithm (in `xrpld/consensus/`) to work with rippled application types. Provides concrete type adapters for transactions, transaction sets, and ledgers.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### RCL Adapters
|
||||
```cpp
|
||||
// RCLCxTx - Adapts SHAMapItem as a consensus transaction
|
||||
// RCLCxTxSet - Adapts SHAMap as a consensus transaction set
|
||||
// RCLCxLedger - Adapts Ledger as a consensus ledger
|
||||
// RCLConsensus - Glues generic consensus to rippled Application
|
||||
```
|
||||
|
||||
### Adapter Pattern
|
||||
```cpp
|
||||
// Generic consensus works with abstract types via CRTP
|
||||
// RCL adapters provide concrete implementations
|
||||
class RCLConsensus : public Consensus<RCLConsensus> {
|
||||
// Implements required methods using rippled types
|
||||
// e.g., acquireLedger(), proposeTx(), relay()
|
||||
};
|
||||
```
|
||||
|
||||
### Validation Handling
|
||||
```cpp
|
||||
// RCLValidations tracks validation messages from the network
|
||||
// Maps to the generic Validations<> template
|
||||
// Handles trusted vs untrusted validators
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Adapter methods must match the CRTP interface exactly - compiler errors are cryptic
|
||||
- Never import generic consensus types into adapter code - always go through the adapter
|
||||
- RCLConsensus holds references to Application services - ensure Application outlives it
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/consensus/RCLConsensus.h` - Main consensus orchestrator
|
||||
- `src/xrpld/app/consensus/RCLConsensus.cpp` - Implementation
|
||||
- `src/xrpld/app/consensus/RCLValidations.h` - Validation handling
|
||||
- `src/xrpld/app/consensus/RCLCxTx.h` - Transaction adapter
|
||||
- `src/xrpld/app/consensus/RCLCxTxSet.h` - Transaction set adapter
|
||||
- `src/xrpld/app/consensus/RCLCxLedger.h` - Ledger adapter
|
||||
67
.claude/skills/xrpld/app/ledger.md
Normal file
67
.claude/skills/xrpld/app/ledger.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# App Ledger Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with ledger management in `src/xrpld/app/ledger/`. Covers ledger storage, retrieval, history, and the Ledger class itself.
|
||||
|
||||
## Responsibility
|
||||
Manages the lifecycle of ledger objects: creation, storage, retrieval, history tracking, inbound acquisition from network, and order book caching. The Ledger class is the central data structure.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Ledger Class
|
||||
```cpp
|
||||
// Ledger is composed of two SHAMaps:
|
||||
// 1. State Map - Account roots, order books, ledger entries (STLedgerEntry)
|
||||
// 2. Transaction Map - Transactions and metadata for that ledger
|
||||
|
||||
class Ledger final : public std::enable_shared_from_this<Ledger>,
|
||||
public CountedObject<Ledger> {
|
||||
// Can be mutable (sole ownership) or immutable (shared, read-only)
|
||||
// Genesis ledger has special constructor
|
||||
};
|
||||
```
|
||||
|
||||
### Mutable vs Immutable
|
||||
```cpp
|
||||
// Mutable: Only one owner, can be modified
|
||||
// Immutable: Shared via shared_ptr, read-only
|
||||
// Transition: mutable -> immutable when accepted
|
||||
// Never modify an immutable ledger
|
||||
```
|
||||
|
||||
### LedgerMaster
|
||||
```cpp
|
||||
// Manages the chain of validated ledgers
|
||||
// Tracks: current, validated, closed ledgers
|
||||
// Handles ledger transitions during consensus
|
||||
```
|
||||
|
||||
### Inbound Ledger Acquisition
|
||||
```cpp
|
||||
// InboundLedgers manages acquiring missing ledgers from peers
|
||||
// InboundTransactions handles transaction set acquisition
|
||||
// Both use async fetch with timeout and retry
|
||||
```
|
||||
|
||||
### Iterator Adapters
|
||||
```cpp
|
||||
// sles_iter_impl - Iterate over SLE (state entries)
|
||||
// txs_iter_impl - Iterate over transactions
|
||||
// Efficient iteration without copying
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never modify an immutable ledger - check mutability first
|
||||
- Ledger must be shared via shared_ptr (enable_shared_from_this)
|
||||
- Genesis ledger construction is special - don't use for normal ledgers
|
||||
- LedgerMaster state transitions must be atomic with consensus
|
||||
- CountedObject tracking helps detect leaks - don't disable it
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/ledger/Ledger.h` - Core ledger class
|
||||
- `src/xrpld/app/ledger/LedgerMaster.h` - Ledger chain management
|
||||
- `src/xrpld/app/ledger/LedgerHistory.h` - Historical tracking
|
||||
- `src/xrpld/app/ledger/LedgerCleaner.h` - Online deletion
|
||||
- `src/xrpld/app/ledger/InboundLedgers.h` - Network acquisition
|
||||
- `src/xrpld/app/ledger/OrderBookDB.h` - Order book cache
|
||||
- `src/xrpld/app/ledger/TransactionMaster.h` - Transaction lookup
|
||||
18
.claude/skills/xrpld/app/ledger/detail.md
Normal file
18
.claude/skills/xrpld/app/ledger/detail.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# App Ledger Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with ledger implementation details in `src/xrpld/app/ledger/detail/`. Internal helpers for the ledger module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for the app/ledger module. Contains private helpers for ledger state management, iteration, and storage operations.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Detail Namespace Convention
|
||||
- Code in `detail/` is internal to the `app/ledger` module
|
||||
- Never include detail headers from outside `app/ledger`
|
||||
- If you need functionality, use the public `app/ledger/` headers instead
|
||||
|
||||
## Common Pitfalls
|
||||
- Detail implementations may change without API compatibility
|
||||
- Never expose detail types in public interfaces
|
||||
54
.claude/skills/xrpld/app/main.md
Normal file
54
.claude/skills/xrpld/app/main.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# App Main Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application initialization and lifecycle in `src/xrpld/app/main/`. Covers Application startup, shutdown, and core services.
|
||||
|
||||
## Responsibility
|
||||
Application initialization, lifecycle management, and core service wiring. Contains the Application interface and its implementation, gRPC server, load management, node identity, and the node store scheduler.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Application Lifecycle
|
||||
```cpp
|
||||
// 1. Construct Application (parse config, create services)
|
||||
// 2. setup() - Initialize all services, open databases
|
||||
// 3. run() - Main event loop
|
||||
// 4. signalStop() - Graceful shutdown
|
||||
// 5. Destructor - Clean up resources
|
||||
```
|
||||
|
||||
### Node Identity
|
||||
```cpp
|
||||
// NodeIdentity manages the node's public/private key pair
|
||||
// Used for peer handshake, session signatures, and cluster membership
|
||||
// Keys persisted in wallet_db
|
||||
```
|
||||
|
||||
### Load Manager
|
||||
```cpp
|
||||
// Tracks server load across all subsystems
|
||||
// Triggers load-based fee escalation
|
||||
// Monitors job queue depth and execution time
|
||||
```
|
||||
|
||||
### gRPC Server
|
||||
```cpp
|
||||
// Optional gRPC server alongside JSON-RPC
|
||||
// Uses proto definitions from include/xrpl/proto/
|
||||
// Separate handler set from JSON-RPC
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- setup() must complete before any service is used
|
||||
- signalStop() should be called for graceful shutdown - avoid hard kills
|
||||
- Node identity keys must never be logged or exposed
|
||||
- Load manager affects fee escalation - test under load
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/main/Application.h` - Core interface
|
||||
- `src/xrpld/app/main/Application.cpp` - Implementation
|
||||
- `src/xrpld/app/main/BasicApp.h` - Base services
|
||||
- `src/xrpld/app/main/GRPCServer.h` - gRPC integration
|
||||
- `src/xrpld/app/main/LoadManager.h` - Load tracking
|
||||
- `src/xrpld/app/main/NodeIdentity.h` - Node key management
|
||||
- `src/xrpld/app/main/NodeStoreScheduler.h` - Async DB scheduler
|
||||
75
.claude/skills/xrpld/app/misc.md
Normal file
75
.claude/skills/xrpld/app/misc.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# App Misc Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application services in `src/xrpld/app/misc/`. Covers fee voting, amendments, SHAMapStore, transaction queue, validator management, and NetworkOPs.
|
||||
|
||||
## Responsibility
|
||||
Collection of application-level services: fee voting system, amendment mechanism, online deletion (SHAMapStore), transaction queue (TxQ), validator key/list management, and NetworkOPs (the central operations coordinator).
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Fee Voting
|
||||
```cpp
|
||||
// Validators vote on fee schedules every 256 ledgers ("voting ledgers")
|
||||
// Pseudo-transactions injected to set fees
|
||||
// Majority vote determines new fee schedule
|
||||
// FeeVote.h - voting logic
|
||||
// FeeEscalation.md - escalation documentation
|
||||
```
|
||||
|
||||
### Amendment Mechanism
|
||||
```cpp
|
||||
// Network-wide ledger rule changes
|
||||
// Requires 80% validator approval sustained for 2 weeks
|
||||
// Tracked as pseudo-transactions in each ledger
|
||||
// AmendmentTableImpl.h manages tracking and state
|
||||
```
|
||||
|
||||
### SHAMapStore (Online Delete)
|
||||
```cpp
|
||||
// Prunes old ledger history automatically
|
||||
// Uses rotation between two databases
|
||||
// Configurable deletion intervals
|
||||
// Must not delete data needed for active operations
|
||||
```
|
||||
|
||||
### Transaction Queue (TxQ)
|
||||
```cpp
|
||||
// Queues transactions when ledger is full
|
||||
// Priority based on fee level
|
||||
// Handles fee escalation under load
|
||||
// TxQ.h - queue implementation
|
||||
```
|
||||
|
||||
### Validator Management
|
||||
```cpp
|
||||
// ValidatorKeys.h - Node's own validator keys
|
||||
// ValidatorList.h - Trusted validator list (UNL)
|
||||
// ValidatorSite.h - Sites serving validator lists
|
||||
// Keys loaded from config, lists fetched from URLs
|
||||
```
|
||||
|
||||
### NetworkOPs
|
||||
```cpp
|
||||
// Central operations coordinator - the "god object"
|
||||
// Coordinates: consensus, ledger acceptance, transaction submission
|
||||
// NetworkOPs.cpp is one of the largest files in the codebase
|
||||
// Access via app.getOPs()
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Fee voting only happens on voting ledgers (every 256) - don't trigger manually
|
||||
- Amendments require 2-week sustained 80% approval - no fast path
|
||||
- SHAMapStore deletion must respect the advisory_delete safety window
|
||||
- TxQ priority depends on current fee escalation level
|
||||
- NetworkOPs is massive - changes here affect many systems
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/misc/FeeVote.h` - Fee voting system
|
||||
- `src/xrpld/app/misc/AmendmentTableImpl.h` - Amendment tracking
|
||||
- `src/xrpld/app/misc/SHAMapStore.h` - Online deletion
|
||||
- `src/xrpld/app/misc/TxQ.h` - Transaction queue
|
||||
- `src/xrpld/app/misc/ValidatorKeys.h` - Validator key management
|
||||
- `src/xrpld/app/misc/ValidatorList.h` - Trusted validator list
|
||||
- `src/xrpld/app/misc/NetworkOPs.cpp` - Central operations
|
||||
- `src/xrpld/app/misc/README.md` - Architecture documentation
|
||||
18
.claude/skills/xrpld/app/misc/detail.md
Normal file
18
.claude/skills/xrpld/app/misc/detail.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# App Misc Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with internal service implementation details in `src/xrpld/app/misc/detail/`. Internal helpers for the misc services module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for app/misc services (fee voting internals, amendment table implementation, SHAMapStore internals, etc.).
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Detail Namespace Convention
|
||||
- Code in `detail/` is internal to the `app/misc` module
|
||||
- Implementation classes (e.g., AmendmentTableImpl) live here
|
||||
- Never include detail headers from outside `app/misc`
|
||||
|
||||
## Common Pitfalls
|
||||
- Detail implementations may change without API compatibility
|
||||
- Always use the public `app/misc/` interfaces
|
||||
53
.claude/skills/xrpld/app/paths.md
Normal file
53
.claude/skills/xrpld/app/paths.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# App Paths Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with payment path finding in `src/xrpld/app/paths/`. Covers the path finding algorithm, trust line caching, and AMM liquidity integration.
|
||||
|
||||
## Responsibility
|
||||
Implements the XRP Ledger payment path finding algorithm at the application level. Manages path requests, trust line caching, and integration with Automated Market Maker liquidity.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Path Finding
|
||||
```cpp
|
||||
// Pathfinder: Algorithm that finds payment paths between accounts
|
||||
// Considers: trust lines, order books, AMM pools
|
||||
// Returns: Set of paths ranked by cost/quality
|
||||
```
|
||||
|
||||
### Path Request Management
|
||||
```cpp
|
||||
// PathRequest - Individual path find request
|
||||
// PathRequests - Manages collection of active requests
|
||||
// Requests can be one-shot or subscribed (streaming updates)
|
||||
```
|
||||
|
||||
### Trust Line Caching
|
||||
```cpp
|
||||
// RippleLineCache caches trust line data
|
||||
// Avoids repeated ledger lookups during path finding
|
||||
// Cache is invalidated on ledger close
|
||||
// TrustLine.h provides the trust line representation
|
||||
```
|
||||
|
||||
### AMM Integration
|
||||
```cpp
|
||||
// AMMLiquidity.h - Integrates AMM pools into path finding
|
||||
// AMMOffer.h - Represents AMM as a synthetic offer
|
||||
// AMM pools are treated as a special offer type in the path finder
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Path finding is computationally expensive - respect search depth limits
|
||||
- Trust line cache must be invalidated on ledger close
|
||||
- AMM liquidity changes with pool state - don't cache AMM offers across ledgers
|
||||
- Path subscriptions can be memory-intensive with many clients
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/paths/Pathfinder.h` - Path finding algorithm
|
||||
- `src/xrpld/app/paths/PathRequest.h` - Individual request handling
|
||||
- `src/xrpld/app/paths/PathRequests.h` - Request collection management
|
||||
- `src/xrpld/app/paths/RippleLineCache.h` - Trust line caching
|
||||
- `src/xrpld/app/paths/TrustLine.h` - Trust line representation
|
||||
- `src/xrpld/app/paths/AMMLiquidity.h` - AMM pool integration
|
||||
- `src/xrpld/app/paths/AMMOffer.h` - Synthetic AMM offers
|
||||
18
.claude/skills/xrpld/app/paths/detail.md
Normal file
18
.claude/skills/xrpld/app/paths/detail.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# App Paths Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with path finding implementation details in `src/xrpld/app/paths/detail/`. Internal helpers for the path finding module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for the path finding algorithm, including search heuristics, cost calculation helpers, and internal data structures.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Detail Namespace Convention
|
||||
- Code in `detail/` is internal to the `app/paths` module
|
||||
- Contains algorithm-specific helpers not needed by callers
|
||||
- Never include detail headers from outside `app/paths`
|
||||
|
||||
## Common Pitfalls
|
||||
- Path finding internals are performance-sensitive - profile before modifying
|
||||
- Detail implementations may change without API compatibility
|
||||
39
.claude/skills/xrpld/app/rdb.md
Normal file
39
.claude/skills/xrpld/app/rdb.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# App RDB Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application-level database operations in `src/xrpld/app/rdb/`. Covers database abstractions and backend implementations.
|
||||
|
||||
## Responsibility
|
||||
Application-level relational database operations. Provides interfaces for peer finding data storage, SQLite backend implementation, and database operation details.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Interface-Based Design
|
||||
```cpp
|
||||
// PeerFinder.h - Abstract interface for peer data storage
|
||||
// Backend implementations in backend/ subdirectory
|
||||
// Allows swapping database backends without changing callers
|
||||
```
|
||||
|
||||
### SQLite Backend
|
||||
```cpp
|
||||
// SQLiteDatabase.h - Primary backend implementation
|
||||
// Uses SOCI wrapper from libxrpl/rdb
|
||||
// Handles: peer data, transaction history, ledger metadata
|
||||
```
|
||||
|
||||
### Backend Abstraction
|
||||
```cpp
|
||||
// backend/ directory contains concrete implementations
|
||||
// backend/detail/ has implementation-specific helpers
|
||||
// detail/ has shared implementation details
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always use the abstract interface, not the SQLite backend directly
|
||||
- Database operations should be off the main thread (use job queue)
|
||||
- Respect the SOCI wrapper patterns from libxrpl/rdb
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/rdb/PeerFinder.h` - Peer data interface
|
||||
- `src/xrpld/app/rdb/backend/SQLiteDatabase.h` - SQLite implementation
|
||||
31
.claude/skills/xrpld/app/rdb/backend.md
Normal file
31
.claude/skills/xrpld/app/rdb/backend.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# App RDB Backend Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with database backend implementations in `src/xrpld/app/rdb/backend/`. Covers concrete database implementations.
|
||||
|
||||
## Responsibility
|
||||
Concrete database backend implementations for the app/rdb module. Primary implementation is SQLiteDatabase.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### SQLiteDatabase
|
||||
```cpp
|
||||
// Primary backend implementation using SQLite via SOCI
|
||||
// Handles: peer storage, transaction history, ledger metadata
|
||||
// Thread-safe via session-per-thread pattern from libxrpl/rdb
|
||||
```
|
||||
|
||||
### Backend Detail
|
||||
```cpp
|
||||
// backend/detail/ contains SQLite-specific helpers
|
||||
// Schema creation, migration, and optimization queries
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always use parameterized queries via SOCI - never raw string SQL
|
||||
- Database files can grow large - implement periodic VACUUM
|
||||
- WAL checkpoint scheduling prevents unbounded WAL growth
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/rdb/backend/SQLiteDatabase.h` - SQLite implementation
|
||||
- `src/xrpld/app/rdb/backend/detail/` - SQLite-specific helpers
|
||||
11
.claude/skills/xrpld/app/rdb/backend/detail.md
Normal file
11
.claude/skills/xrpld/app/rdb/backend/detail.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# App RDB Backend Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with database backend implementation details in `src/xrpld/app/rdb/backend/detail/`. SQLite-specific internal helpers.
|
||||
|
||||
## Responsibility
|
||||
SQLite-specific implementation details: schema definitions, migration scripts, query optimization, and SOCI binding helpers.
|
||||
|
||||
## Common Pitfalls
|
||||
- Schema migrations must be backwards-compatible
|
||||
- Never include these headers from outside the rdb/backend module
|
||||
18
.claude/skills/xrpld/app/rdb/detail.md
Normal file
18
.claude/skills/xrpld/app/rdb/detail.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# App RDB Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with database implementation details in `src/xrpld/app/rdb/detail/`. Internal helpers for the relational database module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for app-level database operations, including SQL query helpers and schema management.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Detail Namespace Convention
|
||||
- Code in `detail/` is internal to the `app/rdb` module
|
||||
- Contains SQL query construction and result parsing helpers
|
||||
- Never include detail headers from outside `app/rdb`
|
||||
|
||||
## Common Pitfalls
|
||||
- SQL queries must use parameterized bindings (SOCI style) - never string concatenation
|
||||
- Detail implementations may change without API compatibility
|
||||
34
.claude/skills/xrpld/app/tx.md
Normal file
34
.claude/skills/xrpld/app/tx.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# App Tx Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application-level transaction handling in `src/xrpld/app/tx/`. Covers transaction submission, validation, and application-layer processing.
|
||||
|
||||
## Responsibility
|
||||
Application-level transaction handling that bridges the protocol-layer transaction processing (libxrpl/tx) with the running server. Handles transaction submission, validation, and integration with the consensus process.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Relationship to libxrpl/tx
|
||||
```cpp
|
||||
// libxrpl/tx: Protocol-level transaction processing (Transactor, preflight, preclaim, doApply)
|
||||
// xrpld/app/tx: Application-level orchestration (submission, queuing, consensus integration)
|
||||
// This module calls into libxrpl/tx for actual transaction execution
|
||||
```
|
||||
|
||||
### Transaction Submission Flow
|
||||
```cpp
|
||||
// 1. Client submits transaction via RPC
|
||||
// 2. app/tx validates and queues transaction
|
||||
// 3. Transaction enters TxQ (app/misc/TxQ)
|
||||
// 4. Consensus selects transactions for next ledger
|
||||
// 5. libxrpl/tx executes selected transactions
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Don't duplicate transaction validation logic - defer to libxrpl/tx
|
||||
- Application-level checks (queue depth, fee escalation) happen here, not in libxrpl
|
||||
- Transaction metadata is generated at this level after execution
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/app/tx/` - Application transaction handling
|
||||
- `src/xrpld/app/tx/detail/` - Implementation details
|
||||
11
.claude/skills/xrpld/app/tx/detail.md
Normal file
11
.claude/skills/xrpld/app/tx/detail.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# App Tx Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application transaction handling details in `src/xrpld/app/tx/detail/`. Internal helpers for transaction submission and processing.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for application-level transaction handling, including submission validation, queue integration, and metadata generation.
|
||||
|
||||
## Common Pitfalls
|
||||
- Don't duplicate libxrpl/tx validation logic here
|
||||
- Detail implementations may change without API compatibility
|
||||
59
.claude/skills/xrpld/consensus.md
Normal file
59
.claude/skills/xrpld/consensus.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Consensus Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with the generic consensus algorithm in `src/xrpld/consensus/`. This is the application-independent consensus implementation.
|
||||
|
||||
## Responsibility
|
||||
Implements the generic consensus algorithm separate from application-specific types. Uses CRTP (Curiously Recurring Template Pattern) to allow the application layer to plug in concrete types without virtual dispatch overhead.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### CRTP Design
|
||||
```cpp
|
||||
// Generic consensus uses CRTP - derived class provides concrete types
|
||||
template <class Derived>
|
||||
class Consensus {
|
||||
// Calls static_cast<Derived*>(this)->method() for app-specific behavior
|
||||
// No virtual dispatch overhead
|
||||
};
|
||||
|
||||
// Application adapter:
|
||||
class RCLConsensus : public Consensus<RCLConsensus> {
|
||||
// Provides concrete types: RCLCxTx, RCLCxTxSet, RCLCxLedger
|
||||
};
|
||||
```
|
||||
|
||||
### Consensus Phases
|
||||
```cpp
|
||||
// Open -> Establish -> Accept
|
||||
// Open: Collecting transactions
|
||||
// Establish: Proposing and voting on transaction set
|
||||
// Accept: Applying agreed-upon transaction set to ledger
|
||||
```
|
||||
|
||||
### Consensus Parameters (ConsensusParms.h)
|
||||
```cpp
|
||||
// Timing parameters for consensus rounds
|
||||
// These are tuned for network behavior - don't change without careful analysis
|
||||
```
|
||||
|
||||
### Disputed Transactions
|
||||
```cpp
|
||||
// DisputedTx tracks transactions where validators disagree
|
||||
// Votes are collected and transaction is included/excluded based on threshold
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Never modify consensus parameters without understanding network-wide impact
|
||||
- CRTP means compilation errors from type mismatches appear in template instantiation - read errors carefully
|
||||
- The generic consensus module should NEVER depend on application-specific types (Ledger, STTx, etc.)
|
||||
- Always test consensus changes with multi-node simulation
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/consensus/Consensus.h` - Main consensus class (extensively documented)
|
||||
- `src/xrpld/consensus/ConsensusParms.h` - Timing parameters
|
||||
- `src/xrpld/consensus/ConsensusProposal.h` - Proposal structures
|
||||
- `src/xrpld/consensus/DisputedTx.h` - Transaction dispute tracking
|
||||
- `src/xrpld/consensus/LedgerTiming.h` - Ledger timing calculations
|
||||
- `src/xrpld/consensus/LedgerTrie.h` - Transaction set representation
|
||||
- `src/xrpld/consensus/Validations.h` - Generic validation tracking
|
||||
55
.claude/skills/xrpld/core.md
Normal file
55
.claude/skills/xrpld/core.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Core Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with core configuration and system services in `src/xrpld/core/`. Covers Config, time keeping, and network identity.
|
||||
|
||||
## Responsibility
|
||||
System-level configuration and core services. The Config class extends BasicConfig from libxrpl with rippled-specific settings. Provides time keeping and network ID management.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Config Class
|
||||
```cpp
|
||||
// Config extends BasicConfig from libxrpl
|
||||
class Config : public BasicConfig {
|
||||
// SizedItem enum for memory-dependent configuration
|
||||
enum SizedItem { siSweepInterval, siNodeCacheSize, ... };
|
||||
|
||||
// FeeSetup for fee parameters
|
||||
struct FeeSetup {
|
||||
XRPAmount reference_fee;
|
||||
XRPAmount account_reserve;
|
||||
XRPAmount owner_reserve;
|
||||
};
|
||||
|
||||
// Access sections by name
|
||||
auto const& section = config["server"];
|
||||
};
|
||||
```
|
||||
|
||||
### Configuration Sections
|
||||
```cpp
|
||||
// Section names defined in ConfigSections.h
|
||||
static constexpr char const* SECTION_NODE_DB = "node_db";
|
||||
static constexpr char const* SECTION_VALIDATORS = "validators";
|
||||
// Always use constants, never string literals
|
||||
```
|
||||
|
||||
### Gradual Refactoring
|
||||
```cpp
|
||||
// Legacy config uses mixed patterns - refactoring is ongoing
|
||||
// New code should follow the Section-based approach
|
||||
// Deprecated patterns are documented with TODO comments
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always use `ConfigSections.h` constants for section names
|
||||
- Config extends BasicConfig - check both for available methods
|
||||
- SizedItem values scale with node size configuration - don't hardcode sizes
|
||||
- Never modify Config after Application startup
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/core/Config.h` - Configuration object
|
||||
- `src/xrpld/core/ConfigSections.h` - Section name constants
|
||||
- `src/xrpld/core/TimeKeeper.h` - System time tracking
|
||||
- `src/xrpld/core/NetworkIDServiceImpl.h` - Network ID implementation
|
||||
11
.claude/skills/xrpld/core/detail.md
Normal file
11
.claude/skills/xrpld/core/detail.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Core Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with core configuration implementation details in `src/xrpld/core/detail/`. Internal helpers for the Config system.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for the core configuration module, including config parsing helpers and platform-specific abstractions.
|
||||
|
||||
## Common Pitfalls
|
||||
- Never include detail headers from outside the core module
|
||||
- Config parsing must handle all edge cases gracefully (missing sections, invalid values)
|
||||
74
.claude/skills/xrpld/overlay.md
Normal file
74
.claude/skills/xrpld/overlay.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Overlay Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with P2P networking in `src/xrpld/overlay/`. Covers peer connections, protocol negotiation, message relay, and clustering.
|
||||
|
||||
## Responsibility
|
||||
Manages peer-to-peer connections and the overlay network protocol. Handles HTTP/1.1 upgrade handshake, session signatures (MITM prevention), Protocol Buffer message serialization, message compression, and cluster node management.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### HTTP/1.1 Upgrade Handshake
|
||||
```cpp
|
||||
// Connection starts as HTTP, upgrades to ripple protocol
|
||||
// Custom headers:
|
||||
// Connect-As, Public-Key, Session-Signature
|
||||
// Network-ID, Network-Time
|
||||
// Closed-Ledger, Previous-Ledger
|
||||
// Remote-IP, Local-IP, Crawl
|
||||
```
|
||||
|
||||
### Session Signature (MITM Prevention)
|
||||
```cpp
|
||||
// Binds SSL/TLS session to node identities
|
||||
// Each peer signs the shared SSL session data
|
||||
// Prevents man-in-the-middle attacks at the protocol level
|
||||
```
|
||||
|
||||
### Message Serialization
|
||||
```cpp
|
||||
// Google Protocol Buffers for all p2p messages
|
||||
// Messages are compressed before transmission
|
||||
// Compression.h handles LZ4/no-compression selection
|
||||
```
|
||||
|
||||
### Peer Management
|
||||
```cpp
|
||||
// Overlay manages the set of connected peers
|
||||
class Overlay {
|
||||
virtual Peer::ptr findPeerByShortID(Peer::id_t) = 0;
|
||||
virtual void send(std::shared_ptr<Message> const&) = 0; // Broadcast
|
||||
virtual void relay(Message const&, uint256 const& suppression) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
### Clustering
|
||||
```cpp
|
||||
// Multiple rippled nodes can form a cluster
|
||||
// Cluster nodes: share load, distribute crypto operations
|
||||
// Cluster membership verified via node public keys
|
||||
```
|
||||
|
||||
### Reduce Relay
|
||||
```cpp
|
||||
// ReduceRelayCommon.h - Minimize redundant message relay
|
||||
// Uses HashRouter for message deduplication
|
||||
// Peers track which messages they've already seen
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always validate session signatures during handshake - never skip
|
||||
- Never send uncompressed messages to peers that advertise compression support
|
||||
- Cluster keys must be pre-configured - no dynamic cluster joining
|
||||
- Message suppression via HashRouter is critical for network health - never bypass
|
||||
- Protocol Buffer messages must match the expected schema version
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/overlay/Overlay.h` - Main overlay manager interface
|
||||
- `src/xrpld/overlay/Peer.h` - Peer connection representation
|
||||
- `src/xrpld/overlay/PeerSet.h` - Collection of peers
|
||||
- `src/xrpld/overlay/Cluster.h` - Cluster management
|
||||
- `src/xrpld/overlay/Message.h` - Message structure
|
||||
- `src/xrpld/overlay/Compression.h` - Message compression
|
||||
- `src/xrpld/overlay/ReduceRelayCommon.h` - Relay optimization
|
||||
- `src/xrpld/overlay/README.md` - Comprehensive protocol documentation
|
||||
27
.claude/skills/xrpld/overlay/detail.md
Normal file
27
.claude/skills/xrpld/overlay/detail.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Overlay Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with P2P networking implementation details in `src/xrpld/overlay/detail/`. Internal helpers for the overlay module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for the overlay networking layer, including protocol message handling, peer connection state machines, and handshake implementation.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### PeerImp
|
||||
```cpp
|
||||
// PeerImp is the concrete implementation of the Peer interface
|
||||
// Manages: SSL connection, protocol state, message queuing
|
||||
// Uses enable_shared_from_this for async callback safety
|
||||
```
|
||||
|
||||
### OverlayImpl
|
||||
```cpp
|
||||
// OverlayImpl is the concrete implementation of Overlay
|
||||
// Manages: listening sockets, peer lifecycle, broadcast
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Peer connection state machine transitions must be atomic
|
||||
- Never access PeerImp internals from outside overlay/detail/
|
||||
- Message queuing must respect back-pressure limits
|
||||
58
.claude/skills/xrpld/peerfinder.md
Normal file
58
.claude/skills/xrpld/peerfinder.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# PeerFinder Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with network discovery in `src/xrpld/peerfinder/`. Covers peer bootstrap, cache management, and connection slot strategy.
|
||||
|
||||
## Responsibility
|
||||
Bootstraps into the XRP Ledger network and discovers peers. Manages bootcache (persistent addresses ranked by success), livecache (ephemeral recently-seen peers), and connection slot allocation.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Three-Stage Connection Strategy
|
||||
```cpp
|
||||
// Stage 1: Connect to fixed peers (configured addresses)
|
||||
// Stage 2: Try Livecache addresses (recently seen, with open slots)
|
||||
// Stage 3: Fall back to Bootcache (persistent, ranked by valence)
|
||||
```
|
||||
|
||||
### Bootcache (Persistent)
|
||||
```cpp
|
||||
// Persistent store of peer addresses ranked by "valence" (connection success)
|
||||
// Higher valence = more reliable peer
|
||||
// Persisted across restarts
|
||||
// Used as fallback when livecache is empty
|
||||
```
|
||||
|
||||
### Livecache (Ephemeral)
|
||||
```cpp
|
||||
// Recently seen peers with available connection slots
|
||||
// Uses hop counts for distance estimation
|
||||
// Random distribution for load balancing
|
||||
// Not persisted - rebuilt on restart via gossip
|
||||
```
|
||||
|
||||
### Slot Management
|
||||
```cpp
|
||||
// Slot states: accept, connect, connected, active, closing
|
||||
// Slot properties: Inbound/Outbound, Fixed, Cluster
|
||||
// Slots track connection lifecycle from handshake to disconnect
|
||||
```
|
||||
|
||||
### Callback Pattern
|
||||
```cpp
|
||||
// Abstract interface for socket operations
|
||||
// PeerFinder doesn't directly manage sockets
|
||||
// Delegates I/O to the overlay layer via callbacks
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Fixed peers should always be tried first (Stage 1) - they are trusted
|
||||
- Bootcache valence can decay over time - implement proper aging
|
||||
- Livecache entries expire quickly - don't rely on stale data
|
||||
- Slot limits prevent connection exhaustion - never bypass them
|
||||
- Always check README.md for algorithm details before modifying
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/peerfinder/PeerfinderManager.h` - Main manager interface
|
||||
- `src/xrpld/peerfinder/Slot.h` - Connection slot representation
|
||||
- `src/xrpld/peerfinder/README.md` - Extensive design documentation
|
||||
21
.claude/skills/xrpld/peerfinder/detail.md
Normal file
21
.claude/skills/xrpld/peerfinder/detail.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# PeerFinder Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with peer discovery implementation details in `src/xrpld/peerfinder/detail/`. Internal helpers for the peerfinder module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for peer discovery: bootcache persistence, livecache management, slot state machine, and connection strategy implementation.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Logic Class
|
||||
```cpp
|
||||
// The main implementation class for peer finding
|
||||
// Implements the three-stage connection strategy
|
||||
// Manages bootcache and livecache state
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Bootcache persistence must be atomic to prevent corruption
|
||||
- Livecache expiration must be checked on every access
|
||||
- Never include detail headers from outside peerfinder/
|
||||
31
.claude/skills/xrpld/perflog.md
Normal file
31
.claude/skills/xrpld/perflog.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# PerfLog Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with performance logging in `src/xrpld/perflog/`. Covers performance instrumentation and metric collection.
|
||||
|
||||
## Responsibility
|
||||
Performance logging and instrumentation for the rippled server. Tracks timing data, throughput metrics, and operational statistics for monitoring and debugging.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Performance Logging Interface
|
||||
```cpp
|
||||
// Abstract interface for performance data collection
|
||||
// Implementations can log to file, export to monitoring systems, etc.
|
||||
// Enabled/disabled via configuration
|
||||
```
|
||||
|
||||
### Detail Namespace
|
||||
```cpp
|
||||
// Implementation details in detail/ subdirectory
|
||||
// Not part of public API
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Performance logging should have minimal overhead when disabled
|
||||
- Never log sensitive data (keys, balances) in performance logs
|
||||
- Ensure timestamps use consistent clock sources
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/perflog/` - Performance logging implementation
|
||||
- `src/xrpld/perflog/detail/` - Implementation details
|
||||
11
.claude/skills/xrpld/perflog/detail.md
Normal file
11
.claude/skills/xrpld/perflog/detail.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# PerfLog Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with performance logging implementation details in `src/xrpld/perflog/detail/`. Internal helpers for the perflog module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for performance logging, including metric collection, formatting, and output management.
|
||||
|
||||
## Common Pitfalls
|
||||
- Performance logging overhead must be minimal when disabled
|
||||
- Never include detail headers from outside perflog/
|
||||
91
.claude/skills/xrpld/rpc.md
Normal file
91
.claude/skills/xrpld/rpc.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# RPC Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with RPC request handling in `src/xrpld/rpc/`. Covers command dispatch, handler implementation, coroutine suspension, and the gRPC interface.
|
||||
|
||||
## Responsibility
|
||||
HTTP/JSON and gRPC RPC interface to rippled. Dispatches requests to 40+ command handlers, manages request context, supports coroutine-based suspension for async operations, and handles user roles/permissions.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### RPC Handler Pattern
|
||||
```cpp
|
||||
// Each handler is a function taking context, returning Json::Value
|
||||
Json::Value doMyCommand(RPC::JsonContext& context) {
|
||||
// Validate parameters
|
||||
if (!context.params.isMember("field"))
|
||||
return RPC::missing_field_error("field");
|
||||
|
||||
// Access application services
|
||||
auto& app = context.app;
|
||||
|
||||
// Build response
|
||||
Json::Value result(Json::objectValue);
|
||||
result["status"] = "success";
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
### Coroutine Suspension
|
||||
```cpp
|
||||
// RPC handlers can suspend for async operations
|
||||
// Key types:
|
||||
// Callback - 0-argument function
|
||||
// Continuation - Takes callback, promises to call it later
|
||||
// Suspend - Function from coroutine that takes continuation
|
||||
// Coroutine - Function given suspend to enable suspension
|
||||
|
||||
// This allows handlers to yield without blocking threads
|
||||
```
|
||||
|
||||
### Request Context
|
||||
```cpp
|
||||
struct JsonContext {
|
||||
Application& app;
|
||||
Resource::Charge& loadType;
|
||||
Json::Value params;
|
||||
beast::Journal j;
|
||||
Role role; // User, Admin, Identified, etc.
|
||||
};
|
||||
```
|
||||
|
||||
### Role-Based Access
|
||||
```cpp
|
||||
enum class Role { GUEST, USER, ADMIN, IDENTIFIED, PROXY, FORBID };
|
||||
// Handlers specify minimum required role
|
||||
// Admin handlers only accessible from admin IP ranges
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
```cpp
|
||||
// Standard error helpers:
|
||||
RPC::missing_field_error("field_name");
|
||||
RPC::invalid_field_error("field_name");
|
||||
RPC::make_error(rpcINVALID_PARAMS, "description");
|
||||
// Errors injected into JSON response
|
||||
```
|
||||
|
||||
### gRPC Handlers
|
||||
```cpp
|
||||
// Separate handler set for gRPC interface
|
||||
// Defined in GRPCHandlers.h
|
||||
// Use Protocol Buffer request/response types
|
||||
// Convert to/from native types at boundary
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always validate parameters before accessing them
|
||||
- Check user Role before executing privileged operations
|
||||
- Use coroutine suspension for any operation that might block
|
||||
- Never return internal data structures directly - always convert to JSON
|
||||
- Handler functions are in `handlers/` directory - one file per command or group
|
||||
- gRPC handlers must convert proto types to native types at the boundary
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/rpc/RPCHandler.h` - Command dispatcher
|
||||
- `src/xrpld/rpc/Context.h` - RPC context/state
|
||||
- `src/xrpld/rpc/Status.h` - RPC status codes
|
||||
- `src/xrpld/rpc/Role.h` - User role/permissions
|
||||
- `src/xrpld/rpc/GRPCHandlers.h` - gRPC integration
|
||||
- `src/xrpld/rpc/handlers/` - Individual command handlers (40+)
|
||||
- `src/xrpld/rpc/README.md` - Coroutine documentation
|
||||
11
.claude/skills/xrpld/rpc/detail.md
Normal file
11
.claude/skills/xrpld/rpc/detail.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# RPC Detail Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with RPC implementation details in `src/xrpld/rpc/detail/`. Internal helpers for the RPC module.
|
||||
|
||||
## Responsibility
|
||||
Internal implementation details for RPC handling, including request parsing, response formatting, coroutine machinery, and middleware.
|
||||
|
||||
## Common Pitfalls
|
||||
- Coroutine state must be carefully managed to prevent leaks
|
||||
- Never include detail headers from outside rpc/
|
||||
74
.claude/skills/xrpld/rpc/handlers.md
Normal file
74
.claude/skills/xrpld/rpc/handlers.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# RPC Handlers Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when adding or modifying RPC command handlers in `src/xrpld/rpc/handlers/`. Contains 40+ individual RPC command implementations.
|
||||
|
||||
## Responsibility
|
||||
Individual RPC command handler implementations. Each file implements one or more related RPC commands following the standard handler pattern.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Handler Function Signature
|
||||
```cpp
|
||||
// Standard handler pattern
|
||||
Json::Value doMyCommand(RPC::JsonContext& context) {
|
||||
// 1. Validate parameters
|
||||
if (!context.params.isMember("required_field"))
|
||||
return RPC::missing_field_error("required_field");
|
||||
|
||||
// 2. Check permissions
|
||||
// (Role already verified by dispatcher based on handler metadata)
|
||||
|
||||
// 3. Access application services
|
||||
auto& app = context.app;
|
||||
auto& ledger = context.ledgerMaster.getValidatedLedger();
|
||||
|
||||
// 4. Execute logic
|
||||
// ...
|
||||
|
||||
// 5. Build and return response
|
||||
Json::Value result(Json::objectValue);
|
||||
result["status"] = "success";
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
### Parameter Validation
|
||||
```cpp
|
||||
// Use standard error helpers
|
||||
RPC::missing_field_error("field_name"); // Required field missing
|
||||
RPC::invalid_field_error("field_name"); // Field has wrong type/value
|
||||
RPC::make_error(rpcINVALID_PARAMS, "description"); // Generic error
|
||||
```
|
||||
|
||||
### Adding a New Handler
|
||||
1. Create a new .cpp file in `handlers/`
|
||||
2. Implement the handler function following the pattern above
|
||||
3. Register the command in the handler dispatch table
|
||||
4. Document the command parameters and response format
|
||||
|
||||
### Common Handler Files
|
||||
```
|
||||
AccountInfo.cpp - account_info command
|
||||
AccountLines.cpp - account_lines (trust lines)
|
||||
AccountOffers.cpp - account_offers
|
||||
Submit.cpp - submit (transaction submission)
|
||||
Subscribe.cpp - subscribe (event streaming)
|
||||
LedgerData.cpp - ledger_data
|
||||
ServerInfo.cpp - server_info
|
||||
Fee1.cpp - fee command
|
||||
Tx.cpp - tx (transaction lookup)
|
||||
BookOffers.cpp - book_offers (order book)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always validate ALL parameters before using them
|
||||
- Never return internal data structures - convert to JSON at the boundary
|
||||
- Respect Role-based access control - admin handlers must check role
|
||||
- Handlers should be stateless - all state comes from context
|
||||
- Use coroutine suspension for any blocking operation (DB queries, network)
|
||||
- Error responses must follow the standard error format
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/rpc/handlers/` - All handler implementations
|
||||
- `src/xrpld/rpc/RPCHandler.h` - Dispatch table and registration
|
||||
32
.claude/skills/xrpld/shamap.md
Normal file
32
.claude/skills/xrpld/shamap.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# SHAMap (xrpld) Module Best Practices
|
||||
|
||||
## Description
|
||||
Use when working with application-level SHAMap operations in `src/xrpld/shamap/`. Covers NodeFamily and application integration with the Merkle tree.
|
||||
|
||||
## Responsibility
|
||||
Application-level integration of the SHAMap (Merkle radix tree) with the rippled server. Provides NodeFamily for managing tree node relationships and connecting the generic SHAMap to the node store.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### NodeFamily
|
||||
```cpp
|
||||
// NodeFamily connects SHAMap to the persistent NodeStore
|
||||
// Provides: database access, tree node creation, hash verification
|
||||
// Each SHAMap references a Family for storage operations
|
||||
```
|
||||
|
||||
### Relationship to libxrpl/shamap
|
||||
```cpp
|
||||
// libxrpl/shamap: Generic Merkle tree implementation
|
||||
// xrpld/shamap: Application-specific integration (NodeFamily, storage)
|
||||
// The generic tree doesn't know about databases - NodeFamily bridges the gap
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
- Always use NodeFamily to create SHAMap instances connected to storage
|
||||
- The libxrpl SHAMap is the implementation - this module is the glue layer
|
||||
- Don't duplicate SHAMap logic here - extend via NodeFamily only
|
||||
|
||||
## Key Files
|
||||
- `src/xrpld/shamap/NodeFamily.h` - Family relationship management
|
||||
- `src/xrpld/shamap/NodeFamily.cpp` - Implementation
|
||||
247
.cmake-format.yaml
Normal file
247
.cmake-format.yaml
Normal file
@@ -0,0 +1,247 @@
|
||||
_help_parse: Options affecting listfile parsing
|
||||
parse:
|
||||
_help_additional_commands:
|
||||
- Specify structure for custom cmake functions
|
||||
additional_commands:
|
||||
target_protobuf_sources:
|
||||
pargs:
|
||||
- target
|
||||
- prefix
|
||||
kwargs:
|
||||
PROTOS: "*"
|
||||
LANGUAGE: cpp
|
||||
IMPORT_DIRS: "*"
|
||||
GENERATE_EXTENSIONS: "*"
|
||||
PLUGIN: "*"
|
||||
_help_override_spec:
|
||||
- Override configurations per-command where available
|
||||
override_spec: {}
|
||||
_help_vartags:
|
||||
- Specify variable tags.
|
||||
vartags: []
|
||||
_help_proptags:
|
||||
- Specify property tags.
|
||||
proptags: []
|
||||
_help_format: Options affecting formatting.
|
||||
format:
|
||||
_help_disable:
|
||||
- Disable formatting entirely, making cmake-format a no-op
|
||||
disable: false
|
||||
_help_line_width:
|
||||
- How wide to allow formatted cmake files
|
||||
line_width: 120
|
||||
_help_tab_size:
|
||||
- How many spaces to tab for indent
|
||||
tab_size: 4
|
||||
_help_use_tabchars:
|
||||
- If true, lines are indented using tab characters (utf-8
|
||||
- 0x09) instead of <tab_size> space characters (utf-8 0x20).
|
||||
- In cases where the layout would require a fractional tab
|
||||
- character, the behavior of the fractional indentation is
|
||||
- governed by <fractional_tab_policy>
|
||||
use_tabchars: false
|
||||
_help_fractional_tab_policy:
|
||||
- If <use_tabchars> is True, then the value of this variable
|
||||
- indicates how fractional indentions are handled during
|
||||
- whitespace replacement. If set to 'use-space', fractional
|
||||
- indentation is left as spaces (utf-8 0x20). If set to
|
||||
- "`round-up` fractional indentation is replaced with a single"
|
||||
- tab character (utf-8 0x09) effectively shifting the column
|
||||
- to the next tabstop
|
||||
fractional_tab_policy: use-space
|
||||
_help_max_subgroups_hwrap:
|
||||
- If an argument group contains more than this many sub-groups
|
||||
- (parg or kwarg groups) then force it to a vertical layout.
|
||||
max_subgroups_hwrap: 4
|
||||
_help_max_pargs_hwrap:
|
||||
- If a positional argument group contains more than this many
|
||||
- arguments, then force it to a vertical layout.
|
||||
max_pargs_hwrap: 5
|
||||
_help_max_rows_cmdline:
|
||||
- If a cmdline positional group consumes more than this many
|
||||
- lines without nesting, then invalidate the layout (and nest)
|
||||
max_rows_cmdline: 2
|
||||
_help_separate_ctrl_name_with_space:
|
||||
- If true, separate flow control names from their parentheses
|
||||
- with a space
|
||||
separate_ctrl_name_with_space: true
|
||||
_help_separate_fn_name_with_space:
|
||||
- If true, separate function names from parentheses with a
|
||||
- space
|
||||
separate_fn_name_with_space: false
|
||||
_help_dangle_parens:
|
||||
- If a statement is wrapped to more than one line, than dangle
|
||||
- the closing parenthesis on its own line.
|
||||
dangle_parens: false
|
||||
_help_dangle_align:
|
||||
- If the trailing parenthesis must be 'dangled' on its on
|
||||
- "line, then align it to this reference: `prefix`: the start"
|
||||
- "of the statement, `prefix-indent`: the start of the"
|
||||
- "statement, plus one indentation level, `child`: align to"
|
||||
- the column of the arguments
|
||||
dangle_align: prefix
|
||||
_help_min_prefix_chars:
|
||||
- If the statement spelling length (including space and
|
||||
- parenthesis) is smaller than this amount, then force reject
|
||||
- nested layouts.
|
||||
min_prefix_chars: 18
|
||||
_help_max_prefix_chars:
|
||||
- If the statement spelling length (including space and
|
||||
- parenthesis) is larger than the tab width by more than this
|
||||
- amount, then force reject un-nested layouts.
|
||||
max_prefix_chars: 10
|
||||
_help_max_lines_hwrap:
|
||||
- If a candidate layout is wrapped horizontally but it exceeds
|
||||
- this many lines, then reject the layout.
|
||||
max_lines_hwrap: 2
|
||||
_help_line_ending:
|
||||
- What style line endings to use in the output.
|
||||
line_ending: unix
|
||||
_help_command_case:
|
||||
- Format command names consistently as 'lower' or 'upper' case
|
||||
command_case: canonical
|
||||
_help_keyword_case:
|
||||
- Format keywords consistently as 'lower' or 'upper' case
|
||||
keyword_case: unchanged
|
||||
_help_always_wrap:
|
||||
- A list of command names which should always be wrapped
|
||||
always_wrap: []
|
||||
_help_enable_sort:
|
||||
- If true, the argument lists which are known to be sortable
|
||||
- will be sorted lexicographicall
|
||||
enable_sort: true
|
||||
_help_autosort:
|
||||
- If true, the parsers may infer whether or not an argument
|
||||
- list is sortable (without annotation).
|
||||
autosort: true
|
||||
_help_require_valid_layout:
|
||||
- By default, if cmake-format cannot successfully fit
|
||||
- everything into the desired linewidth it will apply the
|
||||
- last, most aggressive attempt that it made. If this flag is
|
||||
- True, however, cmake-format will print error, exit with non-
|
||||
- zero status code, and write-out nothing
|
||||
require_valid_layout: false
|
||||
_help_layout_passes:
|
||||
- A dictionary mapping layout nodes to a list of wrap
|
||||
- decisions. See the documentation for more information.
|
||||
layout_passes: {}
|
||||
_help_markup: Options affecting comment reflow and formatting.
|
||||
markup:
|
||||
_help_bullet_char:
|
||||
- What character to use for bulleted lists
|
||||
bullet_char: "-"
|
||||
_help_enum_char:
|
||||
- What character to use as punctuation after numerals in an
|
||||
- enumerated list
|
||||
enum_char: .
|
||||
_help_first_comment_is_literal:
|
||||
- If comment markup is enabled, don't reflow the first comment
|
||||
- block in each listfile. Use this to preserve formatting of
|
||||
- your copyright/license statements.
|
||||
first_comment_is_literal: false
|
||||
_help_literal_comment_pattern:
|
||||
- If comment markup is enabled, don't reflow any comment block
|
||||
- which matches this (regex) pattern. Default is `None`
|
||||
- (disabled).
|
||||
literal_comment_pattern: null
|
||||
_help_fence_pattern:
|
||||
- Regular expression to match preformat fences in comments
|
||||
- default= ``r'^\s*([`~]{3}[`~]*)(.*)$'``
|
||||
fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
|
||||
_help_ruler_pattern:
|
||||
- Regular expression to match rulers in comments default=
|
||||
- '``r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''``'
|
||||
ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
|
||||
_help_explicit_trailing_pattern:
|
||||
- If a comment line matches starts with this pattern then it
|
||||
- is explicitly a trailing comment for the preceding
|
||||
- argument. Default is '#<'
|
||||
explicit_trailing_pattern: "#<"
|
||||
_help_hashruler_min_length:
|
||||
- If a comment line starts with at least this many consecutive
|
||||
- hash characters, then don't lstrip() them off. This allows
|
||||
- for lazy hash rulers where the first hash char is not
|
||||
- separated by space
|
||||
hashruler_min_length: 10
|
||||
_help_canonicalize_hashrulers:
|
||||
- If true, then insert a space between the first hash char and
|
||||
- remaining hash chars in a hash ruler, and normalize its
|
||||
- length to fill the column
|
||||
canonicalize_hashrulers: true
|
||||
_help_enable_markup:
|
||||
- enable comment markup parsing and reflow
|
||||
enable_markup: false
|
||||
_help_lint: Options affecting the linter
|
||||
lint:
|
||||
_help_disabled_codes:
|
||||
- a list of lint codes to disable
|
||||
disabled_codes: []
|
||||
_help_function_pattern:
|
||||
- regular expression pattern describing valid function names
|
||||
function_pattern: "[0-9a-z_]+"
|
||||
_help_macro_pattern:
|
||||
- regular expression pattern describing valid macro names
|
||||
macro_pattern: "[0-9A-Z_]+"
|
||||
_help_global_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with global (cache) scope
|
||||
global_var_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_internal_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with global scope (but internal semantic)
|
||||
internal_var_pattern: _[A-Z][0-9A-Z_]+
|
||||
_help_local_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- variables with local scope
|
||||
local_var_pattern: "[a-z][a-z0-9_]+"
|
||||
_help_private_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- privatedirectory variables
|
||||
private_var_pattern: _[0-9a-z_]+
|
||||
_help_public_var_pattern:
|
||||
- regular expression pattern describing valid names for public
|
||||
- directory variables
|
||||
public_var_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_argument_var_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- function/macro arguments and loop variables.
|
||||
argument_var_pattern: "[a-z][a-z0-9_]+"
|
||||
_help_keyword_pattern:
|
||||
- regular expression pattern describing valid names for
|
||||
- keywords used in functions or macros
|
||||
keyword_pattern: "[A-Z][0-9A-Z_]+"
|
||||
_help_max_conditionals_custom_parser:
|
||||
- In the heuristic for C0201, how many conditionals to match
|
||||
- within a loop in before considering the loop a parser.
|
||||
max_conditionals_custom_parser: 2
|
||||
_help_min_statement_spacing:
|
||||
- Require at least this many newlines between statements
|
||||
min_statement_spacing: 1
|
||||
_help_max_statement_spacing:
|
||||
- Require no more than this many newlines between statements
|
||||
max_statement_spacing: 2
|
||||
max_returns: 6
|
||||
max_branches: 12
|
||||
max_arguments: 5
|
||||
max_localvars: 15
|
||||
max_statements: 50
|
||||
_help_encode: Options affecting file encoding
|
||||
encode:
|
||||
_help_emit_byteorder_mark:
|
||||
- If true, emit the unicode byte-order mark (BOM) at the start
|
||||
- of the file
|
||||
emit_byteorder_mark: false
|
||||
_help_input_encoding:
|
||||
- Specify the encoding of the input file. Defaults to utf-8
|
||||
input_encoding: utf-8
|
||||
_help_output_encoding:
|
||||
- Specify the encoding of the output file. Defaults to utf-8.
|
||||
- Note that cmake only claims to support utf-8 so be careful
|
||||
- when using anything else
|
||||
output_encoding: utf-8
|
||||
_help_misc: Miscellaneous configurations options.
|
||||
misc:
|
||||
_help_per_command:
|
||||
- A dictionary containing any per-command configuration
|
||||
- overrides. Currently only `command_case` is supported.
|
||||
per_command: {}
|
||||
@@ -28,6 +28,7 @@ ignoreRegExpList:
|
||||
- /[\['"`]-[DWw][a-zA-Z0-9_-]+['"`\]]/g # compile flags
|
||||
suggestWords:
|
||||
- xprl->xrpl
|
||||
- xprld->xrpld
|
||||
- unsynched->unsynced
|
||||
- synched->synced
|
||||
- synch->sync
|
||||
@@ -51,6 +52,7 @@ words:
|
||||
- Btrfs
|
||||
- canonicality
|
||||
- checkme
|
||||
- choco
|
||||
- chrono
|
||||
- citardauq
|
||||
- clawback
|
||||
@@ -60,6 +62,7 @@ words:
|
||||
- compr
|
||||
- conanfile
|
||||
- conanrun
|
||||
- confs
|
||||
- connectability
|
||||
- coro
|
||||
- coros
|
||||
@@ -68,6 +71,7 @@ words:
|
||||
- cryptoconditional
|
||||
- cryptoconditions
|
||||
- csprng
|
||||
- ctest
|
||||
- ctid
|
||||
- currenttxhash
|
||||
- daria
|
||||
@@ -83,19 +87,21 @@ words:
|
||||
- doxyfile
|
||||
- dxrpl
|
||||
- endmacro
|
||||
- endpointv
|
||||
- exceptioned
|
||||
- Falco
|
||||
- finalizers
|
||||
- firewalled
|
||||
- fmtdur
|
||||
- fsanitize
|
||||
- funclets
|
||||
- gcov
|
||||
- gcovr
|
||||
- ghead
|
||||
- Gnutella
|
||||
- gpgcheck
|
||||
- gpgkey
|
||||
- hotwallet
|
||||
- hwrap
|
||||
- ifndef
|
||||
- inequation
|
||||
- insuf
|
||||
@@ -103,11 +109,14 @@ words:
|
||||
- iou
|
||||
- ious
|
||||
- isrdc
|
||||
- itype
|
||||
- jemalloc
|
||||
- jlog
|
||||
- keylet
|
||||
- keylets
|
||||
- keyvadb
|
||||
- kwarg
|
||||
- kwargs
|
||||
- ledgerentry
|
||||
- ledgerhash
|
||||
- ledgerindex
|
||||
@@ -123,6 +132,7 @@ words:
|
||||
- lseq
|
||||
- lsmf
|
||||
- ltype
|
||||
- mcmodel
|
||||
- MEMORYSTATUSEX
|
||||
- Merkle
|
||||
- Metafuncton
|
||||
@@ -156,6 +166,7 @@ words:
|
||||
- nunl
|
||||
- Nyffenegger
|
||||
- ostr
|
||||
- pargs
|
||||
- partitioner
|
||||
- paychan
|
||||
- paychans
|
||||
@@ -191,10 +202,12 @@ words:
|
||||
- roundings
|
||||
- sahyadri
|
||||
- Satoshi
|
||||
- scons
|
||||
- secp
|
||||
- sendq
|
||||
- seqit
|
||||
- sf
|
||||
- SFIELD
|
||||
- shamap
|
||||
- shamapitem
|
||||
- sidechain
|
||||
@@ -221,6 +234,8 @@ words:
|
||||
- takergets
|
||||
- takerpays
|
||||
- ters
|
||||
- TMEndpointv2
|
||||
- trixie
|
||||
- tx
|
||||
- txid
|
||||
- txids
|
||||
@@ -228,6 +243,8 @@ words:
|
||||
- txn
|
||||
- txns
|
||||
- txs
|
||||
- UBSAN
|
||||
- ubsan
|
||||
- umant
|
||||
- unacquired
|
||||
- unambiguity
|
||||
@@ -263,6 +280,7 @@ words:
|
||||
- xbridge
|
||||
- xchain
|
||||
- ximinez
|
||||
- EXPECT_STREQ
|
||||
- XMACRO
|
||||
- xrpkuwait
|
||||
- xrpl
|
||||
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,5 +1,6 @@
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
#* text=auto
|
||||
# cspell: disable
|
||||
|
||||
# Visual Studio
|
||||
*.sln text eol=crlf
|
||||
|
||||
8
.github/CODEOWNERS
vendored
8
.github/CODEOWNERS
vendored
@@ -1,8 +0,0 @@
|
||||
# Allow anyone to review any change by default.
|
||||
*
|
||||
|
||||
# Require the rpc-reviewers team to review changes to the rpc code.
|
||||
include/xrpl/protocol/ @xrplf/rpc-reviewers
|
||||
src/libxrpl/protocol/ @xrplf/rpc-reviewers
|
||||
src/xrpld/rpc/ @xrplf/rpc-reviewers
|
||||
src/xrpld/app/misc/ @xrplf/rpc-reviewers
|
||||
6
.github/actions/build-deps/action.yml
vendored
6
.github/actions/build-deps/action.yml
vendored
@@ -18,6 +18,10 @@ inputs:
|
||||
description: "The logging verbosity."
|
||||
required: false
|
||||
default: "verbose"
|
||||
sanitizers:
|
||||
description: "The sanitizers to enable."
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -29,9 +33,11 @@ runs:
|
||||
BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
LOG_VERBOSITY: ${{ inputs.log_verbosity }}
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
run: |
|
||||
echo 'Installing dependencies.'
|
||||
conan install \
|
||||
--profile ci \
|
||||
--build="${BUILD_OPTION}" \
|
||||
--options:host='&:tests=True' \
|
||||
--options:host='&:xrpld=True' \
|
||||
|
||||
44
.github/actions/generate-version/action.yml
vendored
Normal file
44
.github/actions/generate-version/action.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Generate build version number
|
||||
description: "Generate build version number."
|
||||
|
||||
outputs:
|
||||
version:
|
||||
description: "The generated build version number."
|
||||
value: ${{ steps.version.outputs.version }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# When a tag is pushed, the version is used as-is.
|
||||
- name: Generate version for tag event
|
||||
if: ${{ github.event_name == 'tag' }}
|
||||
shell: bash
|
||||
env:
|
||||
VERSION: ${{ github.ref_name }}
|
||||
run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
|
||||
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
|
||||
# We use a plus sign instead of a hyphen because Conan recipe versions do
|
||||
# not support two hyphens.
|
||||
- name: Generate version for non-tag event
|
||||
if: ${{ github.event_name != 'tag' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'Extracting version from BuildInfo.cpp.'
|
||||
VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')"
|
||||
if [[ -z "${VERSION}" ]]; then
|
||||
echo 'Unable to extract version from BuildInfo.cpp.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'Appending shortened commit hash to version.'
|
||||
SHA='${{ github.sha }}'
|
||||
VERSION="${VERSION}+${SHA:0:7}"
|
||||
|
||||
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Output version
|
||||
id: version
|
||||
shell: bash
|
||||
run: echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
|
||||
16
.github/actions/setup-conan/action.yml
vendored
16
.github/actions/setup-conan/action.yml
vendored
@@ -2,11 +2,11 @@ name: Setup Conan
|
||||
description: "Set up Conan configuration, profile, and remote."
|
||||
|
||||
inputs:
|
||||
conan_remote_name:
|
||||
remote_name:
|
||||
description: "The name of the Conan remote to use."
|
||||
required: false
|
||||
default: xrplf
|
||||
conan_remote_url:
|
||||
remote_url:
|
||||
description: "The URL of the Conan endpoint to use."
|
||||
required: false
|
||||
default: https://conan.ripplex.io
|
||||
@@ -28,19 +28,19 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'Installing profile.'
|
||||
conan config install conan/profiles/default -tf $(conan config home)/profiles/
|
||||
conan config install conan/profiles/ -tf $(conan config home)/profiles/
|
||||
|
||||
echo 'Conan profile:'
|
||||
conan profile show
|
||||
conan profile show --profile ci
|
||||
|
||||
- name: Set up Conan remote
|
||||
shell: bash
|
||||
env:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
CONAN_REMOTE_URL: ${{ inputs.conan_remote_url }}
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
REMOTE_URL: ${{ inputs.remote_url }}
|
||||
run: |
|
||||
echo "Adding Conan remote '${CONAN_REMOTE_NAME}' at '${CONAN_REMOTE_URL}'."
|
||||
conan remote add --index 0 --force "${CONAN_REMOTE_NAME}" "${CONAN_REMOTE_URL}"
|
||||
echo "Adding Conan remote '${REMOTE_NAME}' at '${REMOTE_URL}'."
|
||||
conan remote add --index 0 --force "${REMOTE_NAME}" "${REMOTE_URL}"
|
||||
|
||||
echo 'Listing Conan remotes.'
|
||||
conan remote list
|
||||
|
||||
2
.github/scripts/levelization/README.md
vendored
2
.github/scripts/levelization/README.md
vendored
@@ -84,7 +84,7 @@ It generates many files of [results](results):
|
||||
to the destination module, de-duped, and with frequency counts.
|
||||
- `includes/`: A directory where each file represents a module and
|
||||
contains a list of modules and counts that the module _includes_.
|
||||
- `includedby/`: Similar to `includes/`, but the other way around. Each
|
||||
- `included_by/`: Similar to `includes/`, but the other way around. Each
|
||||
file represents a module and contains a list of modules and counts
|
||||
that _include_ the module.
|
||||
- [`loops.txt`](results/loops.txt): A list of direct loops detected
|
||||
|
||||
6
.github/scripts/levelization/generate.sh
vendored
6
.github/scripts/levelization/generate.sh
vendored
@@ -29,7 +29,7 @@ pushd results
|
||||
oldifs=${IFS}
|
||||
IFS=:
|
||||
mkdir includes
|
||||
mkdir includedby
|
||||
mkdir included_by
|
||||
echo Build levelization paths
|
||||
exec 3< ${includes} # open rawincludes.txt for input
|
||||
while read -r -u 3 file include
|
||||
@@ -59,7 +59,7 @@ do
|
||||
echo $level $includelevel | tee -a paths.txt
|
||||
fi
|
||||
done
|
||||
echo Sort and dedup paths
|
||||
echo Sort and deduplicate paths
|
||||
sort -ds paths.txt | uniq -c | tee sortedpaths.txt
|
||||
mv sortedpaths.txt paths.txt
|
||||
exec 3>&- #close fd 3
|
||||
@@ -71,7 +71,7 @@ exec 4<paths.txt # open paths.txt for input
|
||||
while read -r -u 4 count level include
|
||||
do
|
||||
echo ${include} ${count} | tee -a includes/${level}
|
||||
echo ${level} ${count} | tee -a includedby/${include}
|
||||
echo ${level} ${count} | tee -a included_by/${include}
|
||||
done
|
||||
exec 4>&- #close fd 4
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ test.overlay > xrpl.basics
|
||||
test.overlay > xrpld.app
|
||||
test.overlay > xrpld.overlay
|
||||
test.overlay > xrpld.peerfinder
|
||||
test.overlay > xrpl.nodestore
|
||||
test.overlay > xrpl.protocol
|
||||
test.overlay > xrpl.shamap
|
||||
test.peerfinder > test.beast
|
||||
@@ -152,6 +153,7 @@ tests.libxrpl > xrpl.json
|
||||
tests.libxrpl > xrpl.net
|
||||
xrpl.core > xrpl.basics
|
||||
xrpl.core > xrpl.json
|
||||
xrpl.core > xrpl.ledger
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
xrpl.ledger > xrpl.protocol
|
||||
|
||||
2
.github/scripts/rename/README.md
vendored
2
.github/scripts/rename/README.md
vendored
@@ -19,7 +19,7 @@ run from the repository root.
|
||||
1. `.github/scripts/rename/definitions.sh`: This script will rename all
|
||||
definitions, such as include guards, from `RIPPLE_XXX` and `RIPPLED_XXX` to
|
||||
`XRPL_XXX`.
|
||||
2. `.github/scripts/rename/copyright.sh`: This script will remove superflous
|
||||
2. `.github/scripts/rename/copyright.sh`: This script will remove superfluous
|
||||
copyright notices.
|
||||
3. `.github/scripts/rename/cmake.sh`: This script will rename all CMake files
|
||||
from `RippleXXX.cmake` or `RippledXXX.cmake` to `XrplXXX.cmake`, and any
|
||||
|
||||
2
.github/scripts/rename/config.sh
vendored
2
.github/scripts/rename/config.sh
vendored
@@ -56,7 +56,7 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do
|
||||
done
|
||||
${SED_COMMAND} -i 's/rippled/xrpld/g' cfg/xrpld-example.cfg
|
||||
${SED_COMMAND} -i 's/rippled/xrpld/g' src/test/core/Config_test.cpp
|
||||
${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp
|
||||
${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp # cspell: disable-line
|
||||
${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' src/test/core/Config_test.cpp
|
||||
${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp
|
||||
${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp
|
||||
|
||||
12
.github/scripts/rename/copyright.sh
vendored
12
.github/scripts/rename/copyright.sh
vendored
@@ -50,11 +50,11 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do
|
||||
# Handle the cases where the copyright notice is enclosed in /* ... */
|
||||
# and usually surrounded by //---- and //======.
|
||||
${SED_COMMAND} -z -i -E 's@^//-------+\n+@@' "${FILE}"
|
||||
${SED_COMMAND} -z -i -E 's@^.*Copyright.+(Ripple|Bougalis|Falco|Hinnant|Null|Ritchford|XRPLF).+PERFORMANCE OF THIS SOFTWARE\.\n\*/\n+@@' "${FILE}"
|
||||
${SED_COMMAND} -z -i -E 's@^.*Copyright.+(Ripple|Bougalis|Falco|Hinnant|Null|Ritchford|XRPLF).+PERFORMANCE OF THIS SOFTWARE\.\n\*/\n+@@' "${FILE}" # cspell: ignore Bougalis Falco Hinnant Ritchford
|
||||
${SED_COMMAND} -z -i -E 's@^//=======+\n+@@' "${FILE}"
|
||||
|
||||
# Handle the cases where the copyright notice is commented out with //.
|
||||
${SED_COMMAND} -z -i -E 's@^//\n// Copyright.+Falco \(vinnie dot falco at gmail dot com\)\n//\n+@@' "${FILE}"
|
||||
${SED_COMMAND} -z -i -E 's@^//\n// Copyright.+Falco \(vinnie dot falco at gmail dot com\)\n//\n+@@' "${FILE}" # cspell: ignore Vinnie Falco
|
||||
done
|
||||
done
|
||||
|
||||
@@ -83,16 +83,16 @@ if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/ValidatorInfo.cpp; then
|
||||
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/ValidatorInfo.cpp
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/spinlock.h; then
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/tagged_integer.h; then
|
||||
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h
|
||||
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Ritchford' include/xrpl/beast/utility/Zero.h; then
|
||||
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h
|
||||
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
|
||||
fi
|
||||
|
||||
# Restore newlines and tabs in string literals in the affected file.
|
||||
|
||||
30
.github/scripts/rename/include.sh
vendored
Executable file
30
.github/scripts/rename/include.sh
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit the script as soon as an error occurs.
|
||||
set -e
|
||||
|
||||
# This script checks whether there are no new include guards introduced by a new
|
||||
# PR, as header files should use "#pragma once" instead. The script assumes any
|
||||
# include guards will use "XRPL_" as prefix.
|
||||
# Usage: .github/scripts/rename/include.sh <repository directory>
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <repository directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIRECTORY=$1
|
||||
echo "Processing directory: ${DIRECTORY}"
|
||||
if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" \) | while read -r FILE; do
|
||||
echo "Processing file: ${FILE}"
|
||||
if grep -q "#ifndef XRPL_" "${FILE}"; then
|
||||
echo "Please replace all include guards by #pragma once."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Checking complete."
|
||||
138
.github/scripts/strategy-matrix/generate.py
vendored
138
.github/scripts/strategy-matrix/generate.py
vendored
@@ -20,8 +20,8 @@ class Config:
|
||||
Generate a strategy matrix for GitHub Actions CI.
|
||||
|
||||
On each PR commit we will build a selection of Debian, RHEL, Ubuntu, MacOS, and
|
||||
Windows configurations, while upon merge into the develop, release, or master
|
||||
branches, we will build all configurations, and test most of them.
|
||||
Windows configurations, while upon merge into the develop or release branches,
|
||||
we will build all configurations, and test most of them.
|
||||
|
||||
We will further set additional CMake arguments as follows:
|
||||
- All builds will have the `tests`, `werr`, and `xrpld` options.
|
||||
@@ -51,22 +51,20 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# Only generate a subset of configurations in PRs.
|
||||
if not all:
|
||||
# Debian:
|
||||
# - Bookworm using GCC 13: Release and Unity on linux/amd64, set
|
||||
# the reference fee to 500.
|
||||
# - Bookworm using GCC 15: Debug and no Unity on linux/amd64, enable
|
||||
# code coverage (which will be done below).
|
||||
# - Bookworm using Clang 16: Debug and no Unity on linux/arm64,
|
||||
# enable voidstar.
|
||||
# - Bookworm using Clang 17: Release and no Unity on linux/amd64,
|
||||
# set the reference fee to 1000.
|
||||
# - Bookworm using Clang 20: Debug and Unity on linux/amd64.
|
||||
# - Bookworm using GCC 13: Release on linux/amd64, set the reference
|
||||
# fee to 500.
|
||||
# - Bookworm using GCC 15: Debug on linux/amd64, enable code
|
||||
# coverage (which will be done below).
|
||||
# - Bookworm using Clang 16: Debug on linux/arm64, enable voidstar.
|
||||
# - Bookworm using Clang 17: Release on linux/amd64, set the
|
||||
# reference fee to 1000.
|
||||
# - Bookworm using Clang 20: Debug on linux/amd64.
|
||||
if os["distro_name"] == "debian":
|
||||
skip = True
|
||||
if os["distro_version"] == "bookworm":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-13"
|
||||
and build_type == "Release"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}"
|
||||
@@ -74,14 +72,12 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-16"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/arm64"
|
||||
):
|
||||
cmake_args = f"-Dvoidstar=ON {cmake_args}"
|
||||
@@ -89,7 +85,6 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-17"
|
||||
and build_type == "Release"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=1000 {cmake_args}"
|
||||
@@ -97,7 +92,6 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
@@ -105,15 +99,14 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# RHEL:
|
||||
# - 9 using GCC 12: Debug and Unity on linux/amd64.
|
||||
# - 10 using Clang: Release and no Unity on linux/amd64.
|
||||
# - 9 using GCC 12: Debug on linux/amd64.
|
||||
# - 10 using Clang: Release on linux/amd64.
|
||||
if os["distro_name"] == "rhel":
|
||||
skip = True
|
||||
if os["distro_version"] == "9":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
@@ -121,7 +114,6 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-any"
|
||||
and build_type == "Release"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
@@ -129,17 +121,16 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# Ubuntu:
|
||||
# - Jammy using GCC 12: Debug and no Unity on linux/arm64.
|
||||
# - Noble using GCC 14: Release and Unity on linux/amd64.
|
||||
# - Noble using Clang 18: Debug and no Unity on linux/amd64.
|
||||
# - Noble using Clang 19: Release and Unity on linux/arm64.
|
||||
# - Jammy using GCC 12: Debug on linux/arm64.
|
||||
# - Noble using GCC 14: Release on linux/amd64.
|
||||
# - Noble using Clang 18: Debug on linux/amd64.
|
||||
# - Noble using Clang 19: Release on linux/arm64.
|
||||
if os["distro_name"] == "ubuntu":
|
||||
skip = True
|
||||
if os["distro_version"] == "jammy":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/arm64"
|
||||
):
|
||||
skip = False
|
||||
@@ -147,21 +138,18 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-14"
|
||||
and build_type == "Release"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-18"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-19"
|
||||
and build_type == "Release"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "linux/arm64"
|
||||
):
|
||||
skip = False
|
||||
@@ -169,20 +157,16 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# MacOS:
|
||||
# - Debug and no Unity on macos/arm64.
|
||||
# - Debug on macos/arm64.
|
||||
if os["distro_name"] == "macos" and not (
|
||||
build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "macos/arm64"
|
||||
build_type == "Debug" and architecture["platform"] == "macos/arm64"
|
||||
):
|
||||
continue
|
||||
|
||||
# Windows:
|
||||
# - Release and Unity on windows/amd64.
|
||||
# - Release on windows/amd64.
|
||||
if os["distro_name"] == "windows" and not (
|
||||
build_type == "Release"
|
||||
and "-Dunity=ON" in cmake_args
|
||||
and architecture["platform"] == "windows/amd64"
|
||||
build_type == "Release" and architecture["platform"] == "windows/amd64"
|
||||
):
|
||||
continue
|
||||
|
||||
@@ -209,18 +193,28 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
):
|
||||
continue
|
||||
|
||||
# Enable code coverage for Debian Bookworm using GCC 15 in Debug and no
|
||||
# Unity on linux/amd64
|
||||
# Enable code coverage for Debian Bookworm using GCC 15 in Debug on
|
||||
# linux/amd64
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
|
||||
f"{os['distro_name']}-{os['distro_version']}" == "debian-bookworm"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
|
||||
and build_type == "Debug"
|
||||
and "-Dunity=OFF" in cmake_args
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
cmake_args = f"-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0 {cmake_args}"
|
||||
cmake_args = f"{cmake_args} -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
|
||||
|
||||
# Enable unity build for Ubuntu Jammy using GCC 12 in Debug on
|
||||
# linux/amd64.
|
||||
if (
|
||||
f"{os['distro_name']}-{os['distro_version']}" == "ubuntu-jammy"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
|
||||
and build_type == "Debug"
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
cmake_args = f"{cmake_args} -Dunity=ON"
|
||||
|
||||
# Generate a unique name for the configuration, e.g. macos-arm64-debug
|
||||
# or debian-bookworm-gcc-12-amd64-release-unity.
|
||||
# or debian-bookworm-gcc-12-amd64-release.
|
||||
config_name = os["distro_name"]
|
||||
if (n := os["distro_version"]) != "":
|
||||
config_name += f"-{n}"
|
||||
@@ -229,7 +223,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
if (n := os["compiler_version"]) != "":
|
||||
config_name += f"-{n}"
|
||||
config_name += (
|
||||
f"-{architecture['platform'][architecture['platform'].find('/') + 1 :]}"
|
||||
f"-{architecture['platform'][architecture['platform'].find('/')+1:]}"
|
||||
)
|
||||
config_name += f"-{build_type.lower()}"
|
||||
if "-Dcoverage=ON" in cmake_args:
|
||||
@@ -240,17 +234,53 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# Add the configuration to the list, with the most unique fields first,
|
||||
# so that they are easier to identify in the GitHub Actions UI, as long
|
||||
# names get truncated.
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name,
|
||||
"cmake_args": cmake_args,
|
||||
"cmake_target": cmake_target,
|
||||
"build_only": build_only,
|
||||
"build_type": build_type,
|
||||
"os": os,
|
||||
"architecture": architecture,
|
||||
}
|
||||
)
|
||||
# Add Address and Thread (both coupled with UB) sanitizers for specific bookworm distros.
|
||||
# GCC-Asan rippled-embedded tests are failing because of https://github.com/google/sanitizers/issues/856
|
||||
if (
|
||||
os["distro_version"] == "bookworm"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20"
|
||||
):
|
||||
# Add ASAN + UBSAN configuration.
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name + "-asan-ubsan",
|
||||
"cmake_args": cmake_args,
|
||||
"cmake_target": cmake_target,
|
||||
"build_only": build_only,
|
||||
"build_type": build_type,
|
||||
"os": os,
|
||||
"architecture": architecture,
|
||||
"sanitizers": "address,undefinedbehavior",
|
||||
}
|
||||
)
|
||||
# TSAN is deactivated due to seg faults with latest compilers.
|
||||
activate_tsan = False
|
||||
if activate_tsan:
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name + "-tsan-ubsan",
|
||||
"cmake_args": cmake_args,
|
||||
"cmake_target": cmake_target,
|
||||
"build_only": build_only,
|
||||
"build_type": build_type,
|
||||
"os": os,
|
||||
"architecture": architecture,
|
||||
"sanitizers": "thread,undefinedbehavior",
|
||||
}
|
||||
)
|
||||
else:
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name,
|
||||
"cmake_args": cmake_args,
|
||||
"cmake_target": cmake_target,
|
||||
"build_only": build_only,
|
||||
"build_type": build_type,
|
||||
"os": os,
|
||||
"architecture": architecture,
|
||||
"sanitizers": "",
|
||||
}
|
||||
)
|
||||
|
||||
return configurations
|
||||
|
||||
|
||||
58
.github/scripts/strategy-matrix/linux.json
vendored
58
.github/scripts/strategy-matrix/linux.json
vendored
@@ -15,198 +15,198 @@
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "15",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "20",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "15",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "20",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "21",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "jammy",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19",
|
||||
"image_sha": "cc09fd3"
|
||||
"image_sha": "ab4d1f0"
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
"cmake_args": ["-Dunity=OFF", "-Dunity=ON"]
|
||||
"cmake_args": [""]
|
||||
}
|
||||
|
||||
5
.github/scripts/strategy-matrix/macos.json
vendored
5
.github/scripts/strategy-matrix/macos.json
vendored
@@ -15,8 +15,5 @@
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
"cmake_args": [
|
||||
"-Dunity=OFF -DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
||||
"-Dunity=ON -DCMAKE_POLICY_VERSION_MINIMUM=3.5"
|
||||
]
|
||||
"cmake_args": ["-DCMAKE_POLICY_VERSION_MINIMUM=3.5"]
|
||||
}
|
||||
|
||||
2
.github/scripts/strategy-matrix/windows.json
vendored
2
.github/scripts/strategy-matrix/windows.json
vendored
@@ -15,5 +15,5 @@
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
"cmake_args": ["-Dunity=OFF", "-Dunity=ON"]
|
||||
"cmake_args": [""]
|
||||
}
|
||||
|
||||
40
.github/workflows/on-pr.yml
vendored
40
.github/workflows/on-pr.yml
vendored
@@ -1,7 +1,8 @@
|
||||
# This workflow runs all workflows to check, build and test the project on
|
||||
# various Linux flavors, as well as on MacOS and Windows, on every push to a
|
||||
# user branch. However, it will not run if the pull request is a draft unless it
|
||||
# has the 'DraftRunCI' label.
|
||||
# has the 'DraftRunCI' label. For commits to PRs that target a release branch,
|
||||
# it also uploads the libxrpl recipe to the Conan remote.
|
||||
name: PR
|
||||
|
||||
on:
|
||||
@@ -53,12 +54,12 @@ jobs:
|
||||
.github/scripts/rename/**
|
||||
.github/workflows/reusable-check-levelization.yml
|
||||
.github/workflows/reusable-check-rename.yml
|
||||
.github/workflows/reusable-notify-clio.yml
|
||||
.github/workflows/on-pr.yml
|
||||
|
||||
# Keep the paths below in sync with those in `on-trigger.yml`.
|
||||
.github/actions/build-deps/**
|
||||
.github/actions/build-test/**
|
||||
.github/actions/generate-version/**
|
||||
.github/actions/setup-conan/**
|
||||
.github/scripts/strategy-matrix/**
|
||||
.github/workflows/reusable-build.yml
|
||||
@@ -66,6 +67,7 @@ jobs:
|
||||
.github/workflows/reusable-build-test.yml
|
||||
.github/workflows/reusable-strategy-matrix.yml
|
||||
.github/workflows/reusable-test.yml
|
||||
.github/workflows/reusable-upload-recipe.yml
|
||||
.codecov.yml
|
||||
cmake/**
|
||||
conan/**
|
||||
@@ -121,22 +123,42 @@ jobs:
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
notify-clio:
|
||||
upload-recipe:
|
||||
needs:
|
||||
- should-run
|
||||
- build-test
|
||||
if: ${{ needs.should-run.outputs.go == 'true' && (startsWith(github.base_ref, 'release') || github.base_ref == 'master') }}
|
||||
uses: ./.github/workflows/reusable-notify-clio.yml
|
||||
# Only run when committing to a PR that targets a release branch in the
|
||||
# XRPLF repository.
|
||||
if: ${{ github.repository_owner == 'XRPLF' && needs.should-run.outputs.go == 'true' && startsWith(github.ref, 'refs/heads/release') }}
|
||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||
secrets:
|
||||
clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }}
|
||||
conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
conan_remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
|
||||
notify-clio:
|
||||
needs: upload-recipe
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Notify the Clio repository about the newly proposed release version, so
|
||||
# it can be checked for compatibility before the release is actually made.
|
||||
- name: Notify Clio
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.CLIO_NOTIFY_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
|
||||
-F "client_payload[pr_url]=${PR_URL}"
|
||||
|
||||
passed:
|
||||
if: failure() || cancelled()
|
||||
needs:
|
||||
- build-test
|
||||
- check-levelization
|
||||
- check-rename
|
||||
- build-test
|
||||
- upload-recipe
|
||||
- notify-clio
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fail
|
||||
|
||||
25
.github/workflows/on-tag.yml
vendored
Normal file
25
.github/workflows/on-tag.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# This workflow uploads the libxrpl recipe to the Conan remote when a versioned
|
||||
# tag is pushed.
|
||||
name: Tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
upload-recipe:
|
||||
# Only run when a tag is pushed to the XRPLF repository.
|
||||
if: ${{ github.repository_owner == 'XRPLF' }}
|
||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||
secrets:
|
||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
30
.github/workflows/on-trigger.yml
vendored
30
.github/workflows/on-trigger.yml
vendored
@@ -1,9 +1,7 @@
|
||||
# This workflow runs all workflows to build the dependencies required for the
|
||||
# project on various Linux flavors, as well as on MacOS and Windows, on a
|
||||
# scheduled basis, on merge into the 'develop', 'release', or 'master' branches,
|
||||
# or manually. The missing commits check is only run when the code is merged
|
||||
# into the 'develop' or 'release' branches, and the documentation is built when
|
||||
# the code is merged into the 'develop' branch.
|
||||
# This workflow runs all workflows to build and test the code on various Linux
|
||||
# flavors, as well as on MacOS and Windows, on a scheduled basis, on merge into
|
||||
# the 'develop' or 'release*' branches, or when requested manually. Upon pushes
|
||||
# to the develop branch it also uploads the libxrpl recipe to the Conan remote.
|
||||
name: Trigger
|
||||
|
||||
on:
|
||||
@@ -11,7 +9,6 @@ on:
|
||||
branches:
|
||||
- "develop"
|
||||
- "release*"
|
||||
- "master"
|
||||
paths:
|
||||
# These paths are unique to `on-trigger.yml`.
|
||||
- ".github/workflows/on-trigger.yml"
|
||||
@@ -19,6 +16,7 @@ on:
|
||||
# Keep the paths below in sync with those in `on-pr.yml`.
|
||||
- ".github/actions/build-deps/**"
|
||||
- ".github/actions/build-test/**"
|
||||
- ".github/actions/generate-version/**"
|
||||
- ".github/actions/setup-conan/**"
|
||||
- ".github/scripts/strategy-matrix/**"
|
||||
- ".github/workflows/reusable-build.yml"
|
||||
@@ -26,6 +24,7 @@ on:
|
||||
- ".github/workflows/reusable-build-test.yml"
|
||||
- ".github/workflows/reusable-strategy-matrix.yml"
|
||||
- ".github/workflows/reusable-test.yml"
|
||||
- ".github/workflows/reusable-upload-recipe.yml"
|
||||
- ".codecov.yml"
|
||||
- "cmake/**"
|
||||
- "conan/**"
|
||||
@@ -70,11 +69,20 @@ jobs:
|
||||
with:
|
||||
# Enable ccache only for events targeting the XRPLF repository, since
|
||||
# other accounts will not have access to our remote cache storage.
|
||||
# However, we do not enable ccache for events targeting the master or a
|
||||
# release branch, to protect against the rare case that the output
|
||||
# produced by ccache is not identical to a regular compilation.
|
||||
ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !(github.base_ref == 'master' || startsWith(github.base_ref, 'release')) }}
|
||||
# However, we do not enable ccache for events targeting a release branch,
|
||||
# to protect against the rare case that the output produced by ccache is
|
||||
# not identical to a regular compilation.
|
||||
ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !startsWith(github.ref, 'refs/heads/release') }}
|
||||
os: ${{ matrix.os }}
|
||||
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
upload-recipe:
|
||||
needs: build-test
|
||||
# Only run when pushing to the develop branch in the XRPLF repository.
|
||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
|
||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||
secrets:
|
||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
|
||||
8
.github/workflows/pre-commit.yml
vendored
8
.github/workflows/pre-commit.yml
vendored
@@ -3,13 +3,15 @@ name: Run pre-commit hooks
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [develop, release, master]
|
||||
branches:
|
||||
- "develop"
|
||||
- "release*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@320be44621ca2a080f05aeb15817c44b84518108
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-ab4d1f0" }'
|
||||
|
||||
2
.github/workflows/publish-docs.yml
vendored
2
.github/workflows/publish-docs.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
||||
|
||||
29
.github/workflows/reusable-build-test-config.yml
vendored
29
.github/workflows/reusable-build-test-config.yml
vendored
@@ -51,6 +51,12 @@ on:
|
||||
type: number
|
||||
default: 2
|
||||
|
||||
sanitizers:
|
||||
description: "The sanitizers to enable."
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
@@ -91,18 +97,19 @@ jobs:
|
||||
# Determine if coverage and voidstar should be enabled.
|
||||
COVERAGE_ENABLED: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }}
|
||||
VOIDSTAR_ENABLED: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
SANITIZERS_ENABLED: ${{ inputs.sanitizers != '' }}
|
||||
steps:
|
||||
- name: Cleanup workspace (macOS and Windows)
|
||||
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
with:
|
||||
disable_ccache: ${{ !inputs.ccache_enabled }}
|
||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
||||
|
||||
- name: Set ccache log file
|
||||
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
|
||||
@@ -112,12 +119,14 @@ jobs:
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Setup Conan
|
||||
env:
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
@@ -128,11 +137,13 @@ jobs:
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
@@ -174,7 +185,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Check linking (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
run: |
|
||||
ldd ./xrpld
|
||||
@@ -191,6 +202,14 @@ jobs:
|
||||
run: |
|
||||
./xrpld --version | grep libvoidstar
|
||||
|
||||
- name: Set sanitizer options
|
||||
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
|
||||
run: |
|
||||
echo "ASAN_OPTIONS=print_stacktrace=1:detect_container_overflow=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp" >> ${GITHUB_ENV}
|
||||
echo "TSAN_OPTIONS=second_deadlock_stack=1:halt_on_error=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
|
||||
echo "UBSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
|
||||
echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
|
||||
1
.github/workflows/reusable-build-test.yml
vendored
1
.github/workflows/reusable-build-test.yml
vendored
@@ -57,5 +57,6 @@ jobs:
|
||||
runs_on: ${{ toJSON(matrix.architecture.runner) }}
|
||||
image: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || '' }}
|
||||
config_name: ${{ matrix.config_name }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
2
.github/workflows/reusable-check-rename.yml
vendored
2
.github/workflows/reusable-check-rename.yml
vendored
@@ -31,6 +31,8 @@ jobs:
|
||||
run: .github/scripts/rename/namespace.sh .
|
||||
- name: Check config name
|
||||
run: .github/scripts/rename/config.sh .
|
||||
- name: Check include guards
|
||||
run: .github/scripts/rename/include.sh .
|
||||
- name: Check for differences
|
||||
env:
|
||||
MESSAGE: |
|
||||
|
||||
91
.github/workflows/reusable-notify-clio.yml
vendored
91
.github/workflows/reusable-notify-clio.yml
vendored
@@ -1,91 +0,0 @@
|
||||
# This workflow exports the built libxrpl package to the Conan remote on a
|
||||
# a channel named after the pull request, and notifies the Clio repository about
|
||||
# the new version so it can check for compatibility.
|
||||
name: Notify Clio
|
||||
|
||||
# This workflow can only be triggered by other workflows.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
conan_remote_name:
|
||||
description: "The name of the Conan remote to use."
|
||||
required: false
|
||||
type: string
|
||||
default: xrplf
|
||||
conan_remote_url:
|
||||
description: "The URL of the Conan endpoint to use."
|
||||
required: false
|
||||
type: string
|
||||
default: https://conan.ripplex.io
|
||||
secrets:
|
||||
clio_notify_token:
|
||||
description: "The GitHub token to notify Clio about new versions."
|
||||
required: true
|
||||
conan_remote_username:
|
||||
description: "The username for logging into the Conan remote."
|
||||
required: true
|
||||
conan_remote_password:
|
||||
description: "The password for logging into the Conan remote."
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-clio
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- name: Generate outputs
|
||||
id: generate
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
echo 'Generating user and channel.'
|
||||
echo "user=clio" >> "${GITHUB_OUTPUT}"
|
||||
echo "channel=pr_${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
|
||||
echo 'Extracting version.'
|
||||
echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}"
|
||||
- name: Calculate conan reference
|
||||
id: conan_ref
|
||||
run: |
|
||||
echo "conan_ref=${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }}" >> "${GITHUB_OUTPUT}"
|
||||
- name: Set up Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
conan_remote_name: ${{ inputs.conan_remote_name }}
|
||||
conan_remote_url: ${{ inputs.conan_remote_url }}
|
||||
- name: Log into Conan remote
|
||||
env:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
|
||||
- name: Upload package
|
||||
env:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
run: |
|
||||
conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} .
|
||||
conan upload --confirm --check --remote="${CONAN_REMOTE_NAME}" xrpl/${{ steps.conan_ref.outputs.conan_ref }}
|
||||
outputs:
|
||||
conan_ref: ${{ steps.conan_ref.outputs.conan_ref }}
|
||||
|
||||
notify:
|
||||
needs: upload
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Notify Clio
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.clio_notify_token }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||
-F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \
|
||||
-F "client_payload[pr_url]=${PR_URL}"
|
||||
97
.github/workflows/reusable-upload-recipe.yml
vendored
Normal file
97
.github/workflows/reusable-upload-recipe.yml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
# This workflow exports the built libxrpl package to the Conan remote.
|
||||
name: Upload Conan recipe
|
||||
|
||||
# This workflow can only be triggered by other workflows.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
remote_name:
|
||||
description: "The name of the Conan remote to use."
|
||||
required: false
|
||||
type: string
|
||||
default: xrplf
|
||||
remote_url:
|
||||
description: "The URL of the Conan endpoint to use."
|
||||
required: false
|
||||
type: string
|
||||
default: https://conan.ripplex.io
|
||||
|
||||
secrets:
|
||||
remote_username:
|
||||
description: "The username for logging into the Conan remote."
|
||||
required: true
|
||||
remote_password:
|
||||
description: "The password for logging into the Conan remote."
|
||||
required: true
|
||||
|
||||
outputs:
|
||||
recipe_ref:
|
||||
description: "The Conan recipe reference ('name/version') that was uploaded."
|
||||
value: ${{ jobs.upload.outputs.ref }}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-upload-recipe
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Generate build version number
|
||||
id: version
|
||||
uses: ./.github/actions/generate-version
|
||||
|
||||
- name: Set up Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
remote_name: ${{ inputs.remote_name }}
|
||||
remote_url: ${{ inputs.remote_url }}
|
||||
|
||||
- name: Log into Conan remote
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
REMOTE_USERNAME: ${{ secrets.remote_username }}
|
||||
REMOTE_PASSWORD: ${{ secrets.remote_password }}
|
||||
run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}"
|
||||
|
||||
- name: Upload Conan recipe (version)
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=${{ steps.version.outputs.version }}
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Upload Conan recipe (develop)
|
||||
if: ${{ github.ref == 'refs/heads/develop' }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=develop
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
|
||||
|
||||
- name: Upload Conan recipe (rc)
|
||||
if: ${{ startsWith(github.ref, 'refs/heads/release') }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=rc
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
|
||||
|
||||
- name: Upload Conan recipe (release)
|
||||
if: ${{ github.event_name == 'tag' }}
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
run: |
|
||||
conan export . --version=release
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release
|
||||
|
||||
outputs:
|
||||
ref: xrpl/${{ steps.version.outputs.version }}
|
||||
15
.github/workflows/upload-conan-deps.yml
vendored
15
.github/workflows/upload-conan-deps.yml
vendored
@@ -64,30 +64,32 @@ jobs:
|
||||
steps:
|
||||
- name: Cleanup workspace (macOS and Windows)
|
||||
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
||||
with:
|
||||
disable_ccache: true
|
||||
enable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6
|
||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
||||
|
||||
- name: Setup Conan
|
||||
env:
|
||||
SANITIZERS: ${{ matrix.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
conan_remote_name: ${{ env.CONAN_REMOTE_NAME }}
|
||||
conan_remote_url: ${{ env.CONAN_REMOTE_URL }}
|
||||
remote_name: ${{ env.CONAN_REMOTE_NAME }}
|
||||
remote_url: ${{ env.CONAN_REMOTE_URL }}
|
||||
|
||||
- name: Build dependencies
|
||||
uses: ./.github/actions/build-deps
|
||||
@@ -98,6 +100,7 @@ jobs:
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
|
||||
- name: Log into Conan remote
|
||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
# .gitignore
|
||||
# cspell: disable
|
||||
|
||||
# Macintosh Desktop Services Store files.
|
||||
.DS_Store
|
||||
@@ -63,7 +64,8 @@ DerivedData
|
||||
/.vs/
|
||||
/.vscode/
|
||||
|
||||
# zed IDE.
|
||||
/.zed/
|
||||
|
||||
# AI tools.
|
||||
/.augment
|
||||
/.claude
|
||||
/CLAUDE.md
|
||||
|
||||
@@ -26,30 +26,36 @@ repos:
|
||||
args: [--style=file]
|
||||
"types_or": [c++, c, proto]
|
||||
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
|
||||
hooks:
|
||||
- id: cmake-format
|
||||
additional_dependencies: [PyYAML]
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 25.11.0
|
||||
rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: v25.12.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
# - repo: https://github.com/streetsidesoftware/cspell-cli
|
||||
# rev: v9.2.0
|
||||
# hooks:
|
||||
# - id: cspell # Spell check changed files
|
||||
# - id: cspell # Spell check the commit message
|
||||
# name: check commit message spelling
|
||||
# args:
|
||||
# - --no-must-find-files
|
||||
# - --no-progress
|
||||
# - --no-summary
|
||||
# - --files
|
||||
# - .git/COMMIT_EDITMSG
|
||||
# stages: [commit-msg]
|
||||
# always_run: true # This might not be necessary.
|
||||
- repo: https://github.com/streetsidesoftware/cspell-cli
|
||||
rev: 1cfa010f078c354f3ffb8413616280cc28f5ba21 # frozen: v9.4.0
|
||||
hooks:
|
||||
- id: cspell # Spell check changed files
|
||||
exclude: .config/cspell.config.yaml
|
||||
- id: cspell # Spell check the commit message
|
||||
name: check commit message spelling
|
||||
args:
|
||||
- --no-must-find-files
|
||||
- --no-progress
|
||||
- --no-summary
|
||||
- --files
|
||||
- .git/COMMIT_EDITMSG
|
||||
stages: [commit-msg]
|
||||
|
||||
exclude: |
|
||||
(?x)^(
|
||||
|
||||
200
API-CHANGELOG.md
200
API-CHANGELOG.md
@@ -6,90 +6,85 @@ For info about how [API versioning](https://xrpl.org/request-formatting.html#api
|
||||
|
||||
The API version controls the API behavior you see. This includes what properties you see in responses, what parameters you're permitted to send in requests, and so on. You specify the API version in each of your requests. When a breaking change is introduced to the `rippled` API, a new version is released. To avoid breaking your code, you should set (or increase) your version when you're ready to upgrade.
|
||||
|
||||
The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code.
|
||||
|
||||
For a log of breaking changes, see the **API Version [number]** headings. In general, breaking changes are associated with a particular API Version number. For non-breaking changes, scroll to the **XRP Ledger version [x.y.z]** headings. Non-breaking changes are associated with a particular XRP Ledger (`rippled`) release.
|
||||
|
||||
## API Version 3 (Beta)
|
||||
|
||||
API version 3 is currently a beta API. It requires enabling `[beta_rpc_api]` in the rippled configuration to use. See [API-VERSION-3.md](API-VERSION-3.md) for the full list of changes in API version 3.
|
||||
|
||||
## API Version 2
|
||||
|
||||
API version 2 is available in `rippled` version 2.0.0 and later. To use this API, clients specify `"api_version" : 2` in each request.
|
||||
|
||||
#### Removed methods
|
||||
|
||||
In API version 2, the following deprecated methods are no longer available: (https://github.com/XRPLF/rippled/pull/4759)
|
||||
|
||||
- `tx_history` - Instead, use other methods such as `account_tx` or `ledger` with the `transactions` field set to `true`.
|
||||
- `ledger_header` - Instead, use the `ledger` method.
|
||||
|
||||
#### Modifications to JSON transaction element in V2
|
||||
|
||||
In API version 2, JSON elements for transaction output have been changed and made consistent for all methods which output transactions. (https://github.com/XRPLF/rippled/pull/4775)
|
||||
This helps to unify the JSON serialization format of transactions. (https://github.com/XRPLF/clio/issues/722, https://github.com/XRPLF/rippled/issues/4727)
|
||||
|
||||
- JSON transaction element is named `tx_json`
|
||||
- Binary transaction element is named `tx_blob`
|
||||
- JSON transaction metadata element is named `meta`
|
||||
- Binary transaction metadata element is named `meta_blob`
|
||||
|
||||
Additionally, these elements are now consistently available next to `tx_json` (i.e. sibling elements), where possible:
|
||||
|
||||
- `hash` - Transaction ID. This data was stored inside transaction output in API version 1, but in API version 2 is a sibling element.
|
||||
- `ledger_index` - Ledger index (only set on validated ledgers)
|
||||
- `ledger_hash` - Ledger hash (only set on closed or validated ledgers)
|
||||
- `close_time_iso` - Ledger close time expressed in ISO 8601 time format (only set on validated ledgers)
|
||||
- `validated` - Bool element set to `true` if the transaction is in a validated ledger, otherwise `false`
|
||||
|
||||
This change affects the following methods:
|
||||
|
||||
- `tx` - Transaction data moved into element `tx_json` (was inline inside `result`) or, if binary output was requested, moved from `tx` to `tx_blob`. Renamed binary transaction metadata element (if it was requested) from `meta` to `meta_blob`. Changed location of `hash` and added new elements
|
||||
- `account_tx` - Renamed transaction element from `tx` to `tx_json`. Renamed binary transaction metadata element (if it was requested) from `meta` to `meta_blob`. Changed location of `hash` and added new elements
|
||||
- `transaction_entry` - Renamed transaction metadata element from `metadata` to `meta`. Changed location of `hash` and added new elements
|
||||
- `subscribe` - Renamed transaction element from `transaction` to `tx_json`. Changed location of `hash` and added new elements
|
||||
- `sign`, `sign_for`, `submit` and `submit_multisigned` - Changed location of `hash` element.
|
||||
|
||||
#### Modification to `Payment` transaction JSON schema
|
||||
|
||||
When reading Payments, the `Amount` field should generally **not** be used. Instead, use [delivered_amount](https://xrpl.org/partial-payments.html#the-delivered_amount-field) to see the amount that the Payment delivered. To clarify its meaning, the `Amount` field is being renamed to `DeliverMax`. (https://github.com/XRPLF/rippled/pull/4733)
|
||||
|
||||
- In `Payment` transaction type, JSON RPC field `Amount` is renamed to `DeliverMax`. To enable smooth client transition, `Amount` is still handled, as described below: (https://github.com/XRPLF/rippled/pull/4733)
|
||||
- On JSON RPC input (e.g. `submit_multisigned` etc. methods), `Amount` is recognized as an alias to `DeliverMax` for both API version 1 and version 2 clients.
|
||||
- On JSON RPC input, submitting both `Amount` and `DeliverMax` fields is allowed _only_ if they are identical; otherwise such input is rejected with `rpcINVALID_PARAMS` error.
|
||||
- On JSON RPC output (e.g. `subscribe`, `account_tx` etc. methods), `DeliverMax` is present in both API version 1 and version 2.
|
||||
- On JSON RPC output, `Amount` is only present in API version 1 and _not_ in version 2.
|
||||
|
||||
#### Modifications to account_info response
|
||||
|
||||
- `signer_lists` is returned in the root of the response. (In API version 1, it was nested under `account_data`.) (https://github.com/XRPLF/rippled/pull/3770)
|
||||
- When using an invalid `signer_lists` value, the API now returns an "invalidParams" error. (https://github.com/XRPLF/rippled/pull/4585)
|
||||
- (`signer_lists` must be a boolean. In API version 1, strings were accepted and may return a normal response - i.e. as if `signer_lists` were `true`.)
|
||||
|
||||
#### Modifications to [account_tx](https://xrpl.org/account_tx.html#account_tx) response
|
||||
|
||||
- Using `ledger_index_min`, `ledger_index_max`, and `ledger_index` returns `invalidParams` because if you use `ledger_index_min` or `ledger_index_max`, then it does not make sense to also specify `ledger_index`. In API version 1, no error was returned. (https://github.com/XRPLF/rippled/pull/4571)
|
||||
- The same applies for `ledger_index_min`, `ledger_index_max`, and `ledger_hash`. (https://github.com/XRPLF/rippled/issues/4545#issuecomment-1565065579)
|
||||
- Using a `ledger_index_min` or `ledger_index_max` beyond the range of ledgers that the server has:
|
||||
- returns `lgrIdxMalformed` in API version 2. Previously, in API version 1, no error was returned. (https://github.com/XRPLF/rippled/issues/4288)
|
||||
- Attempting to use a non-boolean value (such as a string) for the `binary` or `forward` parameters returns `invalidParams` (`rpcINVALID_PARAMS`). Previously, in API version 1, no error was returned. (https://github.com/XRPLF/rippled/pull/4620)
|
||||
|
||||
#### Modifications to [noripple_check](https://xrpl.org/noripple_check.html#noripple_check) response
|
||||
|
||||
- Attempting to use a non-boolean value (such as a string) for the `transactions` parameter returns `invalidParams` (`rpcINVALID_PARAMS`). Previously, in API version 1, no error was returned. (https://github.com/XRPLF/rippled/pull/4620)
|
||||
API version 2 is available in `rippled` version 2.0.0 and later. See [API-VERSION-2.md](API-VERSION-2.md) for the full list of changes in API version 2.
|
||||
|
||||
## API Version 1
|
||||
|
||||
This version is supported by all `rippled` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
|
||||
|
||||
The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code.
|
||||
## XRP Ledger server version 3.1.0
|
||||
|
||||
### Inconsistency: server_info - network_id
|
||||
[Version 3.1.0](https://github.com/XRPLF/rippled/releases/tag/3.1.0) was released on Jan 27, 2026.
|
||||
|
||||
The `network_id` field was added in the `server_info` response in version 1.5.0 (2019), but it is not returned in [reporting mode](https://xrpl.org/rippled-server-modes.html#reporting-mode). However, use of reporting mode is now discouraged, in favor of using [Clio](https://github.com/XRPLF/clio) instead.
|
||||
### Additions in 3.1.0
|
||||
|
||||
- `vault_info`: New RPC method to retrieve information about a specific vault (part of XLS-66 Lending Protocol). ([#6156](https://github.com/XRPLF/rippled/pull/6156))
|
||||
|
||||
## XRP Ledger server version 3.0.0
|
||||
|
||||
[Version 3.0.0](https://github.com/XRPLF/rippled/releases/tag/3.0.0) was released on Dec 9, 2025.
|
||||
|
||||
### Additions in 3.0.0
|
||||
|
||||
- `ledger_entry`: Supports all ledger entry types with dedicated parsers. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
||||
- `ledger_entry`: New error codes `entryNotFound` and `unexpectedLedgerType` for more specific error handling. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
||||
- `ledger_entry`: Improved error messages with more context (e.g., specifying which field is invalid or missing). ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
||||
- `ledger_entry`: Assorted bug fixes in RPC processing. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
||||
- `simulate`: Supports additional metadata in the response. ([#5754](https://github.com/XRPLF/rippled/pull/5754))
|
||||
|
||||
## XRP Ledger server version 2.6.2
|
||||
|
||||
[Version 2.6.2](https://github.com/XRPLF/rippled/releases/tag/2.6.2) was released on Nov 19, 2025.
|
||||
|
||||
This release contains bug fixes only and no API changes.
|
||||
|
||||
## XRP Ledger server version 2.6.1
|
||||
|
||||
[Version 2.6.1](https://github.com/XRPLF/rippled/releases/tag/2.6.1) was released on Sep 30, 2025.
|
||||
|
||||
This release contains bug fixes only and no API changes.
|
||||
|
||||
## XRP Ledger server version 2.6.0
|
||||
|
||||
[Version 2.6.0](https://github.com/XRPLF/rippled/releases/tag/2.6.0) was released on Aug 27, 2025.
|
||||
|
||||
### Additions in 2.6.0
|
||||
|
||||
- `account_info`: Added `allowTrustLineLocking` flag in response. ([#5525](https://github.com/XRPLF/rippled/pull/5525))
|
||||
- `ledger`: Removed the type filter from the RPC command. ([#4934](https://github.com/XRPLF/rippled/pull/4934))
|
||||
- `subscribe` (`validations` stream): `network_id` is now included. ([#5579](https://github.com/XRPLF/rippled/pull/5579))
|
||||
- `subscribe` (`transactions` stream): `nftoken_id`, `nftoken_ids`, and `offer_id` are now included in transaction metadata. ([#5230](https://github.com/XRPLF/rippled/pull/5230))
|
||||
|
||||
## XRP Ledger server version 2.5.1
|
||||
|
||||
[Version 2.5.1](https://github.com/XRPLF/rippled/releases/tag/2.5.1) was released on Sep 17, 2025.
|
||||
|
||||
This release contains bug fixes only and no API changes.
|
||||
|
||||
## XRP Ledger server version 2.5.0
|
||||
|
||||
As of 2025-04-04, version 2.5.0 is in development. You can use a pre-release version by building from source or [using the `nightly` package](https://xrpl.org/docs/infrastructure/installation/install-rippled-on-ubuntu).
|
||||
[Version 2.5.0](https://github.com/XRPLF/rippled/releases/tag/2.5.0) was released on Jun 24, 2025.
|
||||
|
||||
### Additions and bugfixes in 2.5.0
|
||||
|
||||
- `channel_authorize`: If `signing_support` is not enabled in the config, the RPC is disabled.
|
||||
- `tx`: Added `ctid` field to the response and improved error handling. ([#4738](https://github.com/XRPLF/rippled/pull/4738))
|
||||
- `ledger_entry`: Improved error messages in `permissioned_domain`. ([#5344](https://github.com/XRPLF/rippled/pull/5344))
|
||||
- `simulate`: Improved multi-sign usage. ([#5479](https://github.com/XRPLF/rippled/pull/5479))
|
||||
- `channel_authorize`: If `signing_support` is not enabled in the config, the RPC is disabled. ([#5385](https://github.com/XRPLF/rippled/pull/5385))
|
||||
- `subscribe` (admin): Removed webhook queue limit to prevent dropping notifications; reduced HTTP timeout from 10 minutes to 30 seconds. ([#5163](https://github.com/XRPLF/rippled/pull/5163))
|
||||
- `ledger_data` (gRPC): Fixed crashing issue with some invalid markers. ([#5137](https://github.com/XRPLF/rippled/pull/5137))
|
||||
- `account_lines`: Fixed error with `no_ripple` and `no_ripple_peer` sometimes showing up incorrectly. ([#5345](https://github.com/XRPLF/rippled/pull/5345))
|
||||
- `account_tx`: Fixed issue with incorrect CTIDs. ([#5408](https://github.com/XRPLF/rippled/pull/5408))
|
||||
|
||||
## XRP Ledger server version 2.4.0
|
||||
|
||||
@@ -97,11 +92,19 @@ As of 2025-04-04, version 2.5.0 is in development. You can use a pre-release ver
|
||||
|
||||
### Additions and bugfixes in 2.4.0
|
||||
|
||||
- `ledger_entry`: `state` is added an alias for `ripple_state`.
|
||||
- `ledger_entry`: Enables case-insensitive filtering by canonical name in addition to case-sensitive filtering by RPC name.
|
||||
- `validators`: Added new field `validator_list_threshold` in response.
|
||||
- `simulate`: A new RPC that executes a [dry run of a transaction submission](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0069d-simulate#2-rpc-simulate)
|
||||
- Signing methods autofill fees better and properly handle transactions that don't have a base fee, and will also autofill the `NetworkID` field.
|
||||
- `simulate`: A new RPC that executes a [dry run of a transaction submission](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0069d-simulate#2-rpc-simulate). ([#5069](https://github.com/XRPLF/rippled/pull/5069))
|
||||
- Signing methods (`sign`, `sign_for`, `submit`): Autofill fees better, properly handle transactions without a base fee, and autofill the `NetworkID` field. ([#5069](https://github.com/XRPLF/rippled/pull/5069))
|
||||
- `ledger_entry`: `state` is added as an alias for `ripple_state`. ([#5199](https://github.com/XRPLF/rippled/pull/5199))
|
||||
- `ledger`, `ledger_data`, `account_objects`: Support filtering ledger entry types by their canonical names (case-insensitive). ([#5271](https://github.com/XRPLF/rippled/pull/5271))
|
||||
- `validators`: Added new field `validator_list_threshold` in response. ([#5112](https://github.com/XRPLF/rippled/pull/5112))
|
||||
- `server_info`: Added git commit hash info on admin connection. ([#5225](https://github.com/XRPLF/rippled/pull/5225))
|
||||
- `server_definitions`: Changed larger `UInt` serialized types to `Hash`. ([#5231](https://github.com/XRPLF/rippled/pull/5231))
|
||||
|
||||
## XRP Ledger server version 2.3.1
|
||||
|
||||
[Version 2.3.1](https://github.com/XRPLF/rippled/releases/tag/2.3.1) was released on Jan 29, 2025.
|
||||
|
||||
This release contains bug fixes only and no API changes.
|
||||
|
||||
## XRP Ledger server version 2.3.0
|
||||
|
||||
@@ -109,19 +112,30 @@ As of 2025-04-04, version 2.5.0 is in development. You can use a pre-release ver
|
||||
|
||||
### Breaking changes in 2.3.0
|
||||
|
||||
- `book_changes`: If the requested ledger version is not available on this node, a `ledgerNotFound` error is returned and the node does not attempt to acquire the ledger from the p2p network (as with other non-admin RPCs).
|
||||
|
||||
Admins can still attempt to retrieve old ledgers with the `ledger_request` RPC.
|
||||
- `book_changes`: If the requested ledger version is not available on this node, a `ledgerNotFound` error is returned and the node does not attempt to acquire the ledger from the p2p network (as with other non-admin RPCs). Admins can still attempt to retrieve old ledgers with the `ledger_request` RPC.
|
||||
|
||||
### Additions and bugfixes in 2.3.0
|
||||
|
||||
- `book_changes`: Returns a `validated` field in its response, which was missing in prior versions.
|
||||
- `book_changes`: Returns a `validated` field in its response. ([#5096](https://github.com/XRPLF/rippled/pull/5096))
|
||||
- `book_changes`: Accepts shortcut strings (`current`, `closed`, `validated`) for the `ledger_index` parameter. ([#5096](https://github.com/XRPLF/rippled/pull/5096))
|
||||
- `server_definitions`: Include `index` in response. ([#5190](https://github.com/XRPLF/rippled/pull/5190))
|
||||
- `account_nfts`: Fix issue where unassociated marker would return incorrect results. ([#5045](https://github.com/XRPLF/rippled/pull/5045))
|
||||
- `account_objects`: Fix issue where invalid marker would not return an error. ([#5046](https://github.com/XRPLF/rippled/pull/5046))
|
||||
- `account_objects`: Disallow filtering by ledger entry types that an account cannot hold. ([#5056](https://github.com/XRPLF/rippled/pull/5056))
|
||||
- `tx`: Allow lowercase CTID. ([#5049](https://github.com/XRPLF/rippled/pull/5049))
|
||||
- `feature`: Better error handling for invalid values of `feature`. ([#5063](https://github.com/XRPLF/rippled/pull/5063))
|
||||
|
||||
## XRP Ledger server version 2.2.0
|
||||
|
||||
[Version 2.2.0](https://github.com/XRPLF/rippled/releases/tag/2.2.0) was released on Jun 5, 2024. The following additions are non-breaking (because they are purely additive):
|
||||
|
||||
- The `feature` method now has a non-admin mode for users. (It was previously only available to admin connections.) The method returns an updated list of amendments, including their names and other information. ([#4781](https://github.com/XRPLF/rippled/pull/4781))
|
||||
- `feature`: Add a non-admin mode for users. (It was previously only available to admin connections.) The method returns an updated list of amendments, including their names and other information. ([#4781](https://github.com/XRPLF/rippled/pull/4781))
|
||||
|
||||
## XRP Ledger server version 2.0.1
|
||||
|
||||
[Version 2.0.1](https://github.com/XRPLF/rippled/releases/tag/2.0.1) was released on Jan 29, 2024. The following additions are non-breaking:
|
||||
|
||||
- `path_find`: Fixes unbounded memory growth. ([#4822](https://github.com/XRPLF/rippled/pull/4822))
|
||||
|
||||
## XRP Ledger server version 2.0.0
|
||||
|
||||
@@ -129,24 +143,18 @@ Admins can still attempt to retrieve old ledgers with the `ledger_request` RPC.
|
||||
|
||||
- `server_definitions`: A new RPC that generates a `definitions.json`-like output that can be used in XRPL libraries.
|
||||
- In `Payment` transactions, `DeliverMax` has been added. This is a replacement for the `Amount` field, which should not be used. Typically, the `delivered_amount` (in transaction metadata) should be used. To ease the transition, `DeliverMax` is present regardless of API version, since adding a field is non-breaking.
|
||||
- API version 2 has been moved from beta to supported, meaning that it is generally available (regardless of the `beta_rpc_api` setting).
|
||||
|
||||
## XRP Ledger server version 2.2.0
|
||||
|
||||
The following is a non-breaking addition to the API.
|
||||
|
||||
- The `feature` method now has a non-admin mode for users. (It was previously only available to admin connections.) The method returns an updated list of amendments, including their names and other information. ([#4781](https://github.com/XRPLF/rippled/pull/4781))
|
||||
- API version 2 has been moved from beta to supported, meaning that it is generally available (regardless of the `beta_rpc_api` setting). The full list of changes is in [API-VERSION-2.md](API-VERSION-2.md).
|
||||
|
||||
## XRP Ledger server version 1.12.0
|
||||
|
||||
[Version 1.12.0](https://github.com/XRPLF/rippled/releases/tag/1.12.0) was released on Sep 6, 2023. The following additions are non-breaking (because they are purely additive).
|
||||
[Version 1.12.0](https://github.com/XRPLF/rippled/releases/tag/1.12.0) was released on Sep 6, 2023. The following additions are non-breaking (because they are purely additive):
|
||||
|
||||
- `server_info`: Added `ports`, an array which advertises the RPC and WebSocket ports. This information is also included in the `/crawl` endpoint (which calls `server_info` internally). `grpc` and `peer` ports are also included. (https://github.com/XRPLF/rippled/pull/4427)
|
||||
- `server_info`: Added `ports`, an array which advertises the RPC and WebSocket ports. This information is also included in the `/crawl` endpoint (which calls `server_info` internally). `grpc` and `peer` ports are also included. ([#4427](https://github.com/XRPLF/rippled/pull/4427))
|
||||
- `ports` contains objects, each containing a `port` for the listening port (a number string), and a `protocol` array listing the supported protocols on that port.
|
||||
- This allows crawlers to build a more detailed topology without needing to port-scan nodes.
|
||||
- (For peers and other non-admin clients, the info about admin ports is excluded.)
|
||||
- Clawback: The following additions are gated by the Clawback amendment (`featureClawback`). (https://github.com/XRPLF/rippled/pull/4553)
|
||||
- Adds an [AccountRoot flag](https://xrpl.org/accountroot.html#accountroot-flags) called `lsfAllowTrustLineClawback` (https://github.com/XRPLF/rippled/pull/4617)
|
||||
- Clawback: The following additions are gated by the Clawback amendment (`featureClawback`). ([#4553](https://github.com/XRPLF/rippled/pull/4553))
|
||||
- Adds an [AccountRoot flag](https://xrpl.org/accountroot.html#accountroot-flags) called `lsfAllowTrustLineClawback`. ([#4617](https://github.com/XRPLF/rippled/pull/4617))
|
||||
- Adds the corresponding `asfAllowTrustLineClawback` [AccountSet Flag](https://xrpl.org/accountset.html#accountset-flags) as well.
|
||||
- Clawback is disabled by default, so if an issuer desires the ability to claw back funds, they must use an `AccountSet` transaction to set the AllowTrustLineClawback flag. They must do this before creating any trust lines, offers, escrows, payment channels, or checks.
|
||||
- Adds the [Clawback transaction type](https://github.com/XRPLF/XRPL-Standards/blob/master/XLS-39d-clawback/README.md#331-clawback-transaction), containing these fields:
|
||||
@@ -181,16 +189,16 @@ The following is a non-breaking addition to the API.
|
||||
|
||||
### Breaking changes in 1.11
|
||||
|
||||
- Added the ability to mark amendments as obsolete. For the `feature` admin API, there is a new possible value for the `vetoed` field. (https://github.com/XRPLF/rippled/pull/4291)
|
||||
- Added the ability to mark amendments as obsolete. For the `feature` admin API, there is a new possible value for the `vetoed` field. ([#4291](https://github.com/XRPLF/rippled/pull/4291))
|
||||
- The value of `vetoed` can now be `true`, `false`, or `"Obsolete"`.
|
||||
- Removed the acceptance of seeds or public keys in place of account addresses. (https://github.com/XRPLF/rippled/pull/4404)
|
||||
- Removed the acceptance of seeds or public keys in place of account addresses. ([#4404](https://github.com/XRPLF/rippled/pull/4404))
|
||||
- This simplifies the API and encourages better security practices (i.e. seeds should never be sent over the network).
|
||||
- For the `ledger_data` method, when all entries are filtered out, the `state` field of the response is now an empty list (in other words, an empty array, `[]`). (Previously, it would return `null`.) While this is technically a breaking change, the new behavior is consistent with the documentation, so this is considered only a bug fix. (https://github.com/XRPLF/rippled/pull/4398)
|
||||
- For the `ledger_data` method, when all entries are filtered out, the `state` field of the response is now an empty list (in other words, an empty array, `[]`). (Previously, it would return `null`.) While this is technically a breaking change, the new behavior is consistent with the documentation, so this is considered only a bug fix. ([#4398](https://github.com/XRPLF/rippled/pull/4398))
|
||||
- If and when the `fixNFTokenRemint` amendment activates, there will be a new AccountRoot field, `FirstNFTSequence`. This field is set to the current account sequence when the account issues their first NFT. If an account has not issued any NFTs, then the field is not set. ([#4406](https://github.com/XRPLF/rippled/pull/4406))
|
||||
- There is a new account deletion restriction: an account can only be deleted if `FirstNFTSequence` + `MintedNFTokens` + `256` is less than the current ledger sequence.
|
||||
- This is potentially a breaking change if clients have logic for determining whether an account can be deleted.
|
||||
- NetworkID
|
||||
- For sidechains and networks with a network ID greater than 1024, there is a new [transaction common field](https://xrpl.org/transaction-common-fields.html), `NetworkID`. (https://github.com/XRPLF/rippled/pull/4370)
|
||||
- For sidechains and networks with a network ID greater than 1024, there is a new [transaction common field](https://xrpl.org/transaction-common-fields.html), `NetworkID`. ([#4370](https://github.com/XRPLF/rippled/pull/4370))
|
||||
- This field helps to prevent replay attacks and is now required for chains whose network ID is 1025 or higher.
|
||||
- The field must be omitted for Mainnet, so there is no change for Mainnet users.
|
||||
- There are three new local error codes:
|
||||
@@ -200,10 +208,10 @@ The following is a non-breaking addition to the API.
|
||||
|
||||
### Additions and bug fixes in 1.11
|
||||
|
||||
- Added `nftoken_id`, `nftoken_ids` and `offer_id` meta fields into NFT `tx` and `account_tx` responses. (https://github.com/XRPLF/rippled/pull/4447)
|
||||
- Added an `account_flags` object to the `account_info` method response. (https://github.com/XRPLF/rippled/pull/4459)
|
||||
- Added `NFTokenPages` to the `account_objects` RPC. (https://github.com/XRPLF/rippled/pull/4352)
|
||||
- Fixed: `marker` returned from the `account_lines` command would not work on subsequent commands. (https://github.com/XRPLF/rippled/pull/4361)
|
||||
- Added `nftoken_id`, `nftoken_ids` and `offer_id` meta fields into NFT `tx` and `account_tx` responses. ([#4447](https://github.com/XRPLF/rippled/pull/4447))
|
||||
- Added an `account_flags` object to the `account_info` method response. ([#4459](https://github.com/XRPLF/rippled/pull/4459))
|
||||
- Added `NFTokenPages` to the `account_objects` RPC. ([#4352](https://github.com/XRPLF/rippled/pull/4352))
|
||||
- Fixed: `marker` returned from the `account_lines` command would not work on subsequent commands. ([#4361](https://github.com/XRPLF/rippled/pull/4361))
|
||||
|
||||
## XRP Ledger server version 1.10.0
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user