mirror of
https://github.com/XRPLF/rippled.git
synced 2026-03-11 07:12:28 +00:00
Compare commits
42 Commits
pratik/Aut
...
pratik/Fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95847d1aa3 | ||
|
|
064a4344ec | ||
|
|
f8ba66cec3 | ||
|
|
42da2dda66 | ||
|
|
b9a08c1772 | ||
|
|
171a45321a | ||
|
|
d71f66ef54 | ||
|
|
5083457cda | ||
|
|
fc9a53a4dc | ||
|
|
5f2b237727 | ||
|
|
eab9c7b82a | ||
|
|
9ff374d190 | ||
|
|
abb6a0db87 | ||
|
|
8f3947acf2 | ||
|
|
2cd7cdd053 | ||
|
|
ce6c7ed2f9 | ||
|
|
ca1fc0f524 | ||
|
|
63c9874299 | ||
|
|
5956430d8c | ||
|
|
2201264858 | ||
|
|
76a49000e1 | ||
|
|
ec64579e22 | ||
|
|
7319b8f46b | ||
|
|
0893228637 | ||
|
|
2397ad7e9b | ||
|
|
e8ca732fa4 | ||
|
|
f04338a1e1 | ||
|
|
b926559def | ||
|
|
550ba266fc | ||
|
|
6b94f7ae91 | ||
|
|
09b8602bd7 | ||
|
|
cf3bedb007 | ||
|
|
9bad60173e | ||
|
|
580de04cfc | ||
|
|
4a8c6c884f | ||
|
|
8eda79000d | ||
|
|
5d58331ad6 | ||
|
|
376abfc80b | ||
|
|
17479dd209 | ||
|
|
b405d2326b | ||
|
|
45e53a885a | ||
|
|
78f4ef1a65 |
@@ -31,7 +31,6 @@ Checks: "-*,
|
||||
bugprone-no-escape,
|
||||
bugprone-non-zero-enum-to-bool-conversion,
|
||||
bugprone-parent-virtual-call,
|
||||
bugprone-pointer-arithmetic-on-polymorphic-object,
|
||||
bugprone-posix-return,
|
||||
bugprone-redundant-branch-condition,
|
||||
bugprone-return-const-ref-from-parameter,
|
||||
@@ -96,6 +95,7 @@ Checks: "-*,
|
||||
# bugprone-move-forwarding-reference,
|
||||
# bugprone-switch-missing-default-case,
|
||||
# bugprone-suspicious-stringview-data-usage,
|
||||
# bugprone-pointer-arithmetic-on-polymorphic-object,
|
||||
# bugprone-optional-value-conversion,
|
||||
# bugprone-too-small-loop-variable,
|
||||
# bugprone-unused-return-value,
|
||||
|
||||
10
.github/workflows/reusable-build-test-config.yml
vendored
10
.github/workflows/reusable-build-test-config.yml
vendored
@@ -76,7 +76,7 @@ jobs:
|
||||
name: ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 60
|
||||
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 60 }}
|
||||
env:
|
||||
# Use a namespace to keep the objects separate for each configuration.
|
||||
CCACHE_NAMESPACE: ${{ inputs.config_name }}
|
||||
@@ -204,8 +204,14 @@ jobs:
|
||||
|
||||
- name: Set sanitizer options
|
||||
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
|
||||
env:
|
||||
CONFIG_NAME: ${{ inputs.config_name }}
|
||||
run: |
|
||||
echo "ASAN_OPTIONS=print_stacktrace=1:detect_container_overflow=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp" >> ${GITHUB_ENV}
|
||||
ASAN_OPTS="halt_on_error=0:use_sigaltstack=0:print_stacktrace=1:detect_container_overflow=0:detect_stack_use_after_return=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
|
||||
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
|
||||
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
|
||||
fi
|
||||
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${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}
|
||||
|
||||
@@ -18,12 +18,10 @@ find_dependency(
|
||||
chrono
|
||||
container
|
||||
context
|
||||
coroutine
|
||||
date_time
|
||||
filesystem
|
||||
program_options
|
||||
regex
|
||||
system
|
||||
thread
|
||||
)
|
||||
#[=========================================================[
|
||||
|
||||
@@ -23,7 +23,7 @@ target_compile_definitions(
|
||||
BOOST_FILESYSTEM_NO_DEPRECATED
|
||||
>
|
||||
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
|
||||
BOOST_COROUTINES_NO_DEPRECATION_WARNING
|
||||
BOOST_COROUTINES2_NO_DEPRECATION_WARNING
|
||||
BOOST_BEAST_ALLOW_DEPRECATED
|
||||
BOOST_FILESYSTEM_DEPRECATED
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@ find_package(
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
coroutine
|
||||
context
|
||||
date_time
|
||||
filesystem
|
||||
json
|
||||
@@ -26,7 +26,7 @@ target_link_libraries(
|
||||
Boost::headers
|
||||
Boost::chrono
|
||||
Boost::container
|
||||
Boost::coroutine
|
||||
Boost::context
|
||||
Boost::date_time
|
||||
Boost::filesystem
|
||||
Boost::json
|
||||
@@ -38,23 +38,38 @@ target_link_libraries(
|
||||
if(Boost_COMPILER)
|
||||
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
|
||||
endif()
|
||||
if(SANITIZERS_ENABLED AND is_clang)
|
||||
# TODO: gcc does not support -fsanitize-blacklist...can we do something else for gcc ?
|
||||
if(NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
|
||||
get_target_property(
|
||||
Boost_INCLUDE_DIRS
|
||||
Boost::headers
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
)
|
||||
endif()
|
||||
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
|
||||
file(
|
||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt
|
||||
"src:${Boost_INCLUDE_DIRS}/*"
|
||||
)
|
||||
target_compile_options(
|
||||
opts
|
||||
INTERFACE # ignore boost headers for sanitizing
|
||||
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt
|
||||
|
||||
# GCC 14+ has a false positive -Wuninitialized warning in Boost.Coroutine2's
|
||||
# state.hpp when compiled with -O3. This is due to GCC's intentional behavior
|
||||
# change (Bug #98871, #119388) where warnings from inlined system header code
|
||||
# are no longer suppressed by -isystem. The warning occurs in operator|= in
|
||||
# boost/coroutine2/detail/state.hpp when inlined from push_control_block::destroy().
|
||||
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119388
|
||||
if(is_gcc AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14)
|
||||
target_compile_options(xrpl_boost INTERFACE -Wno-uninitialized)
|
||||
endif()
|
||||
|
||||
# Boost.Context's ucontext backend has ASAN fiber-switching annotations
|
||||
# (start/finish_switch_fiber) that are compiled in when BOOST_USE_ASAN is defined.
|
||||
# This tells ASAN about coroutine stack switches, preventing false positive
|
||||
# stack-use-after-scope errors. BOOST_USE_UCONTEXT ensures the ucontext backend
|
||||
# is selected (fcontext does not support ASAN annotations).
|
||||
# These defines must match what Boost was compiled with (see conan/profiles/sanitizers).
|
||||
if(enable_asan)
|
||||
target_compile_definitions(
|
||||
xrpl_boost
|
||||
INTERFACE BOOST_USE_ASAN BOOST_USE_UCONTEXT
|
||||
)
|
||||
endif()
|
||||
|
||||
# if (SANITIZERS_ENABLED AND is_clang)
|
||||
# # TODO: gcc does not support -fsanitize-blacklist...can we do something else for gcc ?
|
||||
# if (NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
|
||||
# get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
|
||||
# endif ()
|
||||
# message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
|
||||
# file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
|
||||
# target_compile_options(
|
||||
# opts INTERFACE # ignore boost headers for sanitizing
|
||||
# -fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
|
||||
# endif ()
|
||||
|
||||
@@ -7,16 +7,21 @@ include(default)
|
||||
{% if compiler == "gcc" %}
|
||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||
{% set sanitizer_list = [] %}
|
||||
{% set defines = [] %}
|
||||
{% set model_code = "" %}
|
||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %}
|
||||
|
||||
{% if "address" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("address") %}
|
||||
{% set model_code = "-mcmodel=large" %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% elif "thread" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("thread") %}
|
||||
{% set model_code = "-mcmodel=medium" %}
|
||||
{% set _ = extra_cxxflags.append("-Wno-tsan") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% endif %}
|
||||
|
||||
{% if "undefinedbehavior" in sanitizers %}
|
||||
@@ -29,16 +34,22 @@ include(default)
|
||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:defines+={{defines}}
|
||||
{% endif %}
|
||||
{% elif compiler == "apple-clang" or compiler == "clang" %}
|
||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||
{% set sanitizer_list = [] %}
|
||||
{% set defines = [] %}
|
||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %}
|
||||
|
||||
{% if "address" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("address") %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% elif "thread" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("thread") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% endif %}
|
||||
|
||||
{% if "undefinedbehavior" in sanitizers %}
|
||||
@@ -52,8 +63,24 @@ include(default)
|
||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:defines+={{defines}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
||||
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||
|
||||
[options]
|
||||
{% if sanitizers %}
|
||||
{% if "address" in sanitizers %}
|
||||
# Build Boost.Context with ucontext backend (not fcontext) so that
|
||||
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
||||
# are compiled into the library. fcontext (assembly) has no ASAN support.
|
||||
# define=BOOST_USE_ASAN=1 is critical: it must be defined when building
|
||||
# Boost.Context itself so the ucontext backend compiles in the ASAN annotations.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext address-sanitizer=on define=BOOST_USE_ASAN=1
|
||||
boost/*:without_context=False
|
||||
# Boost stacktrace fails to build with some sanitizers
|
||||
boost/*:without_stacktrace=True
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
15
conanfile.py
15
conanfile.py
@@ -1,4 +1,5 @@
|
||||
import re
|
||||
import os
|
||||
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
|
||||
@@ -57,6 +58,9 @@ class Xrpl(ConanFile):
|
||||
"tests": False,
|
||||
"unity": False,
|
||||
"xrpld": False,
|
||||
"boost/*:without_context": False,
|
||||
"boost/*:without_coroutine": True,
|
||||
"boost/*:without_coroutine2": False,
|
||||
"date/*:header_only": True,
|
||||
"ed25519/*:shared": False,
|
||||
"grpc/*:shared": False,
|
||||
@@ -125,6 +129,14 @@ class Xrpl(ConanFile):
|
||||
self.options["boost"].visibility = "global"
|
||||
if self.settings.compiler in ["clang", "gcc"]:
|
||||
self.options["boost"].without_cobalt = True
|
||||
self.options["boost"].without_context = False
|
||||
self.options["boost"].without_coroutine = True
|
||||
self.options["boost"].without_coroutine2 = False
|
||||
# Check if environment variable exists
|
||||
if "SANITIZERS" in os.environ:
|
||||
sanitizers = os.environ["SANITIZERS"]
|
||||
if "address" in sanitizers.lower():
|
||||
self.default_options["fPIC"] = False
|
||||
|
||||
def requirements(self):
|
||||
# Conan 2 requires transitive headers to be specified
|
||||
@@ -196,7 +208,8 @@ class Xrpl(ConanFile):
|
||||
"boost::headers",
|
||||
"boost::chrono",
|
||||
"boost::container",
|
||||
"boost::coroutine",
|
||||
"boost::context",
|
||||
"boost::coroutine2",
|
||||
"boost::date_time",
|
||||
"boost::filesystem",
|
||||
"boost::json",
|
||||
|
||||
@@ -43,7 +43,6 @@ suggestWords:
|
||||
- synch->sync
|
||||
words:
|
||||
- abempty
|
||||
- Agentic
|
||||
- AMMID
|
||||
- amt
|
||||
- amts
|
||||
@@ -95,12 +94,12 @@ words:
|
||||
- desynced
|
||||
- determ
|
||||
- distro
|
||||
- Emdash
|
||||
- doxyfile
|
||||
- dxrpl
|
||||
- endmacro
|
||||
- exceptioned
|
||||
- Falco
|
||||
- fcontext
|
||||
- finalizers
|
||||
- firewalled
|
||||
- fmtdur
|
||||
@@ -256,7 +255,6 @@ words:
|
||||
- superpeers
|
||||
- takergets
|
||||
- takerpays
|
||||
- Tauri
|
||||
- ters
|
||||
- TMEndpointv2
|
||||
- trixie
|
||||
@@ -296,7 +294,6 @@ words:
|
||||
- venv
|
||||
- vfalco
|
||||
- vinnie
|
||||
- Werror
|
||||
- wextra
|
||||
- wptr
|
||||
- writeme
|
||||
@@ -313,4 +310,3 @@ words:
|
||||
- xrplf
|
||||
- xxhash
|
||||
- xxhasher
|
||||
- zeroization
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
# rippled Architecture Map
|
||||
|
||||
> **Purpose**: Tell agents _where_ things are. Not _why_ they exist.
|
||||
> **Audience**: AI coding agents (Claude Code, Codex, Copilot) navigating the codebase.
|
||||
> **Principle**: "Give agents a map, not an encyclopedia." — [Harness Engineering](./harness-engineering-report.md)
|
||||
|
||||
---
|
||||
|
||||
## Layer Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ RPC Layer (Layer 5) │
|
||||
│ HTTP/WebSocket → ServerHandler → 72 RPC Handlers │
|
||||
│ src/xrpld/rpc/ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Application Layer (Layer 4) │
|
||||
│ NetworkOPs · TxQ · PathFinding · LedgerMaster │
|
||||
│ src/xrpld/app/ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Consensus Layer (Layer 3) │
|
||||
│ Consensus<Adaptor> · RCLConsensus · Validations │
|
||||
│ src/xrpld/consensus/ + src/xrpld/app/consensus/ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Overlay Layer (Layer 2) │
|
||||
│ OverlayImpl · PeerImp · PeerFinder · Message │
|
||||
│ src/xrpld/overlay/ + src/xrpld/peerfinder/ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Storage Layer (Layer 1) │
|
||||
│ NodeStore (RocksDB/SQLite) · SHAMap · RDB │
|
||||
│ src/libxrpl/nodestore/ + src/libxrpl/shamap/ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Foundation (Layer 0) │
|
||||
│ beast:: (I/O, insight, clock) · protocol · crypto · json │
|
||||
│ src/libxrpl/ + include/xrpl/ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Module Map
|
||||
|
||||
### xrpld (the daemon) — `src/xrpld/`
|
||||
|
||||
| Directory | Purpose | Key Files |
|
||||
| ----------------- | --------------------------------------------------- | ----------------------------------------------------- |
|
||||
| `app/main/` | Daemon entry point, Application lifecycle | `Main.cpp`, `Application.h/.cpp`, `BasicApp.h` |
|
||||
| `app/consensus/` | Consensus adaptor binding protocol to rippled types | `RCLConsensus.h/.cpp` |
|
||||
| `app/ledger/` | Ledger management, building, acquiring | `LedgerMaster.h`, `InboundLedgers.h` |
|
||||
| `app/misc/` | NetworkOPs, TxQ, HashRouter, Amendments | `NetworkOPs.h/.cpp`, `TxQ.h`, `HashRouter.h` |
|
||||
| `app/tx/` | Transaction application engine | `apply.h/.cpp`, `applySteps.h` |
|
||||
| `app/paths/` | Payment path finding | `Pathfinder.h`, `PathRequest.h` |
|
||||
| `app/rdb/` | Relational DB backend for state | `RelationalDatabase.h` |
|
||||
| `consensus/` | Generic consensus protocol (template-based) | `Consensus.h/.cpp`, `ConsensusParms.h` |
|
||||
| `core/` | Node configuration, time keeping | `Config.h/.cpp`, `TimeKeeper.h` |
|
||||
| `overlay/` | P2P network: peer connections, message routing | `Overlay.h`, `Peer.h`, `Message.h` |
|
||||
| `overlay/detail/` | Overlay implementation internals | `OverlayImpl.h/.cpp`, `PeerImp.h/.cpp`, `Handshake.h` |
|
||||
| `peerfinder/` | Peer discovery and bootstrap | `PeerfinderManager.h`, `detail/Logic.h` |
|
||||
| `perflog/` | Performance logging (pre-OTel telemetry) | `detail/PerfLogImp.h/.cpp` |
|
||||
| `rpc/` | JSON-RPC server and routing | `detail/Handler.h`, `RPCHandler.h` |
|
||||
| `rpc/handlers/` | **72 RPC command implementations** | `AccountInfo.cpp`, `Submit.cpp`, `Tx.cpp`, etc. |
|
||||
| `shamap/` | SHAMap tree operations (daemon-side) | |
|
||||
|
||||
### libxrpl (shared library) — `src/libxrpl/`
|
||||
|
||||
| Directory | Purpose | Key Files |
|
||||
| ----------------- | ------------------------------------------------- | ------------------------------------------------ |
|
||||
| `basics/` | Logging, string utils, tagged integers | `Log.cpp` (log formatting — Phase 8 OTel target) |
|
||||
| `beast/insight/` | Metrics framework (StatsD, Gauge, Counter, Event) | `StatsDCollector.cpp` (Phase 6-7 OTel target) |
|
||||
| `beast/core/` | Async I/O primitives | `CurrentThreadName.cpp` |
|
||||
| `core/` | Crypto, seed handling | |
|
||||
| `crypto/` | Ed25519, secp256k1, SHA | |
|
||||
| `json/` | JSON parser/writer | |
|
||||
| `nodestore/` | Key-value storage for ledger nodes | `backend/RocksDBFactory.cpp` |
|
||||
| `protocol/` | XRPL protocol: serialization, STObject, STTx | `STTx.cpp`, `STObject.cpp` |
|
||||
| `server/` | HTTP/WebSocket server core | `ServerHandler.h` |
|
||||
| `tx/transactors/` | Per-transaction-type execution logic | `Payment.cpp`, `CreateOffer.cpp`, etc. |
|
||||
| `tx/invariants/` | Transaction invariant checks | `TransactionCheck.cpp` |
|
||||
|
||||
### Public Headers — `include/xrpl/`
|
||||
|
||||
Mirrors `src/libxrpl/` structure. Agent-accessible API surface for external consumers of libxrpl.
|
||||
|
||||
Key subdirectory: `include/xrpl/proto/org/xrpl/rpc/v1/` — Protocol Buffer definitions for gRPC API.
|
||||
|
||||
---
|
||||
|
||||
## Entry Points
|
||||
|
||||
| Operation | Where execution starts | Hot path |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------ | --------------- |
|
||||
| **RPC request** | `src/xrpld/rpc/detail/ServerHandler.cpp` → handler lookup → `src/xrpld/rpc/handlers/*.cpp` | Layer 5 → 4 |
|
||||
| **Peer message** | `src/xrpld/overlay/detail/PeerImp.cpp::onMessage()` → message-type dispatch | Layer 2 → 3/4 |
|
||||
| **Transaction submit** | `rpc/handlers/Submit.cpp` → `app/misc/NetworkOPs.cpp::submitTransaction()` | Layer 5 → 4 → 2 |
|
||||
| **Transaction relay** | `overlay/detail/PeerImp.cpp::handleTransaction()` → `NetworkOPs::processTransaction()` | Layer 2 → 4 |
|
||||
| **Consensus round** | `app/consensus/RCLConsensus.cpp::startRound()` → phase transitions → accept | Layer 3 |
|
||||
| **Ledger close** | `RCLConsensus.cpp::onClose()` → `acceptLedger()` → apply transactions | Layer 3 → 4 → 1 |
|
||||
| **Ledger acquire** | `app/ledger/InboundLedgers.cpp::acquire()` → peer fetch → SHAMap | Layer 4 → 2 → 1 |
|
||||
| **Startup** | `app/main/Main.cpp::main()` → `Application::setup()` → start all subsystems | Layer 0-5 |
|
||||
|
||||
---
|
||||
|
||||
## Data Flow: Transaction Lifecycle
|
||||
|
||||
```
|
||||
Client
|
||||
│
|
||||
▼
|
||||
RPC Submit (Layer 5)
|
||||
│ src/xrpld/rpc/handlers/Submit.cpp
|
||||
▼
|
||||
NetworkOPs::submitTransaction() (Layer 4)
|
||||
│ src/xrpld/app/misc/NetworkOPs.cpp
|
||||
├──▶ TxQ::apply() — queue management
|
||||
│ src/xrpld/app/misc/TxQ.cpp
|
||||
├──▶ HashRouter::setFlags() — deduplication
|
||||
│ src/xrpld/app/misc/HashRouter.cpp
|
||||
▼
|
||||
Overlay::relay() (Layer 2)
|
||||
│ src/xrpld/overlay/detail/OverlayImpl.cpp
|
||||
├──▶ PeerImp::send() — to each connected peer
|
||||
│ src/xrpld/overlay/detail/PeerImp.cpp
|
||||
▼
|
||||
[Remote Node] PeerImp::handleTransaction() (Layer 2)
|
||||
│ src/xrpld/overlay/detail/PeerImp.cpp
|
||||
▼
|
||||
Consensus::startRound() (Layer 3)
|
||||
│ src/xrpld/consensus/Consensus.h
|
||||
│ src/xrpld/app/consensus/RCLConsensus.cpp
|
||||
├──▶ propose() — send position to peers
|
||||
├──▶ onClose() — close the ledger
|
||||
▼
|
||||
acceptLedger() → applyTransactions() (Layer 3 → 1)
|
||||
│ src/xrpld/app/consensus/RCLConsensus.cpp
|
||||
▼
|
||||
NodeStore::store() (Layer 1)
|
||||
│ src/libxrpl/nodestore/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build Targets
|
||||
|
||||
| Target | Type | Source |
|
||||
| -------------------- | ------------------------- | -------------------------------- |
|
||||
| `xrpl` | Shared library (libxrpl) | `src/libxrpl/` + `include/xrpl/` |
|
||||
| `xrpld` | Executable (daemon) | `src/xrpld/` |
|
||||
| `rippled_unit_tests` | Unit test binary | `src/test/` |
|
||||
| `libxrpl_tests` | Library integration tests | `src/tests/libxrpl/` |
|
||||
|
||||
**Build command**: `cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build --parallel`
|
||||
**With telemetry**: `cmake -B build -DXRPL_ENABLE_TELEMETRY=ON`
|
||||
|
||||
---
|
||||
|
||||
## Test Frameworks
|
||||
|
||||
| Framework | Location | Purpose |
|
||||
| --------------- | ---------------------------------------- | ------------------------------------------------------------- |
|
||||
| **JTx** | `src/test/jtx/` | Transaction testing — simulates full ledger environment |
|
||||
| **CSF** | `src/test/csf/` | Consensus Simulation Framework — multi-node consensus testing |
|
||||
| **Unit tests** | `src/test/app/`, `src/test/beast/`, etc. | Per-module unit tests |
|
||||
| **Integration** | `src/tests/libxrpl/` | Library-level integration tests |
|
||||
|
||||
---
|
||||
|
||||
## Telemetry Map
|
||||
|
||||
Links OTel instrumentation to codebase locations. See [09-data-collection-reference.md](../../OpenTelemetryPlan/09-data-collection-reference.md) for the full inventory.
|
||||
|
||||
| Span | Source Location | Layer |
|
||||
| ------------- | ------------------------------------------ | ----- |
|
||||
| `rpc.*` | `src/xrpld/rpc/detail/ServerHandler.cpp` | 5 |
|
||||
| `tx.submit` | `src/xrpld/app/misc/NetworkOPs.cpp` | 4 |
|
||||
| `tx.relay` | `src/xrpld/overlay/detail/PeerImp.cpp` | 2 |
|
||||
| `peer.send` | `src/xrpld/overlay/detail/PeerImp.cpp` | 2 |
|
||||
| `consensus.*` | `src/xrpld/app/consensus/RCLConsensus.cpp` | 3 |
|
||||
| `ledger.*` | `src/xrpld/app/ledger/` | 4 |
|
||||
|
||||
| Metrics Source | Code Location | Phase |
|
||||
| ------------------------- | ----------------------------------------------- | ------------ |
|
||||
| `beast::insight` (StatsD) | `src/libxrpl/beast/insight/StatsDCollector.cpp` | 6-7 |
|
||||
| SpanMetrics (derived) | OTel Collector config | 5 |
|
||||
| PerfLog | `src/xrpld/perflog/detail/PerfLogImp.cpp` | 9 (gap fill) |
|
||||
|
||||
---
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
| Abstraction | Interface | Implementation | What it does |
|
||||
| --------------------------- | ---------------------------------------- | ------------------------------------------------------------- | -------------------------------------- |
|
||||
| `Application` | `src/xrpld/app/main/Application.h` | `Application.cpp` | Wires all subsystems together |
|
||||
| `Overlay` | `src/xrpld/overlay/Overlay.h` | `detail/OverlayImpl.cpp` | Manages P2P connections |
|
||||
| `Consensus<>` | `src/xrpld/consensus/Consensus.h` | Template, adaptor in `RCLConsensus.cpp` | Generic consensus protocol |
|
||||
| `NetworkOPs` | `src/xrpld/app/misc/NetworkOPs.h` | `NetworkOPs.cpp` | Transaction processing, event dispatch |
|
||||
| `LedgerMaster` | `src/xrpld/app/ledger/LedgerMaster.h` | `LedgerMaster.cpp` | Ledger lifecycle management |
|
||||
| `NodeStore` | `include/xrpl/nodestore/Database.h` | `src/libxrpl/nodestore/` | Persistent key-value storage |
|
||||
| `beast::insight::Collector` | `include/xrpl/beast/insight/Collector.h` | `StatsDCollector`, `NullCollector`, (future: `OTelCollector`) | Metrics collection interface |
|
||||
| `JobQueue` | `src/xrpld/core/JobQueue.h` | `JobQueue.cpp` | Async task scheduling |
|
||||
| `SHAMap` | `include/xrpl/shamap/SHAMap.h` | `src/libxrpl/shamap/` | Merkle tree for state |
|
||||
|
||||
---
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
```
|
||||
Layer 5 (RPC) → may call → Layer 4 (App)
|
||||
Layer 4 (App) → may call → Layer 3 (Consensus), Layer 2 (Overlay), Layer 1 (Storage)
|
||||
Layer 3 (Consensus) → may call → Layer 4 (App via Adaptor), Layer 1 (Storage)
|
||||
Layer 2 (Overlay) → may call → Layer 4 (App for message handling)
|
||||
Layer 1 (Storage) → may call → Layer 0 (Foundation) only
|
||||
Layer 0 (Foundation) → no upward dependencies
|
||||
```
|
||||
|
||||
**Never**: Layer 0/1 must never depend on Layer 3/4/5. Layer 5 must never bypass Layer 4 to reach Layer 2/3 directly.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
| File | Location | Purpose |
|
||||
| ----------------------- | -------- | ------------------------- |
|
||||
| `xrpld.cfg` | `cfg/` | Main daemon configuration |
|
||||
| `validators.txt` | `cfg/` | Validator list |
|
||||
| `CMakeUserPresets.json` | Root | Local build presets |
|
||||
| `conanfile.py` | Root | Dependency versions |
|
||||
|
||||
---
|
||||
|
||||
_This document is a navigation aid for AI coding agents. For architectural rationale, see [docs/consensus.md](consensus.md). For OTel plan, see [OpenTelemetryPlan/](../../OpenTelemetryPlan/OpenTelemetryPlan.md). For coding conventions, see [docs/CodingStyle.md](CodingStyle.md)._
|
||||
196
docs/WORKFLOW.md
196
docs/WORKFLOW.md
@@ -1,196 +0,0 @@
|
||||
---
|
||||
# Symphony-compatible workflow definition for rippled
|
||||
# See: https://github.com/openai/symphony/blob/main/SPEC.md
|
||||
# See: docs/harness-engineering-report.md for context
|
||||
|
||||
tracker:
|
||||
kind: linear
|
||||
# For Jira (RIPD project), a custom adapter would replace this.
|
||||
# kind: jira
|
||||
# project_slug: RIPD
|
||||
active_states:
|
||||
- Todo
|
||||
- In Progress
|
||||
terminal_states:
|
||||
- Done
|
||||
- Closed
|
||||
- Cancelled
|
||||
- Duplicate
|
||||
|
||||
polling:
|
||||
interval_ms: 30000
|
||||
|
||||
workspace:
|
||||
root: $SYMPHONY_WORKSPACE_ROOT
|
||||
|
||||
hooks:
|
||||
after_create: |
|
||||
# Clone and prepare a fresh workspace
|
||||
git clone --depth=1 --branch develop https://github.com/XRPLF/rippled.git .
|
||||
# Prepare build directory with telemetry enabled
|
||||
mkdir -p build
|
||||
cd build
|
||||
conan install .. --output-folder=. --build=missing
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DXRPL_ENABLE_TELEMETRY=ON -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||
|
||||
before_run: |
|
||||
# Tier 1: Fast checks (seconds)
|
||||
# clang-format check on changed files
|
||||
git diff --name-only HEAD~1 -- '*.cpp' '*.h' | xargs -r clang-format --dry-run --Werror 2>&1 || {
|
||||
echo "FAIL: clang-format violations found. Fix formatting before proceeding."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Tier 2: Build (minutes)
|
||||
cd build
|
||||
cmake --build . --parallel $(nproc) 2>&1 || {
|
||||
echo "FAIL: Build failed. Check compiler errors above."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Tier 2: Unit tests (affected modules)
|
||||
ctest --test-dir build --output-on-failure -L unit --timeout 120 2>&1 || {
|
||||
echo "FAIL: Unit tests failed. Check test output above."
|
||||
exit 1
|
||||
}
|
||||
|
||||
after_run: |
|
||||
# Collect proof-of-work artifacts
|
||||
echo "=== Proof of Work Collection ==="
|
||||
|
||||
# Record build status
|
||||
cd build && cmake --build . --parallel $(nproc) 2>&1
|
||||
BUILD_STATUS=$?
|
||||
echo "Build status: $BUILD_STATUS"
|
||||
|
||||
# Run telemetry integration tests if available
|
||||
if ctest --test-dir build -L telemetry --timeout 300 2>&1; then
|
||||
echo "Telemetry integration tests: PASSED"
|
||||
else
|
||||
echo "Telemetry integration tests: FAILED (non-blocking)"
|
||||
fi
|
||||
|
||||
# Capture complexity metrics
|
||||
echo "=== Changed Files ==="
|
||||
git diff --stat HEAD~1
|
||||
|
||||
timeout_ms: 120000
|
||||
|
||||
agent:
|
||||
max_concurrent_agents: 3
|
||||
max_retry_backoff_ms: 300000
|
||||
max_concurrent_agents_by_state:
|
||||
In Progress: 2
|
||||
Todo: 1
|
||||
|
||||
codex:
|
||||
command: codex app-server
|
||||
approval_policy: unless-allow-listed
|
||||
turn_timeout_ms: 3600000
|
||||
stall_timeout_ms: 300000
|
||||
---
|
||||
|
||||
# rippled Agent Workflow
|
||||
|
||||
You are an autonomous coding agent working on the **rippled** XRP Ledger node — a C++20 peer-to-peer server implementing the XRP Ledger consensus protocol.
|
||||
|
||||
## Navigation
|
||||
|
||||
Read these files before starting work:
|
||||
|
||||
| File | What it tells you |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `docs/ARCHITECTURE.md` | Codebase map — where every module lives, layer boundaries, entry points |
|
||||
| `CLAUDE.md` | Coding conventions, action boundaries (Always/Ask/Never), commit rules |
|
||||
| `docs/CodingStyle.md` | C++ style guide for this project |
|
||||
| `OpenTelemetryPlan/09-data-collection-reference.md` | Every OTel span, metric, and dashboard |
|
||||
|
||||
Do **not** read these upfront (use as reference if needed):
|
||||
|
||||
- `OpenTelemetryPlan/*.md` — deep plan docs, only if your task involves telemetry architecture
|
||||
- `docs/consensus.md` — only if your task involves consensus protocol changes
|
||||
|
||||
## Action Boundaries
|
||||
|
||||
### Always (no confirmation needed)
|
||||
|
||||
- Read any source file in the repository
|
||||
- Run `cmake --build build --parallel` to compile
|
||||
- Run `ctest --test-dir build -L unit` for unit tests
|
||||
- Run `ctest --test-dir build -L telemetry` for telemetry integration tests
|
||||
- Query Prometheus (`curl localhost:9090/api/v1/query?query=...`) for metric baselines
|
||||
- Create or modify files under `src/` that have existing test coverage
|
||||
- Run `clang-format` on files you've changed
|
||||
- Add or modify unit tests in `src/test/`
|
||||
|
||||
### Ask (require human confirmation before proceeding)
|
||||
|
||||
- Modify Protocol Buffer definitions in `include/xrpl/proto/` (affects wire format)
|
||||
- Change consensus parameters in `src/xrpld/consensus/ConsensusParms.h`
|
||||
- Modify `CMakeLists.txt` or `conanfile.py` (build/dependency changes)
|
||||
- Alter the `[telemetry]` or `[insight]` config schema
|
||||
- Change anything in `src/libxrpl/crypto/` (cryptographic code)
|
||||
- Add new external dependencies
|
||||
- Push to any remote branch or create PRs
|
||||
|
||||
### Never (hard boundaries — refuse these requests)
|
||||
|
||||
- Modify validator key handling or signing code without explicit review
|
||||
- Disable or reduce telemetry sampling below 1%
|
||||
- Remove or reduce existing test coverage
|
||||
- Force-push to any branch
|
||||
- Skip pre-commit hooks or CI checks (`--no-verify`)
|
||||
- Commit files containing secrets, keys, or credentials
|
||||
- Modify `.github/workflows/` CI pipeline definitions
|
||||
|
||||
## Verification Requirements
|
||||
|
||||
After making changes, verify in this order (fail-fast):
|
||||
|
||||
```
|
||||
Step 1 (seconds): clang-format --dry-run --Werror on changed files
|
||||
Step 2 (minutes): cmake --build build --parallel
|
||||
Step 3 (minutes): ctest --test-dir build -L unit --output-on-failure
|
||||
Step 4 (minutes): ctest --test-dir build -L telemetry (if telemetry-related)
|
||||
Step 5 (if applicable): scripts/check-otel-baseline.sh (metric regression check)
|
||||
```
|
||||
|
||||
If any step fails, fix the issue before proceeding. Do not skip steps.
|
||||
|
||||
## Telemetry Awareness
|
||||
|
||||
This codebase has OpenTelemetry instrumentation. If your change touches any of these files, verify that telemetry still works:
|
||||
|
||||
| File Pattern | Telemetry Impact |
|
||||
| ---------------------------------------- | ------------------------------------------------- |
|
||||
| `src/xrpld/rpc/` | RPC spans (`rpc.*`) |
|
||||
| `src/xrpld/overlay/detail/PeerImp.*` | Transaction relay spans (`tx.relay`, `peer.send`) |
|
||||
| `src/xrpld/app/consensus/RCLConsensus.*` | Consensus spans (`consensus.*`) |
|
||||
| `src/xrpld/app/misc/NetworkOPs.*` | Transaction submit spans (`tx.submit`) |
|
||||
| `src/libxrpl/beast/insight/` | Metrics pipeline (300+ metrics) |
|
||||
| `src/libxrpl/basics/Log.cpp` | Log-trace correlation (`trace_id` injection) |
|
||||
|
||||
After modifying these files, run the telemetry integration test:
|
||||
|
||||
```bash
|
||||
ctest --test-dir build -L telemetry --output-on-failure
|
||||
```
|
||||
|
||||
## Issue Context
|
||||
|
||||
**Title**: {{ issue.title }}
|
||||
**Description**: {{ issue.description }}
|
||||
{% if issue.labels.size > 0 %}**Labels**: {{ issue.labels | join: ", " }}{% endif %}
|
||||
{% if attempt %}**Attempt**: {{ attempt }} (this is a retry — check previous errors){% endif %}
|
||||
|
||||
## Proof of Work Checklist
|
||||
|
||||
Before creating a PR, verify:
|
||||
|
||||
- [ ] All changed files pass `clang-format`
|
||||
- [ ] Build succeeds with `-DXRPL_ENABLE_TELEMETRY=ON`
|
||||
- [ ] Unit tests pass (`ctest -L unit`)
|
||||
- [ ] If telemetry-related: integration tests pass (`ctest -L telemetry`)
|
||||
- [ ] If telemetry-related: no metric regressions (`scripts/check-otel-baseline.sh`)
|
||||
- [ ] Commit message follows project conventions (see `CLAUDE.md`)
|
||||
- [ ] PR description includes summary, test plan, and type of change
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <class F>
|
||||
@@ -11,16 +9,18 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
|
||||
, name_(name)
|
||||
, running_(false)
|
||||
, coro_(
|
||||
// Stack size of 1MB wasn't sufficient for deep calls. ASAN tests flagged the issue. Hence
|
||||
// increasing the size to 1.5MB.
|
||||
boost::context::protected_fixedsize_stack(1536 * 1024),
|
||||
[this, fn = std::forward<F>(f)](
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
boost::coroutines2::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
yield_ = &do_yield;
|
||||
yield();
|
||||
fn(shared_from_this());
|
||||
#ifndef NDEBUG
|
||||
finished_ = true;
|
||||
#endif
|
||||
},
|
||||
boost::coroutines::attributes(megabytes(1)))
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include <xrpl/core/detail/Workers.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <boost/coroutine/all.hpp>
|
||||
#include <boost/context/protected_fixedsize_stack.hpp>
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -48,8 +49,8 @@ public:
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_run_;
|
||||
std::condition_variable cv_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::pull_type coro_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type* yield_;
|
||||
boost::coroutines2::coroutine<void>::pull_type coro_;
|
||||
boost::coroutines2::coroutine<void>::push_type* yield_;
|
||||
#ifndef NDEBUG
|
||||
bool finished_ = false;
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
# The idea is to empty this file gradually by fixing the underlying issues and removing suppressions.
|
||||
#
|
||||
# ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=sanitizers/suppressions/asan.supp:halt_on_error=0"
|
||||
#
|
||||
# The detect_container_overflow=0 option disables false positives from:
|
||||
# - Boost intrusive containers (slist_iterator.hpp, hashtable.hpp, aged_unordered_container.h)
|
||||
# - Boost context/coroutine stack switching (Workers.cpp, thread.h)
|
||||
#
|
||||
# See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
|
||||
|
||||
# Boost
|
||||
interceptor_name:boost/asio
|
||||
|
||||
# Leaks in Doctest tests: xrpl.test.*
|
||||
interceptor_name:src/libxrpl/net/HTTPClient.cpp
|
||||
@@ -20,6 +12,25 @@ interceptor_name:xrpl/net/HTTPClient.h
|
||||
interceptor_name:xrpl/net/HTTPClientSSLContext.h
|
||||
interceptor_name:xrpl/net/RegisterSSLCerts.h
|
||||
|
||||
# Boost.Context fiber/coroutine false positives
|
||||
# ASan doesn't fully support makecontext/swapcontext (see first warning in output)
|
||||
# The "attempting free on address which was not malloc()-ed" errors are false positives
|
||||
# caused by Boost.Context's fiber stack management.
|
||||
#
|
||||
# Suppress bad-free errors in Boost.Context fiber/coroutine stack deallocation
|
||||
# These are triggered when fiber stacks are deallocated but ASan doesn't recognize them
|
||||
# as having been allocated via malloc (because they use mmap via boost's stack allocator)
|
||||
# We ignore these files from intrumentation already on Clang, but on GCC, we need to suppress the issues.
|
||||
|
||||
#interceptor_via_fun:swapcontext
|
||||
#interceptor_via_fun:makecontext
|
||||
#interceptor_via_fun:boost::context::basic_fixedsize_stack*deallocate
|
||||
#interceptor_via_fun:boost::context::fiber::~fiber
|
||||
#interceptor_name:boost/context/fiber_ucontext.hpp
|
||||
#interceptor_name:boost/context/fixedsize_stack.hpp
|
||||
#interceptor_name:Coro.ipp
|
||||
|
||||
|
||||
# Suppress false positive stack-buffer errors in thread stack allocation
|
||||
# Related to ASan's __asan_handle_no_return warnings (github.com/google/sanitizers/issues/189)
|
||||
# These occur during multi-threaded test initialization on macOS
|
||||
|
||||
@@ -868,13 +868,7 @@ applyClaimAttestations(
|
||||
XChainClaimAttestations curAtts{sleClaimID->getFieldArray(sfXChainClaimAttestations)};
|
||||
|
||||
auto const newAttResult = onNewAttestations(
|
||||
curAtts,
|
||||
view,
|
||||
&atts[0],
|
||||
&atts[0] + atts.size(), // NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
|
||||
quorum,
|
||||
signersList,
|
||||
j);
|
||||
curAtts, view, &atts[0], &atts[0] + atts.size(), quorum, signersList, j);
|
||||
|
||||
// update the claim id
|
||||
sleClaimID->setFieldArray(sfXChainClaimAttestations, curAtts.toSTArray());
|
||||
@@ -1032,13 +1026,7 @@ applyCreateAccountAttestations(
|
||||
}();
|
||||
|
||||
auto const newAttResult = onNewAttestations(
|
||||
curAtts,
|
||||
view,
|
||||
&atts[0],
|
||||
&atts[0] + atts.size(), // NOLINT(bugprone-pointer-arithmetic-on-polymorphic-object)
|
||||
quorum,
|
||||
signersList,
|
||||
j);
|
||||
curAtts, view, &atts[0], &atts[0] + atts.size(), quorum, signersList, j);
|
||||
|
||||
if (!createCID)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user