mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-02 16:26:48 +00:00
feat: logging
This commit is contained in:
499
bin/add_trace_logging.py
Normal file
499
bin/add_trace_logging.py
Normal file
@@ -0,0 +1,499 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Instrument every function in the rippled codebase with TRACE_FUNC().
|
||||
|
||||
Adds an RAII trace scope to every function body that logs:
|
||||
- ENTER on function entry (with file:line)
|
||||
- EXIT on function exit (with file:line and duration in microseconds)
|
||||
|
||||
Usage:
|
||||
python3 bin/add_trace_logging.py [--dry-run] [--verbose] [--dir path]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
TRACE_INCLUDE = '#include <xrpl/basics/TraceLog.h>'
|
||||
TRACE_CALL = ' TRACE_FUNC();'
|
||||
|
||||
# Control-flow keywords that produce a '{' on its own line
|
||||
# (due to AfterControlStatement: true in .clang-format)
|
||||
CONTROL_KW_RE = re.compile(
|
||||
r'^\s*('
|
||||
r'if\s*\(|'
|
||||
r'else\s*if\s*\(|'
|
||||
r'else\s*$|'
|
||||
r'for\s*\(|'
|
||||
r'while\s*\(|'
|
||||
r'do\s*$|'
|
||||
r'switch\s*\(|'
|
||||
r'try\s*$|'
|
||||
r'catch\s*\('
|
||||
r')'
|
||||
)
|
||||
|
||||
# Structural keywords (class/struct/enum/union) — brace on own line
|
||||
STRUCT_KW_RE = re.compile(
|
||||
r'^\s*(class|struct|enum|union)\b'
|
||||
)
|
||||
|
||||
# Namespace — AfterNamespace: false so '{' is on same line,
|
||||
# but handle edge cases where someone puts it on next line
|
||||
NAMESPACE_RE = re.compile(r'^\s*namespace\b')
|
||||
|
||||
# Lambda capture: line contains ] possibly followed by () and qualifiers
|
||||
LAMBDA_RE = re.compile(r'\]\s*(\([^)]*\))?\s*(mutable\s*)?(noexcept\s*)?'
|
||||
r'(->[\s\S]*)?\s*$')
|
||||
|
||||
# Function ending: line ends with ) and optional qualifiers
|
||||
FUNC_END_RE = re.compile(
|
||||
r'\)\s*'
|
||||
r'(const\s*)?'
|
||||
r'(volatile\s*)?'
|
||||
r'(noexcept(\([^)]*\))?\s*)?'
|
||||
r'(override\s*)?'
|
||||
r'(final\s*)?'
|
||||
r'(requires\s*\([^)]*\)\s*)?'
|
||||
r'(->[\s\w:<>,*&]+\s*)?'
|
||||
r'\s*$'
|
||||
)
|
||||
|
||||
# Constructor initializer list line: starts with : or , for member init
|
||||
INIT_LIST_RE = re.compile(r'^\s*[,:]\s+\w')
|
||||
|
||||
# Macro-like patterns to skip
|
||||
MACRO_RE = re.compile(r'^\s*\\?\s*$')
|
||||
|
||||
|
||||
def find_source_files(root, dirs, extensions=('.cpp',), exclude_dirs=None):
|
||||
"""Find all source files under given directories."""
|
||||
if exclude_dirs is None:
|
||||
exclude_dirs = {'tests', 'test'}
|
||||
|
||||
files = []
|
||||
for d in dirs:
|
||||
search_dir = root / d
|
||||
if not search_dir.exists():
|
||||
continue
|
||||
for ext in extensions:
|
||||
for f in sorted(search_dir.rglob(f'*{ext}')):
|
||||
# Skip test directories
|
||||
parts = f.relative_to(root).parts
|
||||
if any(p in exclude_dirs for p in parts):
|
||||
continue
|
||||
files.append(f)
|
||||
return files
|
||||
|
||||
|
||||
def find_template_headers(root):
|
||||
"""Find .h files with template implementations that need instrumentation."""
|
||||
headers = []
|
||||
# These directories have header-only template implementations
|
||||
template_dirs = [
|
||||
'src/xrpld/consensus',
|
||||
'src/xrpld/overlay',
|
||||
'src/xrpld/overlay/detail',
|
||||
'src/xrpld/peerfinder',
|
||||
'src/xrpld/peerfinder/detail',
|
||||
'src/xrpld/app/consensus',
|
||||
'src/xrpld/app/ledger',
|
||||
'src/xrpld/app/ledger/detail',
|
||||
'src/xrpld/app/misc',
|
||||
'src/xrpld/app/misc/detail',
|
||||
'src/xrpld/app/main',
|
||||
'src/xrpld/rpc',
|
||||
'src/xrpld/rpc/detail',
|
||||
'src/xrpld/core',
|
||||
'src/xrpld/core/detail',
|
||||
]
|
||||
for d in template_dirs:
|
||||
search_dir = root / d
|
||||
if not search_dir.exists():
|
||||
continue
|
||||
for f in sorted(search_dir.glob('*.h')):
|
||||
headers.append(f)
|
||||
|
||||
# Also include key libxrpl headers with implementations
|
||||
libxrpl_dirs = [
|
||||
'include/xrpl/shamap',
|
||||
'include/xrpl/basics',
|
||||
'include/xrpl/protocol',
|
||||
]
|
||||
for d in libxrpl_dirs:
|
||||
search_dir = root / d
|
||||
if not search_dir.exists():
|
||||
continue
|
||||
for f in sorted(search_dir.glob('*.h')):
|
||||
# Skip TraceLog.h itself
|
||||
if f.name == 'TraceLog.h':
|
||||
continue
|
||||
headers.append(f)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def add_include(lines):
|
||||
"""Add the TraceLog.h include if not already present. Returns modified lines."""
|
||||
# Check if already included
|
||||
for line in lines:
|
||||
if 'TraceLog.h' in line:
|
||||
return lines, False
|
||||
|
||||
# Find insertion point: after last #include <xrpl/...> or <xrpld/...>
|
||||
last_xrpl_idx = -1
|
||||
last_xrpld_idx = -1
|
||||
last_include_idx = -1
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
stripped = line.strip()
|
||||
if stripped.startswith('#include'):
|
||||
last_include_idx = i
|
||||
if '<xrpl/' in stripped:
|
||||
last_xrpl_idx = i
|
||||
elif '<xrpld/' in stripped:
|
||||
last_xrpld_idx = i
|
||||
|
||||
if last_include_idx == -1:
|
||||
return lines, False # No includes at all — skip
|
||||
|
||||
# Prefer inserting after xrpl/ includes (same group), else after xrpld/
|
||||
if last_xrpl_idx >= 0:
|
||||
insert_at = last_xrpl_idx + 1
|
||||
elif last_xrpld_idx >= 0:
|
||||
# Insert after the xrpld block, with a blank line before xrpl includes
|
||||
insert_at = last_xrpld_idx + 1
|
||||
else:
|
||||
insert_at = last_include_idx + 1
|
||||
|
||||
lines.insert(insert_at, TRACE_INCLUDE + '\n')
|
||||
return lines, True
|
||||
|
||||
|
||||
def get_prev_nonblank(lines, idx):
|
||||
"""Get the index of the previous non-blank line before idx."""
|
||||
i = idx - 1
|
||||
while i >= 0:
|
||||
if lines[i].strip():
|
||||
return i
|
||||
i -= 1
|
||||
return -1
|
||||
|
||||
|
||||
def find_matching_open_paren_line(lines, start_idx):
|
||||
"""
|
||||
Starting from start_idx, walk backwards through lines to find the line
|
||||
containing the '(' that matches the last ')' on start_idx's line.
|
||||
Returns the line index, or -1 if not found.
|
||||
Uses character-level paren tracking for accuracy.
|
||||
"""
|
||||
depth = 0
|
||||
for scan in range(start_idx, max(start_idx - 30, -1), -1):
|
||||
line = lines[scan].rstrip()
|
||||
for ch in reversed(line):
|
||||
if ch == ')':
|
||||
depth += 1
|
||||
elif ch == '(':
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return scan
|
||||
return -1
|
||||
|
||||
|
||||
def is_lambda(lines, brace_idx):
|
||||
"""Check if the '{' at brace_idx opens a lambda body."""
|
||||
# Walk back up to 5 non-blank lines looking for ] (lambda capture close)
|
||||
prev = brace_idx - 1
|
||||
checked = 0
|
||||
while prev >= 0 and checked < 6:
|
||||
line = lines[prev].rstrip()
|
||||
if not line.strip():
|
||||
prev -= 1
|
||||
continue
|
||||
# Lambda pattern: line contains ']' possibly followed by () qualifiers
|
||||
if ']' in line:
|
||||
# Skip C++ attributes like [[nodiscard]], [[maybe_unused]], etc.
|
||||
# Attributes use [[ ]] (double brackets)
|
||||
stripped = line.strip()
|
||||
if re.match(r'^\[\[', stripped):
|
||||
# This is a C++ attribute, not a lambda
|
||||
checked += 1
|
||||
prev -= 1
|
||||
continue
|
||||
# Also skip ]] patterns mid-line (attributes in return types)
|
||||
if ']]' in line and '[[' in line:
|
||||
checked += 1
|
||||
prev -= 1
|
||||
continue
|
||||
|
||||
# Check for actual lambda pattern: ] followed by ( or { or mutable
|
||||
# Lambda captures end with ] then optional (params) or {body}
|
||||
if re.search(r'\]\s*(\([^)]*\))?\s*(mutable\s*)?(noexcept\s*)?'
|
||||
r'(->[\s\S]*)?\s*$', line):
|
||||
return True
|
||||
# Stop walking back at scope boundaries
|
||||
if line.strip().startswith('{') or line.strip().startswith('}'):
|
||||
break
|
||||
if line.strip().startswith('#'):
|
||||
break
|
||||
checked += 1
|
||||
prev -= 1
|
||||
return False
|
||||
|
||||
|
||||
def is_function_body(lines, brace_idx):
|
||||
"""
|
||||
Determine if the '{' at brace_idx opens a function body.
|
||||
|
||||
Returns True if this looks like a function definition, False otherwise.
|
||||
"""
|
||||
prev_idx = get_prev_nonblank(lines, brace_idx)
|
||||
if prev_idx < 0:
|
||||
return False
|
||||
|
||||
prev_line = lines[prev_idx].rstrip()
|
||||
|
||||
# Skip if preceded by a single-line control keyword
|
||||
if CONTROL_KW_RE.match(prev_line):
|
||||
return False
|
||||
|
||||
# Skip namespace
|
||||
if NAMESPACE_RE.match(prev_line):
|
||||
return False
|
||||
|
||||
# Skip class/struct/enum/union
|
||||
if STRUCT_KW_RE.match(prev_line):
|
||||
return False
|
||||
|
||||
# Skip lambdas
|
||||
if is_lambda(lines, brace_idx):
|
||||
return False
|
||||
|
||||
# Case 1: Previous line ends with ) + optional qualifiers
|
||||
if FUNC_END_RE.search(prev_line):
|
||||
# Walk back to find the line with the matching '('
|
||||
open_paren_line = find_matching_open_paren_line(lines, prev_idx)
|
||||
if open_paren_line >= 0:
|
||||
# Check if that line (or preceding lines) is a control keyword
|
||||
line = lines[open_paren_line].rstrip()
|
||||
if CONTROL_KW_RE.match(line):
|
||||
return False
|
||||
# Also check the line before (for multi-line: "else\n if(...)")
|
||||
prev_kw = get_prev_nonblank(lines, open_paren_line)
|
||||
if prev_kw >= 0:
|
||||
kw_line = lines[prev_kw].rstrip()
|
||||
if re.match(r'^\s*else\s*$', kw_line):
|
||||
return False
|
||||
return True
|
||||
|
||||
# Case 2: Constructor initializer list — line starts with , or :
|
||||
if INIT_LIST_RE.match(prev_line):
|
||||
# Walk back through initializer list to find constructor signature
|
||||
scan = prev_idx - 1
|
||||
while scan >= 0:
|
||||
line = lines[scan].rstrip()
|
||||
if FUNC_END_RE.search(line):
|
||||
return True
|
||||
if not INIT_LIST_RE.match(line) and ')' not in line:
|
||||
break
|
||||
scan -= 1
|
||||
# Even if we can't find the signature, an init list implies constructor
|
||||
return True
|
||||
|
||||
# Case 3: Previous line ends with something unusual — check a few
|
||||
# lines back for a ')' that might be part of a function signature
|
||||
# (e.g., trailing requires clause or -> return type on separate line)
|
||||
for lookback in range(1, 4):
|
||||
check_idx = prev_idx - lookback
|
||||
if check_idx < 0:
|
||||
break
|
||||
check_line = lines[check_idx].rstrip()
|
||||
if check_line.strip() == '' or check_line.strip().startswith('#'):
|
||||
break
|
||||
if FUNC_END_RE.search(check_line):
|
||||
open_paren_line = find_matching_open_paren_line(
|
||||
lines, check_idx)
|
||||
if open_paren_line >= 0:
|
||||
if CONTROL_KW_RE.match(lines[open_paren_line].rstrip()):
|
||||
return False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_empty_body(lines, brace_idx):
|
||||
"""Check if the function body is empty (next non-blank line is '}')."""
|
||||
i = brace_idx + 1
|
||||
while i < len(lines):
|
||||
stripped = lines[i].strip()
|
||||
if stripped:
|
||||
return stripped == '}'
|
||||
i += 1
|
||||
return True
|
||||
|
||||
|
||||
def already_has_trace(lines, brace_idx):
|
||||
"""Check if TRACE_FUNC is already the first statement."""
|
||||
i = brace_idx + 1
|
||||
while i < len(lines):
|
||||
stripped = lines[i].strip()
|
||||
if stripped:
|
||||
return 'TRACE_FUNC()' in stripped
|
||||
i += 1
|
||||
return False
|
||||
|
||||
|
||||
def get_function_context(lines, brace_idx):
|
||||
"""Try to extract a meaningful function name from the context."""
|
||||
prev_idx = get_prev_nonblank(lines, brace_idx)
|
||||
if prev_idx < 0:
|
||||
return "unknown"
|
||||
|
||||
# Walk back to find the function name line
|
||||
scan = prev_idx
|
||||
while scan >= 0:
|
||||
line = lines[scan].strip()
|
||||
# Look for ClassName::methodName or just functionName
|
||||
match = re.search(r'(\w+(?:::\w+)?)\s*\(', line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
if line.startswith('#') or line == '':
|
||||
break
|
||||
scan -= 1
|
||||
|
||||
return lines[prev_idx].strip()[:60]
|
||||
|
||||
|
||||
def instrument_file(filepath, dry_run=False, verbose=False):
|
||||
"""
|
||||
Add TRACE_FUNC() to every function body in the given file.
|
||||
Returns (functions_found, include_added) tuple.
|
||||
"""
|
||||
with open(filepath, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
original_lines = list(lines)
|
||||
functions_found = 0
|
||||
insertions = [] # (line_index, context_string)
|
||||
|
||||
# Pass 1: Find all function body openings
|
||||
# Track brace depth to skip nested blocks inside functions
|
||||
brace_depth = 0
|
||||
in_function = False
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
stripped = line.strip()
|
||||
|
||||
if in_function:
|
||||
# Count braces to track nesting within the current function
|
||||
brace_depth += stripped.count('{') - stripped.count('}')
|
||||
if brace_depth <= 0:
|
||||
in_function = False
|
||||
brace_depth = 0
|
||||
elif stripped == '{':
|
||||
if is_function_body(lines, i):
|
||||
if not is_empty_body(lines, i) and not already_has_trace(lines, i):
|
||||
ctx = get_function_context(lines, i)
|
||||
insertions.append((i, ctx))
|
||||
functions_found += 1
|
||||
in_function = True
|
||||
brace_depth = 1
|
||||
i += 1
|
||||
|
||||
if functions_found == 0 and not any('TraceLog.h' in l for l in lines):
|
||||
return 0, False # Nothing to do
|
||||
|
||||
# Pass 2: Add include
|
||||
include_added = False
|
||||
if functions_found > 0:
|
||||
lines, include_added = add_include(lines)
|
||||
# Adjust insertion indices if include was added
|
||||
if include_added:
|
||||
# Find where the include was inserted
|
||||
for idx in range(len(lines)):
|
||||
if TRACE_INCLUDE in lines[idx]:
|
||||
include_line = idx
|
||||
break
|
||||
insertions = [
|
||||
(i + 1 if i >= include_line else i, ctx)
|
||||
for i, ctx in insertions
|
||||
]
|
||||
|
||||
# Pass 3: Insert TRACE_FUNC() calls (reverse order to preserve indices)
|
||||
for insert_idx, ctx in reversed(insertions):
|
||||
lines.insert(insert_idx + 1, TRACE_CALL + '\n')
|
||||
|
||||
if verbose and functions_found > 0:
|
||||
rel_path = filepath.name
|
||||
print(f" {rel_path}: {functions_found} functions")
|
||||
for _, ctx in insertions:
|
||||
print(f" -> {ctx}")
|
||||
|
||||
if not dry_run and lines != original_lines:
|
||||
with open(filepath, 'w') as f:
|
||||
f.writelines(lines)
|
||||
|
||||
return functions_found, include_added
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Add TRACE_FUNC() to every function in the rippled codebase')
|
||||
parser.add_argument('--dry-run', action='store_true',
|
||||
help='Print what would change without modifying files')
|
||||
parser.add_argument('--verbose', '-v', action='store_true',
|
||||
help='Show each function found')
|
||||
parser.add_argument('--dir', type=str, default=None,
|
||||
help='Only process files under this subdirectory')
|
||||
parser.add_argument('--headers', action='store_true',
|
||||
help='Also process .h files with template implementations')
|
||||
parser.add_argument('--root', type=str, default='.',
|
||||
help='Project root directory')
|
||||
args = parser.parse_args()
|
||||
|
||||
root = Path(args.root).resolve()
|
||||
|
||||
# Find source files
|
||||
if args.dir:
|
||||
dirs = [args.dir]
|
||||
else:
|
||||
dirs = ['src/xrpld', 'src/libxrpl']
|
||||
|
||||
files = find_source_files(root, dirs)
|
||||
|
||||
if args.headers:
|
||||
files.extend(find_template_headers(root))
|
||||
|
||||
if not files:
|
||||
print(f"No source files found under {root}")
|
||||
sys.exit(1)
|
||||
|
||||
total_functions = 0
|
||||
total_includes = 0
|
||||
total_files_modified = 0
|
||||
|
||||
mode = "DRY RUN" if args.dry_run else "INSTRUMENTING"
|
||||
print(f"[{mode}] Processing {len(files)} files under {root}")
|
||||
print()
|
||||
|
||||
for filepath in files:
|
||||
funcs, inc = instrument_file(
|
||||
filepath, dry_run=args.dry_run, verbose=args.verbose)
|
||||
if funcs > 0:
|
||||
total_functions += funcs
|
||||
total_files_modified += 1
|
||||
if inc:
|
||||
total_includes += 1
|
||||
|
||||
print()
|
||||
print(f"{'Would instrument' if args.dry_run else 'Instrumented'}: "
|
||||
f"{total_functions} functions across {total_files_modified} files")
|
||||
print(f"{'Would add' if args.dry_run else 'Added'}: "
|
||||
f"{total_includes} new #include directives")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
37
include/xrpl/basics/TraceLog.h
Normal file
37
include/xrpl/basics/TraceLog.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
namespace tracing {
|
||||
void init(
|
||||
char const* outputPath,
|
||||
double samplingRate = 1.0,
|
||||
std::uint64_t maxFileSizeMB = 500,
|
||||
int maxFiles = 10);
|
||||
void shutdown();
|
||||
} // namespace tracing
|
||||
|
||||
class TraceScope
|
||||
{
|
||||
std::uint64_t spanId_;
|
||||
std::uint64_t traceId_;
|
||||
std::uint64_t parentId_;
|
||||
char const* func_;
|
||||
char const* file_;
|
||||
int line_;
|
||||
std::int64_t startUs_;
|
||||
bool active_;
|
||||
|
||||
public:
|
||||
TraceScope(char const* func, char const* file, int line) noexcept;
|
||||
~TraceScope() noexcept;
|
||||
TraceScope(TraceScope const&) = delete;
|
||||
TraceScope& operator=(TraceScope const&) = delete;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
#define TRACE_FUNC() \
|
||||
xrpl::TraceScope xrpl_trace_scope_(__func__, __FILE__, __LINE__)
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <xrpl/basics/BasicConfig.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/TaggedCache.ipp>
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/nodestore/Backend.h>
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/protocol/SystemParameters.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
@@ -222,6 +224,12 @@ protected:
|
||||
void
|
||||
importInternal(Backend& dstBackend, Database& srcDB);
|
||||
|
||||
void
|
||||
negCacheErase(uint256 const& hash);
|
||||
|
||||
void
|
||||
negCacheClear();
|
||||
|
||||
void
|
||||
updateFetchMetrics(uint64_t fetches, uint64_t hits, uint64_t duration)
|
||||
{
|
||||
@@ -251,6 +259,10 @@ private:
|
||||
std::atomic<int> readThreads_ = 0;
|
||||
std::atomic<int> runningThreads_ = 0;
|
||||
|
||||
mutable std::mutex negCacheMutex_;
|
||||
std::unordered_set<uint256, beast::Uhash<>> negCache_;
|
||||
static constexpr std::size_t kNegCacheMax = 100'000;
|
||||
|
||||
virtual std::shared_ptr<NodeObject>
|
||||
fetchNodeObject(
|
||||
uint256 const& hash,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/nodestore/DatabaseRotating.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace xrpl::NodeStore {
|
||||
@@ -59,6 +60,7 @@ private:
|
||||
std::shared_ptr<Backend> writableBackend_;
|
||||
std::shared_ptr<Backend> archiveBackend_;
|
||||
mutable std::mutex mutex_;
|
||||
std::atomic<bool> archiveHasData_{true};
|
||||
|
||||
std::shared_ptr<NodeObject>
|
||||
fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport& fetchReport, bool duplicate)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/basics/Archive.h>
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -17,6 +18,7 @@ namespace xrpl {
|
||||
void
|
||||
extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!is_regular_file(src))
|
||||
Throw<std::runtime_error>("Invalid source file");
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/basics/BasicConfig.h>
|
||||
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/regex/v5/regbase.hpp>
|
||||
#include <boost/regex/v5/regex.hpp>
|
||||
@@ -21,12 +22,14 @@ Section::Section(std::string name) : name_(std::move(name))
|
||||
void
|
||||
Section::set(std::string const& key, std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
lookup_.insert_or_assign(key, value);
|
||||
}
|
||||
|
||||
void
|
||||
Section::append(std::vector<std::string> const& lines)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// <key> '=' <value>
|
||||
static boost::regex const kRE1(
|
||||
"^" // start of line
|
||||
@@ -98,12 +101,14 @@ Section::append(std::vector<std::string> const& lines)
|
||||
bool
|
||||
Section::exists(std::string const& name) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return lookup_.contains(name);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, Section const& section)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& [k, v] : section.lookup_)
|
||||
os << k << "=" << v << "\n";
|
||||
return os;
|
||||
@@ -114,18 +119,21 @@ operator<<(std::ostream& os, Section const& section)
|
||||
bool
|
||||
BasicConfig::exists(std::string const& name) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return map_.contains(name);
|
||||
}
|
||||
|
||||
Section&
|
||||
BasicConfig::section(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return map_.emplace(name, name).first->second;
|
||||
}
|
||||
|
||||
Section const&
|
||||
BasicConfig::section(std::string const& name) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static Section const kNONE("");
|
||||
auto const iter = map_.find(name);
|
||||
if (iter == map_.end())
|
||||
@@ -136,6 +144,7 @@ BasicConfig::section(std::string const& name) const
|
||||
void
|
||||
BasicConfig::overwrite(std::string const& section, std::string const& key, std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const result =
|
||||
map_.emplace(std::piecewise_construct, std::make_tuple(section), std::make_tuple(section));
|
||||
result.first->second.set(key, value);
|
||||
@@ -144,6 +153,7 @@ BasicConfig::overwrite(std::string const& section, std::string const& key, std::
|
||||
void
|
||||
BasicConfig::deprecatedClearSection(std::string const& section)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto i = map_.find(section);
|
||||
if (i != map_.end())
|
||||
i->second = Section(section);
|
||||
@@ -152,18 +162,21 @@ BasicConfig::deprecatedClearSection(std::string const& section)
|
||||
void
|
||||
BasicConfig::legacy(std::string const& section, std::string value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
map_.emplace(section, section).first->second.legacy(std::move(value));
|
||||
}
|
||||
|
||||
std::string
|
||||
BasicConfig::legacy(std::string const& sectionName) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return section(sectionName).legacy();
|
||||
}
|
||||
|
||||
void
|
||||
BasicConfig::build(IniFileSections const& ifs)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& entry : ifs)
|
||||
{
|
||||
auto const result = map_.emplace(
|
||||
@@ -175,6 +188,7 @@ BasicConfig::build(IniFileSections const& ifs)
|
||||
std::ostream&
|
||||
operator<<(std::ostream& ss, BasicConfig const& c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& [k, v] : c.map_)
|
||||
ss << "[" << k << "]\n" << v;
|
||||
return ss;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -7,6 +8,7 @@ namespace xrpl {
|
||||
CountedObjects&
|
||||
CountedObjects::getInstance() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static CountedObjects kINSTANCE;
|
||||
|
||||
return kINSTANCE;
|
||||
@@ -19,6 +21,7 @@ CountedObjects::CountedObjects() noexcept : count_(0), head_(nullptr)
|
||||
CountedObjects::List
|
||||
CountedObjects::getCounts(int minimumThreshold) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
List counts;
|
||||
|
||||
// When other operations are concurrent, the count
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpl/basics/FileUtilities.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -22,6 +23,7 @@ getFileContents(
|
||||
boost::filesystem::path const& sourcePath,
|
||||
std::optional<std::size_t> maxSize)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::system::errc;
|
||||
|
||||
@@ -62,6 +64,7 @@ writeFileContents(
|
||||
boost::filesystem::path const& destPath,
|
||||
std::string const& contents)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::system::errc;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -28,6 +29,7 @@ Logs::Sink::Sink(std::string partition, beast::severities::Severity thresh, Logs
|
||||
void
|
||||
Logs::Sink::write(beast::severities::Severity level, std::string const& text)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (level < threshold())
|
||||
return;
|
||||
|
||||
@@ -37,6 +39,7 @@ Logs::Sink::write(beast::severities::Severity level, std::string const& text)
|
||||
void
|
||||
Logs::Sink::writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
logs_.write(level, partition_, text, console());
|
||||
}
|
||||
|
||||
@@ -49,12 +52,14 @@ Logs::File::File() : stream_(nullptr)
|
||||
bool
|
||||
Logs::File::isOpen() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return stream_ != nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
Logs::File::open(boost::filesystem::path const& path)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
close();
|
||||
|
||||
bool wasOpened = false;
|
||||
@@ -77,6 +82,7 @@ Logs::File::open(boost::filesystem::path const& path)
|
||||
bool
|
||||
Logs::File::closeAndReopen()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
close();
|
||||
|
||||
return open(path_);
|
||||
@@ -85,12 +91,14 @@ Logs::File::closeAndReopen()
|
||||
void
|
||||
Logs::File::close()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stream_ = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Logs::File::write(char const* text)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (stream_ != nullptr)
|
||||
(*stream_) << text;
|
||||
}
|
||||
@@ -98,6 +106,7 @@ Logs::File::write(char const* text)
|
||||
void
|
||||
Logs::File::writeln(char const* text)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (stream_ != nullptr)
|
||||
{
|
||||
(*stream_) << text;
|
||||
@@ -114,12 +123,14 @@ Logs::Logs(beast::severities::Severity thresh) : thresh_(thresh) // default sev
|
||||
bool
|
||||
Logs::open(boost::filesystem::path const& pathToLogFile)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return file_.open(pathToLogFile);
|
||||
}
|
||||
|
||||
beast::Journal::Sink&
|
||||
Logs::get(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
auto const result = sinks_.emplace(name, makeSink(name, thresh_));
|
||||
return *result.first->second;
|
||||
@@ -134,18 +145,21 @@ Logs::operator[](std::string const& name)
|
||||
beast::Journal
|
||||
Logs::journal(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return beast::Journal(get(name));
|
||||
}
|
||||
|
||||
beast::severities::Severity
|
||||
Logs::threshold() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return thresh_;
|
||||
}
|
||||
|
||||
void
|
||||
Logs::threshold(beast::severities::Severity thresh)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
thresh_ = thresh;
|
||||
for (auto& sink : sinks_)
|
||||
@@ -155,6 +169,7 @@ Logs::threshold(beast::severities::Severity thresh)
|
||||
std::vector<std::pair<std::string, std::string>>
|
||||
Logs::partitionSeverities() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<std::pair<std::string, std::string>> list;
|
||||
std::scoped_lock const lock(mutex_);
|
||||
list.reserve(sinks_.size());
|
||||
@@ -170,6 +185,7 @@ Logs::write(
|
||||
std::string const& text,
|
||||
bool console)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string s;
|
||||
format(s, text, level, partition);
|
||||
std::scoped_lock const lock(mutex_);
|
||||
@@ -184,6 +200,7 @@ Logs::write(
|
||||
std::string
|
||||
Logs::rotate()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
bool const wasOpened = file_.closeAndReopen();
|
||||
if (wasOpened)
|
||||
@@ -194,12 +211,14 @@ Logs::rotate()
|
||||
std::unique_ptr<beast::Journal::Sink>
|
||||
Logs::makeSink(std::string const& name, beast::severities::Severity threshold)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<Sink>(name, threshold, *this);
|
||||
}
|
||||
|
||||
LogSeverity
|
||||
Logs::fromSeverity(beast::severities::Severity level)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace beast::severities;
|
||||
switch (level)
|
||||
{
|
||||
@@ -229,6 +248,7 @@ Logs::fromSeverity(beast::severities::Severity level)
|
||||
beast::severities::Severity
|
||||
Logs::toSeverity(LogSeverity level)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace beast::severities;
|
||||
switch (level)
|
||||
{
|
||||
@@ -257,6 +277,7 @@ Logs::toSeverity(LogSeverity level)
|
||||
std::string
|
||||
Logs::toString(LogSeverity s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (s)
|
||||
{
|
||||
case LSTrace:
|
||||
@@ -282,6 +303,7 @@ Logs::toString(LogSeverity s)
|
||||
LogSeverity
|
||||
Logs::fromString(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (boost::iequals(s, "trace"))
|
||||
return LSTrace;
|
||||
|
||||
@@ -310,6 +332,7 @@ Logs::format(
|
||||
beast::severities::Severity severity,
|
||||
std::string const& partition)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
output.reserve(message.size() + partition.size() + 100);
|
||||
|
||||
output = xrpl::to_string(std::chrono::system_clock::now());
|
||||
@@ -412,6 +435,7 @@ public:
|
||||
std::unique_ptr<beast::Journal::Sink>
|
||||
set(std::unique_ptr<beast::Journal::Sink> sink)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mtx_);
|
||||
|
||||
using std::swap;
|
||||
@@ -432,6 +456,7 @@ public:
|
||||
beast::Journal::Sink&
|
||||
get()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mtx_);
|
||||
return sink_.get();
|
||||
}
|
||||
@@ -440,6 +465,7 @@ public:
|
||||
static DebugSink&
|
||||
debugSink()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static DebugSink kINST;
|
||||
return kINST;
|
||||
}
|
||||
@@ -447,12 +473,14 @@ debugSink()
|
||||
std::unique_ptr<beast::Journal::Sink>
|
||||
setDebugLogSink(std::unique_ptr<beast::Journal::Sink> sink)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return debugSink().set(std::move(sink));
|
||||
}
|
||||
|
||||
beast::Journal
|
||||
debugLog()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return beast::Journal(debugSink().get());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/predef.h>
|
||||
|
||||
@@ -31,6 +32,7 @@ namespace {
|
||||
bool
|
||||
getRusageThread(struct rusage& ru)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ::getrusage(RUSAGE_THREAD, &ru) == 0; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
@@ -48,12 +50,14 @@ namespace detail {
|
||||
inline int
|
||||
mallocTrimWithPad(std::size_t padBytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ::malloc_trim(padBytes);
|
||||
}
|
||||
|
||||
long
|
||||
parseStatmRSSkB(std::string const& statm)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// /proc/self/statm format: size resident shared text lib data dt
|
||||
// We want the second field (resident) which is in pages
|
||||
std::istringstream iss(statm);
|
||||
@@ -76,6 +80,7 @@ parseStatmRSSkB(std::string const& statm)
|
||||
MallocTrimReport
|
||||
mallocTrim(std::string_view tag, beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// LCOV_EXCL_START
|
||||
|
||||
MallocTrimReport report;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -33,24 +34,28 @@ thread_local std::reference_wrapper<MantissaRange const> Number::kRANGE = kLARGE
|
||||
Number::RoundingMode
|
||||
Number::getround()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return mode;
|
||||
}
|
||||
|
||||
Number::RoundingMode
|
||||
Number::setround(RoundingMode inMode)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::exchange(Number::mode, inMode);
|
||||
}
|
||||
|
||||
MantissaRange::MantissaScale
|
||||
Number::getMantissaScale()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return kRANGE.get().scale;
|
||||
}
|
||||
|
||||
void
|
||||
Number::setMantissaScale(MantissaRange::MantissaScale scale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (scale != MantissaRange::MantissaScale::Small &&
|
||||
scale != MantissaRange::MantissaScale::Large)
|
||||
logicError("Unknown mantissa scale");
|
||||
@@ -130,24 +135,28 @@ private:
|
||||
inline void
|
||||
Number::Guard::setPositive() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
sbit_ = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
Number::Guard::setNegative() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
sbit_ = 1;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Number::Guard::isNegative() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return sbit_ == 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
Number::Guard::doPush(unsigned d) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
xbit_ = xbit_ || ((digits_ & 0x0000'0000'0000'000F) != 0);
|
||||
digits_ >>= 4;
|
||||
digits_ |= (d & 0x0000'0000'0000'000FULL) << 60;
|
||||
@@ -157,12 +166,14 @@ template <class T>
|
||||
inline void
|
||||
Number::Guard::push(T d) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
doPush(static_cast<unsigned>(d));
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
Number::Guard::pop() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
unsigned const d = (digits_ & 0xF000'0000'0000'0000) >> 60;
|
||||
digits_ <<= 4;
|
||||
return d;
|
||||
@@ -175,6 +186,7 @@ Number::Guard::pop() noexcept
|
||||
int
|
||||
Number::Guard::round() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto mode = Number::getround();
|
||||
|
||||
if (mode == RoundingMode::TowardsZero)
|
||||
@@ -217,6 +229,7 @@ Number::Guard::bringIntoRange(
|
||||
int& exponent,
|
||||
internalrep const& minMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Bring mantissa back into the minMantissa / maxMantissa range AFTER
|
||||
// rounding
|
||||
if (mantissa < minMantissa)
|
||||
@@ -244,6 +257,7 @@ Number::Guard::doRoundUp(
|
||||
internalrep const& maxMantissa,
|
||||
std::string location)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto r = round();
|
||||
if (r == 1 || (r == 0 && (mantissa & 1) == 1))
|
||||
{
|
||||
@@ -269,6 +283,7 @@ Number::Guard::doRoundDown(
|
||||
int& exponent,
|
||||
internalrep const& minMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto r = round();
|
||||
if (r == 1 || (r == 0 && (mantissa & 1) == 1))
|
||||
{
|
||||
@@ -286,6 +301,7 @@ Number::Guard::doRoundDown(
|
||||
void
|
||||
Number::Guard::doRound(rep& drops, std::string location) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto r = round();
|
||||
if (r == 1 || (r == 0 && (drops & 1) == 1))
|
||||
{
|
||||
@@ -315,6 +331,7 @@ Number::Guard::doRound(rep& drops, std::string location) const
|
||||
Number::internalrep
|
||||
Number::externalToInternal(rep mantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// If the mantissa is already positive, just return it
|
||||
if (mantissa >= 0)
|
||||
return mantissa;
|
||||
@@ -350,6 +367,7 @@ constexpr Number kONE_LRG = Number::oneLarge();
|
||||
Number
|
||||
Number::one()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (&kRANGE.get() == &kSMALL_RANGE)
|
||||
return kONE_SML;
|
||||
XRPL_ASSERT(&kRANGE.get() == &kLARGE_RANGE, "Number::one() : valid range");
|
||||
@@ -367,6 +385,7 @@ doNormalize(
|
||||
MantissaRange::rep const& minMantissa,
|
||||
MantissaRange::rep const& maxMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto constexpr kMIN_EXPONENT = Number::kMIN_EXPONENT;
|
||||
auto constexpr kMAX_EXPONENT = Number::kMAX_EXPONENT;
|
||||
auto constexpr kMAX_REP = Number::kMAX_REP;
|
||||
@@ -450,6 +469,7 @@ Number::normalize<uint128_t>(
|
||||
internalrep const& minMantissa,
|
||||
internalrep const& maxMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
}
|
||||
|
||||
@@ -462,6 +482,7 @@ Number::normalize<unsigned long long>(
|
||||
internalrep const& minMantissa,
|
||||
internalrep const& maxMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
}
|
||||
|
||||
@@ -474,12 +495,14 @@ Number::normalize<unsigned long>(
|
||||
internalrep const& minMantissa,
|
||||
internalrep const& maxMantissa)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
}
|
||||
|
||||
void
|
||||
Number::normalize()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& range = kRANGE.get();
|
||||
normalize(negative_, mantissa_, exponent_, range.min, range.max);
|
||||
}
|
||||
@@ -490,6 +513,7 @@ Number::normalize()
|
||||
Number
|
||||
Number::shiftExponent(int exponentDelta) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::shiftExponent", "normalized");
|
||||
auto const newExponent = exponent_ + exponentDelta;
|
||||
if (newExponent >= kMAX_EXPONENT)
|
||||
@@ -506,6 +530,7 @@ Number::shiftExponent(int exponentDelta) const
|
||||
Number&
|
||||
Number::operator+=(Number const& y)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
if (y == kZERO)
|
||||
return *this;
|
||||
@@ -611,6 +636,7 @@ Number::operator+=(Number const& y)
|
||||
static inline unsigned
|
||||
divu10(uint128_t& u)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// q = u * 0.75
|
||||
auto q = (u >> 1) + (u >> 2);
|
||||
// iterate towards q = u * 0.8
|
||||
@@ -633,6 +659,7 @@ divu10(uint128_t& u)
|
||||
Number&
|
||||
Number::operator*=(Number const& y)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
if (*this == kZERO)
|
||||
return *this;
|
||||
@@ -696,6 +723,7 @@ Number::operator*=(Number const& y)
|
||||
Number&
|
||||
Number::operator/=(Number const& y)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
if (y == kZERO)
|
||||
throw std::overflow_error("Number: divide by 0");
|
||||
@@ -791,6 +819,7 @@ Number::operator/=(Number const& y)
|
||||
Number::
|
||||
operator rep() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
rep drops = mantissa();
|
||||
int offset = exponent();
|
||||
Guard g;
|
||||
@@ -820,6 +849,7 @@ operator rep() const
|
||||
Number
|
||||
Number::truncate() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (exponent_ >= 0 || mantissa_ == 0)
|
||||
return *this;
|
||||
|
||||
@@ -838,6 +868,7 @@ Number::truncate() const noexcept
|
||||
std::string
|
||||
to_string(Number const& amount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// keep full internal accuracy, but make more human friendly if possible
|
||||
constexpr Number kZERO = Number{};
|
||||
if (amount == kZERO)
|
||||
@@ -936,6 +967,7 @@ to_string(Number const& amount)
|
||||
Number
|
||||
power(Number const& f, unsigned n)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (n == 0)
|
||||
return Number::one();
|
||||
if (n == 1)
|
||||
@@ -959,6 +991,7 @@ power(Number const& f, unsigned n)
|
||||
Number
|
||||
root(Number f, unsigned d)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
auto const one = Number::one();
|
||||
|
||||
@@ -1031,6 +1064,7 @@ root(Number f, unsigned d)
|
||||
Number
|
||||
root2(Number f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
auto const one = Number::one();
|
||||
|
||||
@@ -1078,6 +1112,7 @@ root2(Number f)
|
||||
Number
|
||||
power(Number const& f, unsigned n, unsigned d)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
constexpr Number kZERO = Number{};
|
||||
auto const one = Number::one();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
@@ -47,6 +48,7 @@ class AsyncObject
|
||||
public:
|
||||
~AsyncObject()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Destroying the object with I/O pending? Not a clean exit!
|
||||
XRPL_ASSERT(pending_.load() == 0, "xrpl::AsyncObject::~AsyncObject : nothing pending");
|
||||
}
|
||||
@@ -60,16 +62,19 @@ public:
|
||||
public:
|
||||
explicit CompletionCounter(Derived* owner) : owner_(owner)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++owner_->pending_;
|
||||
}
|
||||
|
||||
CompletionCounter(CompletionCounter const& other) : owner_(other.owner_)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++owner_->pending_;
|
||||
}
|
||||
|
||||
~CompletionCounter()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (--owner_->pending_ == 0)
|
||||
owner_->asyncHandlersComplete();
|
||||
}
|
||||
@@ -84,12 +89,14 @@ public:
|
||||
void
|
||||
addReference()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++pending_;
|
||||
}
|
||||
|
||||
void
|
||||
removeReference()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (--pending_ == 0)
|
||||
(static_cast<Derived*>(this))->asyncHandlersComplete();
|
||||
}
|
||||
@@ -128,6 +135,7 @@ public:
|
||||
template <class StringSequence>
|
||||
Work(StringSequence const& inNames, HandlerType handler) : handler(std::move(handler))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
names.reserve(inNames.size());
|
||||
|
||||
std::reverse_copy(inNames.begin(), inNames.end(), std::back_inserter(names));
|
||||
@@ -148,6 +156,7 @@ public:
|
||||
|
||||
~ResolverAsioImpl() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(work.empty(), "xrpl::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
|
||||
XRPL_ASSERT(stopped, "xrpl::ResolverAsioImpl::~ResolverAsioImpl : stopped");
|
||||
}
|
||||
@@ -157,6 +166,7 @@ public:
|
||||
void
|
||||
asyncHandlersComplete()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::unique_lock<std::mutex> const lk{mut};
|
||||
asyncHandlersCompleted = true;
|
||||
cv.notify_all();
|
||||
@@ -171,6 +181,7 @@ public:
|
||||
void
|
||||
start() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(stopped == true, "xrpl::ResolverAsioImpl::start : stopped");
|
||||
XRPL_ASSERT(stop_called == false, "xrpl::ResolverAsioImpl::start : not stopping");
|
||||
|
||||
@@ -187,6 +198,7 @@ public:
|
||||
void
|
||||
stopAsync() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!stop_called.exchange(true))
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
@@ -201,6 +213,7 @@ public:
|
||||
void
|
||||
stop() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stopAsync();
|
||||
|
||||
JLOG(journal.debug()) << "Waiting to stop";
|
||||
@@ -213,6 +226,7 @@ public:
|
||||
void
|
||||
resolve(std::vector<std::string> const& names, HandlerType const& handler) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(stop_called == false, "xrpl::ResolverAsioImpl::resolve : not stopping");
|
||||
XRPL_ASSERT(!names.empty(), "xrpl::ResolverAsioImpl::resolve : names non-empty");
|
||||
|
||||
@@ -231,6 +245,7 @@ public:
|
||||
void
|
||||
doStop(CompletionCounter)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(stop_called == true, "xrpl::ResolverAsioImpl::do_stop : stopping");
|
||||
|
||||
if (!stopped.exchange(true))
|
||||
@@ -250,6 +265,7 @@ public:
|
||||
boost::asio::ip::tcp::resolver::results_type results,
|
||||
CompletionCounter)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
@@ -278,6 +294,7 @@ public:
|
||||
static HostAndPort
|
||||
parseName(std::string const& str)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// first attempt to parse as an endpoint (IP addr + port).
|
||||
// If that doesn't succeed, fall back to generic name + port parsing
|
||||
|
||||
@@ -324,6 +341,7 @@ public:
|
||||
void
|
||||
doWork(CompletionCounter)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (stop_called)
|
||||
return;
|
||||
|
||||
@@ -369,6 +387,7 @@ public:
|
||||
void
|
||||
doResolve(std::vector<std::string> const& names, HandlerType const& handler, CompletionCounter)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!names.empty(), "xrpl::ResolverAsioImpl::do_resolve : names non-empty");
|
||||
|
||||
if (!stop_called)
|
||||
@@ -395,6 +414,7 @@ public:
|
||||
std::unique_ptr<ResolverAsio>
|
||||
ResolverAsio::make(boost::asio::io_context& ioContext, beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<ResolverAsioImpl>(ioContext, journal);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/beast/core/LexicalCast.h>
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
@@ -22,6 +23,7 @@ namespace xrpl {
|
||||
std::string
|
||||
sqlBlobLiteral(Blob const& blob)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string j;
|
||||
|
||||
j.reserve((blob.size() * 2) + 3);
|
||||
@@ -36,6 +38,7 @@ sqlBlobLiteral(Blob const& blob)
|
||||
bool
|
||||
parseUrl(ParsedUrl& pUrl, std::string const& strUrl)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// scheme://username:password@hostname:port/rest
|
||||
static boost::regex const kRE_URL(
|
||||
"(?i)\\`\\s*"
|
||||
@@ -96,6 +99,7 @@ parseUrl(ParsedUrl& pUrl, std::string const& strUrl)
|
||||
std::string
|
||||
trimWhitespace(std::string str)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
boost::trim(str);
|
||||
return str;
|
||||
}
|
||||
@@ -103,6 +107,7 @@ trimWhitespace(std::string str)
|
||||
std::optional<std::uint64_t>
|
||||
toUint64(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint64_t result = 0;
|
||||
if (beast::lexicalCastChecked(result, s))
|
||||
return result;
|
||||
@@ -112,6 +117,7 @@ toUint64(std::string const& s)
|
||||
bool
|
||||
isProperlyFormedTomlDomain(std::string_view domain)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// The domain must be between 4 and 128 characters long
|
||||
if (domain.size() < 4 || domain.size() > 128)
|
||||
return false;
|
||||
|
||||
304
src/libxrpl/basics/TraceLog.cpp
Normal file
304
src/libxrpl/basics/TraceLog.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
namespace {
|
||||
|
||||
std::atomic<bool> s_enabled{false};
|
||||
std::atomic<double> s_samplingRate{1.0};
|
||||
std::atomic<std::uint64_t> s_nextSpanId{1};
|
||||
std::mutex s_fileMutex;
|
||||
std::FILE* s_file{nullptr};
|
||||
std::string s_basePath;
|
||||
std::uint64_t s_maxFileSize{500ULL * 1024 * 1024};
|
||||
int s_maxFiles{10};
|
||||
std::uint64_t s_currentFileSize{0};
|
||||
|
||||
constexpr int kMaxStackDepth = 512;
|
||||
constexpr std::size_t kFlushThreshold = 65536;
|
||||
|
||||
struct ThreadContext
|
||||
{
|
||||
std::uint64_t traceId{0};
|
||||
std::uint64_t spanStack[kMaxStackDepth];
|
||||
int stackDepth{0};
|
||||
bool sampled{true};
|
||||
std::string buffer;
|
||||
};
|
||||
|
||||
thread_local ThreadContext t_ctx;
|
||||
|
||||
std::uint64_t
|
||||
generateTraceId()
|
||||
{
|
||||
thread_local std::mt19937_64 rng(
|
||||
std::chrono::steady_clock::now().time_since_epoch().count() ^
|
||||
std::hash<std::thread::id>{}(std::this_thread::get_id()));
|
||||
return rng();
|
||||
}
|
||||
|
||||
void
|
||||
rotateFiles()
|
||||
{
|
||||
if (s_file)
|
||||
{
|
||||
std::fclose(s_file);
|
||||
s_file = nullptr;
|
||||
}
|
||||
|
||||
// traces.jsonl.9 -> delete, traces.jsonl.8 -> .9, ... .0 -> .1
|
||||
for (int i = s_maxFiles - 1; i >= 0; --i)
|
||||
{
|
||||
std::string src =
|
||||
(i == 0) ? s_basePath : (s_basePath + "." + std::to_string(i));
|
||||
std::string dst = s_basePath + "." + std::to_string(i + 1);
|
||||
|
||||
if (i == s_maxFiles - 1)
|
||||
std::remove(src.c_str());
|
||||
else
|
||||
std::rename(src.c_str(), dst.c_str());
|
||||
}
|
||||
|
||||
s_file = std::fopen(s_basePath.c_str(), "w");
|
||||
s_currentFileSize = 0;
|
||||
}
|
||||
|
||||
void
|
||||
flushBuffer()
|
||||
{
|
||||
if (t_ctx.buffer.empty())
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(s_fileMutex);
|
||||
if (s_file)
|
||||
{
|
||||
auto written =
|
||||
std::fwrite(t_ctx.buffer.data(), 1, t_ctx.buffer.size(), s_file);
|
||||
std::fflush(s_file);
|
||||
s_currentFileSize += written;
|
||||
|
||||
if (s_currentFileSize >= s_maxFileSize)
|
||||
rotateFiles();
|
||||
}
|
||||
t_ctx.buffer.clear();
|
||||
}
|
||||
|
||||
char const*
|
||||
extractFilename(char const* path)
|
||||
{
|
||||
char const* last = path;
|
||||
for (char const* p = path; *p; ++p)
|
||||
{
|
||||
if (*p == '/' || *p == '\\')
|
||||
last = p + 1;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
void
|
||||
appendJsonString(std::string& buf, char const* s)
|
||||
{
|
||||
buf += '"';
|
||||
for (; *s; ++s)
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '"':
|
||||
buf += "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
buf += "\\\\";
|
||||
break;
|
||||
case '\n':
|
||||
buf += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
buf += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
buf += "\\t";
|
||||
break;
|
||||
default:
|
||||
buf += *s;
|
||||
}
|
||||
}
|
||||
buf += '"';
|
||||
}
|
||||
|
||||
void
|
||||
appendHex(std::string& buf, std::uint64_t val)
|
||||
{
|
||||
static constexpr char kHEX[] = "0123456789abcdef";
|
||||
char hex[17];
|
||||
for (int i = 15; i >= 0; --i)
|
||||
{
|
||||
hex[i] = kHEX[val & 0xf];
|
||||
val >>= 4;
|
||||
}
|
||||
hex[16] = '\0';
|
||||
buf.append(hex, 16);
|
||||
}
|
||||
|
||||
void
|
||||
writeSpan(
|
||||
std::uint64_t traceId,
|
||||
std::uint64_t spanId,
|
||||
std::uint64_t parentId,
|
||||
char const* name,
|
||||
char const* file,
|
||||
int line,
|
||||
std::int64_t startUs,
|
||||
std::int64_t durUs)
|
||||
{
|
||||
auto& buf = t_ctx.buffer;
|
||||
|
||||
buf += "{\"name\":";
|
||||
appendJsonString(buf, name);
|
||||
buf += ",\"trace\":\"";
|
||||
appendHex(buf, traceId);
|
||||
buf += "\",\"span\":\"";
|
||||
appendHex(buf, spanId);
|
||||
buf += "\",\"parent\":\"";
|
||||
appendHex(buf, parentId);
|
||||
buf += "\",\"file\":";
|
||||
appendJsonString(buf, extractFilename(file));
|
||||
buf += ",\"line\":";
|
||||
buf += std::to_string(line);
|
||||
buf += ",\"start_us\":";
|
||||
buf += std::to_string(startUs);
|
||||
buf += ",\"dur_us\":";
|
||||
buf += std::to_string(durUs);
|
||||
buf += "}\n";
|
||||
|
||||
if (buf.size() > kFlushThreshold || t_ctx.stackDepth == 0)
|
||||
flushBuffer();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace tracing {
|
||||
|
||||
void
|
||||
init(char const* outputPath, double samplingRate, std::uint64_t maxFileSizeMB, int maxFiles)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_fileMutex);
|
||||
if (s_file)
|
||||
std::fclose(s_file);
|
||||
s_basePath = outputPath;
|
||||
s_maxFileSize = maxFileSizeMB * 1024ULL * 1024ULL;
|
||||
s_maxFiles = maxFiles;
|
||||
s_file = std::fopen(outputPath, "a");
|
||||
if (s_file)
|
||||
{
|
||||
std::fseek(s_file, 0, SEEK_END);
|
||||
s_currentFileSize = static_cast<std::uint64_t>(std::ftell(s_file));
|
||||
}
|
||||
s_samplingRate.store(samplingRate, std::memory_order_relaxed);
|
||||
s_enabled.store(s_file != nullptr, std::memory_order_release);
|
||||
}
|
||||
|
||||
void
|
||||
shutdown()
|
||||
{
|
||||
s_enabled.store(false, std::memory_order_release);
|
||||
std::lock_guard<std::mutex> lock(s_fileMutex);
|
||||
if (s_file)
|
||||
{
|
||||
std::fclose(s_file);
|
||||
s_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tracing
|
||||
|
||||
TraceScope::TraceScope(
|
||||
char const* func,
|
||||
char const* file,
|
||||
int line) noexcept
|
||||
: spanId_(0)
|
||||
, traceId_(0)
|
||||
, parentId_(0)
|
||||
, func_(func)
|
||||
, file_(file)
|
||||
, line_(line)
|
||||
, startUs_(0)
|
||||
, active_(false)
|
||||
{
|
||||
if (!s_enabled.load(std::memory_order_relaxed))
|
||||
return;
|
||||
|
||||
spanId_ = s_nextSpanId.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
if (t_ctx.stackDepth == 0)
|
||||
{
|
||||
traceId_ = generateTraceId();
|
||||
parentId_ = 0;
|
||||
|
||||
double rate = s_samplingRate.load(std::memory_order_relaxed);
|
||||
if (rate < 1.0)
|
||||
{
|
||||
thread_local std::mt19937 samplerRng(std::random_device{}());
|
||||
std::uniform_real_distribution<double> dist(0.0, 1.0);
|
||||
t_ctx.sampled = dist(samplerRng) < rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
t_ctx.sampled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traceId_ = t_ctx.traceId;
|
||||
parentId_ = t_ctx.spanStack[t_ctx.stackDepth - 1];
|
||||
}
|
||||
|
||||
t_ctx.traceId = traceId_;
|
||||
if (t_ctx.stackDepth < kMaxStackDepth)
|
||||
t_ctx.spanStack[t_ctx.stackDepth] = spanId_;
|
||||
++t_ctx.stackDepth;
|
||||
|
||||
if (!t_ctx.sampled)
|
||||
return;
|
||||
|
||||
startUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
TraceScope::~TraceScope() noexcept
|
||||
{
|
||||
if (spanId_ == 0)
|
||||
return;
|
||||
|
||||
if (active_)
|
||||
{
|
||||
auto const endUs =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
writeSpan(
|
||||
traceId_,
|
||||
spanId_,
|
||||
parentId_,
|
||||
func_,
|
||||
file_,
|
||||
line_,
|
||||
startUs_,
|
||||
endUs - startUs_);
|
||||
}
|
||||
|
||||
--t_ctx.stackDepth;
|
||||
if (t_ctx.stackDepth == 0)
|
||||
t_ctx.traceId = 0;
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include <xrpl/basics/UptimeClock.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
@@ -13,6 +14,7 @@ std::atomic<bool> UptimeClock::kSTOP{false}; // stop update thread
|
||||
// On xrpld shutdown, cancel and wait for the update thread
|
||||
UptimeClock::UpdateThread::~UpdateThread()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (joinable())
|
||||
{
|
||||
kSTOP = true;
|
||||
@@ -26,6 +28,7 @@ UptimeClock::UpdateThread::~UpdateThread()
|
||||
UptimeClock::UpdateThread
|
||||
UptimeClock::startClock()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return UpdateThread{[] {
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
@@ -48,6 +51,7 @@ UptimeClock::startClock()
|
||||
UptimeClock::time_point
|
||||
UptimeClock::now()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// start the update thread on first use
|
||||
static auto const kINIT = startClock();
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
*/
|
||||
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -47,6 +48,7 @@ namespace base64 {
|
||||
inline char const*
|
||||
getAlphabet()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static char constexpr kTAB[] = {
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
|
||||
return &kTAB[0];
|
||||
@@ -55,6 +57,7 @@ getAlphabet()
|
||||
inline signed char const*
|
||||
getInverse()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static signed char constexpr kTAB[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
|
||||
@@ -103,6 +106,7 @@ std::size_t constexpr decodedSize(std::size_t n)
|
||||
std::size_t
|
||||
encode(void* dest, void const* src, std::size_t len)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char* out = static_cast<char*>(dest); // NOLINT(misc-const-correctness)
|
||||
char const* in = static_cast<char const*>(src);
|
||||
auto const tab = base64::getAlphabet();
|
||||
@@ -154,6 +158,7 @@ encode(void* dest, void const* src, std::size_t len)
|
||||
std::pair<std::size_t, std::size_t>
|
||||
decode(void* dest, char const* src, std::size_t len)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char* out = static_cast<char*>(dest); // NOLINT(misc-const-correctness)
|
||||
auto in = reinterpret_cast<unsigned char const*>(src);
|
||||
unsigned char c3[3]{}, c4[4]{};
|
||||
@@ -199,6 +204,7 @@ decode(void* dest, char const* src, std::size_t len)
|
||||
std::string
|
||||
base64Encode(std::uint8_t const* data, std::size_t len)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string dest;
|
||||
dest.resize(base64::encodedSize(len));
|
||||
dest.resize(base64::encode(&dest[0], data, len));
|
||||
@@ -208,6 +214,7 @@ base64Encode(std::uint8_t const* data, std::size_t len)
|
||||
std::string
|
||||
base64Decode(std::string_view data)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string dest;
|
||||
dest.resize(base64::decodedSize(data.size()));
|
||||
auto const result = base64::decode(&dest[0], data.data(), data.size());
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
@@ -12,12 +13,14 @@ namespace xrpl {
|
||||
void
|
||||
logThrow(std::string const& title)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JLOG(debugLog().warn()) << title;
|
||||
}
|
||||
|
||||
[[noreturn]] void
|
||||
logicError(std::string const& s) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// LCOV_EXCL_START
|
||||
JLOG(debugLog().fatal()) << s;
|
||||
std::cerr << "Logic error: " << s << std::endl;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/basics/make_SSLContext.h>
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <boost/asio/ssl/verify_mode.hpp>
|
||||
@@ -89,6 +90,7 @@ std::string const kDEFAULT_CIPHER_LIST = "TLSv1.2:!CBC:!DSS:!PSK:!eNULL:!aNULL";
|
||||
static void
|
||||
initAnonymous(boost::asio::ssl::context& context)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace openssl;
|
||||
|
||||
static auto kDEFAULT_RSA = []() {
|
||||
@@ -229,6 +231,7 @@ initAuthenticated(
|
||||
std::string const& certFile,
|
||||
std::string const& chainFile)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto fmtError = [](boost::system::error_code ec) -> std::string {
|
||||
return " [" + std::to_string(ec.value()) + ": " + ec.message() + "]";
|
||||
};
|
||||
@@ -321,6 +324,7 @@ initAuthenticated(
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
getContext(std::string cipherList)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto c = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
|
||||
|
||||
c->set_options(
|
||||
@@ -352,6 +356,7 @@ getContext(std::string cipherList)
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
makeSslContext(std::string const& cipherList)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto context = openssl::detail::getContext(cipherList);
|
||||
openssl::detail::initAnonymous(*context);
|
||||
// VFALCO NOTE, It seems the WebSocket context never has
|
||||
@@ -367,6 +372,7 @@ makeSslContextAuthed(
|
||||
std::string const& chainFile,
|
||||
std::string const& cipherList)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto context = openssl::detail::getContext(cipherList);
|
||||
openssl::detail::initAuthenticated(*context, keyFile, certFile, chainFile);
|
||||
return context;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpl/basics/mulDiv.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp> // IWYU pragma: keep
|
||||
|
||||
@@ -10,6 +11,7 @@ namespace xrpl {
|
||||
std::optional<std::uint64_t>
|
||||
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
boost::multiprecision::uint128_t result;
|
||||
result = multiply(result, value, mul);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -57,6 +58,7 @@ constexpr std::size_t kFINGERPRINT_SIZE = 32;
|
||||
std::unique_ptr<Condition>
|
||||
loadSimpleSha256(Type type, Slice s, std::error_code& ec)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace der;
|
||||
|
||||
auto p = parsePreamble(s, ec);
|
||||
@@ -137,6 +139,7 @@ loadSimpleSha256(Type type, Slice s, std::error_code& ec)
|
||||
std::unique_ptr<Condition>
|
||||
Condition::deserialize(Slice s, std::error_code& ec)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Per the RFC, in a condition we choose a type based
|
||||
// on the tag of the item we contain:
|
||||
//
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
@@ -15,6 +16,7 @@ namespace xrpl::cryptoconditions {
|
||||
bool
|
||||
match(Fulfillment const& f, Condition const& c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Fast check: the fulfillment's type must match the
|
||||
// conditions's type:
|
||||
if (f.type() != c.type)
|
||||
@@ -28,18 +30,21 @@ match(Fulfillment const& f, Condition const& c)
|
||||
bool
|
||||
validate(Fulfillment const& f, Condition const& c, Slice m)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return match(f, c) && f.validate(m);
|
||||
}
|
||||
|
||||
bool
|
||||
validate(Fulfillment const& f, Condition const& c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return validate(f, c, {});
|
||||
}
|
||||
|
||||
std::unique_ptr<Fulfillment>
|
||||
Fulfillment::deserialize(Slice s, std::error_code& ec)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Per the RFC, in a fulfillment we choose a type based
|
||||
// on the tag of the item we contain:
|
||||
//
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
@@ -17,12 +18,14 @@ public:
|
||||
[[nodiscard]] char const*
|
||||
name() const noexcept override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return "cryptoconditions";
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (safeCast<Error>(ev))
|
||||
{
|
||||
case Error::UnsupportedType:
|
||||
@@ -82,18 +85,21 @@ public:
|
||||
[[nodiscard]] std::error_condition
|
||||
default_error_condition(int ev) const noexcept override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::error_condition{ev, *this};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
equivalent(int ev, std::error_condition const& condition) const noexcept override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return &condition.category() == this && condition.value() == ev;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
equivalent(std::error_code const& error, int ev) const noexcept override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return &error.category() == this && error.value() == ev;
|
||||
}
|
||||
};
|
||||
@@ -101,6 +107,7 @@ public:
|
||||
inline std::error_category const&
|
||||
getCryptoconditionsErrorCategory()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static CryptoconditionsErrorCategory const kCAT{};
|
||||
return kCAT;
|
||||
}
|
||||
@@ -110,6 +117,7 @@ getCryptoconditionsErrorCategory()
|
||||
std::error_code
|
||||
make_error_code(Error ev)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::error_code{
|
||||
safeCast<std::underlying_type_t<Error>>(ev), detail::getCryptoconditionsErrorCategory()};
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/beast/container/detail/aged_unordered_container.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
@@ -17,6 +18,7 @@ namespace xrpl {
|
||||
auto
|
||||
HashRouter::emplace(uint256 const& key) -> std::pair<Entry&, bool>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto iter = suppressionMap_.find(key);
|
||||
|
||||
if (iter != suppressionMap_.end())
|
||||
@@ -34,6 +36,7 @@ HashRouter::emplace(uint256 const& key) -> std::pair<Entry&, bool>
|
||||
void
|
||||
HashRouter::addSuppression(uint256 const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
emplace(key);
|
||||
@@ -42,12 +45,14 @@ HashRouter::addSuppression(uint256 const& key)
|
||||
bool
|
||||
HashRouter::addSuppressionPeer(uint256 const& key, PeerShortID peer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return addSuppressionPeerWithStatus(key, peer).first;
|
||||
}
|
||||
|
||||
std::pair<bool, std::optional<Stopwatch::time_point>>
|
||||
HashRouter::addSuppressionPeerWithStatus(uint256 const& key, PeerShortID peer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
auto result = emplace(key);
|
||||
@@ -58,6 +63,7 @@ HashRouter::addSuppressionPeerWithStatus(uint256 const& key, PeerShortID peer)
|
||||
bool
|
||||
HashRouter::addSuppressionPeer(uint256 const& key, PeerShortID peer, HashRouterFlags& flags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
auto [s, created] = emplace(key);
|
||||
@@ -73,6 +79,7 @@ HashRouter::shouldProcess(
|
||||
HashRouterFlags& flags,
|
||||
std::chrono::seconds txInterval)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
auto result = emplace(key);
|
||||
@@ -85,6 +92,7 @@ HashRouter::shouldProcess(
|
||||
HashRouterFlags
|
||||
HashRouter::getFlags(uint256 const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
return emplace(key).first.getFlags();
|
||||
@@ -93,6 +101,7 @@ HashRouter::getFlags(uint256 const& key)
|
||||
bool
|
||||
HashRouter::setFlags(uint256 const& key, HashRouterFlags flags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(static_cast<bool>(flags), "xrpl::HashRouter::setFlags : valid input");
|
||||
|
||||
std::scoped_lock const lock(mutex_);
|
||||
@@ -109,6 +118,7 @@ HashRouter::setFlags(uint256 const& key, HashRouterFlags flags)
|
||||
auto
|
||||
HashRouter::shouldRelay(uint256 const& key) -> std::optional<std::set<PeerShortID>>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
auto& s = emplace(key).first;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -27,24 +28,28 @@ Job::Job(
|
||||
std::function<void()> const& job)
|
||||
: type_(type), jobIndex_(index), job_(job), name_(name), queue_time_(clock_type::now())
|
||||
{
|
||||
TRACE_FUNC();
|
||||
loadEvent_ = std::make_shared<LoadEvent>(std::ref(lm), name, false);
|
||||
}
|
||||
|
||||
JobType
|
||||
Job::getType() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_;
|
||||
}
|
||||
|
||||
Job::clock_type::time_point const&
|
||||
Job::queueTime() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return queue_time_;
|
||||
}
|
||||
|
||||
void
|
||||
Job::doJob()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
beast::setCurrentThreadName("j:" + name_);
|
||||
loadEvent_->start();
|
||||
loadEvent_->setName(name_);
|
||||
@@ -59,6 +64,7 @@ Job::doJob()
|
||||
bool
|
||||
Job::operator>(Job const& j) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (type_ < j.type_)
|
||||
return true;
|
||||
|
||||
@@ -71,6 +77,7 @@ Job::operator>(Job const& j) const
|
||||
bool
|
||||
Job::operator>=(Job const& j) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (type_ < j.type_)
|
||||
return true;
|
||||
|
||||
@@ -83,6 +90,7 @@ Job::operator>=(Job const& j) const
|
||||
bool
|
||||
Job::operator<(Job const& j) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (type_ < j.type_)
|
||||
return false;
|
||||
|
||||
@@ -95,6 +103,7 @@ Job::operator<(Job const& j) const
|
||||
bool
|
||||
Job::operator<=(Job const& j) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (type_ < j.type_)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
#include <xrpl/core/PerfLog.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -33,6 +34,7 @@ JobQueue::JobQueue(
|
||||
, perfLog_(perfLog)
|
||||
, collector_(collector)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JLOG(journal_.info()) << "Using " << threadCount << " threads";
|
||||
|
||||
hook_ = collector_->makeHook(std::bind(&JobQueue::collect, this));
|
||||
@@ -58,6 +60,7 @@ JobQueue::JobQueue(
|
||||
|
||||
JobQueue::~JobQueue()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Must unhook before destroying
|
||||
hook_ = beast::insight::Hook();
|
||||
}
|
||||
@@ -65,6 +68,7 @@ JobQueue::~JobQueue()
|
||||
void
|
||||
JobQueue::collect()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
job_count_ = jobSet_.size();
|
||||
}
|
||||
@@ -72,6 +76,7 @@ JobQueue::collect()
|
||||
bool
|
||||
JobQueue::addRefCountedJob(JobType type, std::string const& name, JobFunction const& func)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(type != JtInvalid, "xrpl::JobQueue::addRefCountedJob : valid input job type");
|
||||
|
||||
auto iter(jobData_.find(type));
|
||||
@@ -119,6 +124,7 @@ JobQueue::addRefCountedJob(JobType type, std::string const& name, JobFunction co
|
||||
int
|
||||
JobQueue::getJobCount(JobType t) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
JobDataMap::const_iterator const c = jobData_.find(t);
|
||||
@@ -129,6 +135,7 @@ JobQueue::getJobCount(JobType t) const
|
||||
int
|
||||
JobQueue::getJobCountTotal(JobType t) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
JobDataMap::const_iterator const c = jobData_.find(t);
|
||||
@@ -139,6 +146,7 @@ JobQueue::getJobCountTotal(JobType t) const
|
||||
int
|
||||
JobQueue::getJobCountGE(JobType t) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// return the number of jobs at this priority level or greater
|
||||
int ret = 0;
|
||||
|
||||
@@ -156,6 +164,7 @@ JobQueue::getJobCountGE(JobType t) const
|
||||
std::unique_ptr<LoadEvent>
|
||||
JobQueue::makeLoadEvent(JobType t, std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JobDataMap::iterator const iter(jobData_.find(t));
|
||||
XRPL_ASSERT(iter != jobData_.end(), "xrpl::JobQueue::makeLoadEvent : valid job type input");
|
||||
|
||||
@@ -168,6 +177,7 @@ JobQueue::makeLoadEvent(JobType t, std::string const& name)
|
||||
void
|
||||
JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isStopped())
|
||||
logicError("JobQueue::addLoadEvents() called after JobQueue stopped");
|
||||
|
||||
@@ -179,12 +189,14 @@ JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed)
|
||||
bool
|
||||
JobQueue::isOverloaded()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::ranges::any_of(jobData_, [](auto& entry) { return entry.second.load().isOver(); });
|
||||
}
|
||||
|
||||
json::Value
|
||||
JobQueue::getJson(int c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono_literals;
|
||||
json::Value ret(json::ObjectValue);
|
||||
|
||||
@@ -242,6 +254,7 @@ JobQueue::getJson(int c)
|
||||
void
|
||||
JobQueue::rendezvous()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cv_.wait(lock, [this] { return processCount_ == 0 && jobSet_.empty(); });
|
||||
}
|
||||
@@ -249,6 +262,7 @@ JobQueue::rendezvous()
|
||||
JobTypeData&
|
||||
JobQueue::getJobTypeData(JobType type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JobDataMap::iterator const c(jobData_.find(type));
|
||||
XRPL_ASSERT(c != jobData_.end(), "xrpl::JobQueue::getJobTypeData : valid job type input");
|
||||
|
||||
@@ -263,6 +277,7 @@ JobQueue::getJobTypeData(JobType type)
|
||||
void
|
||||
JobQueue::stop()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stopping_ = true;
|
||||
using namespace std::chrono_literals;
|
||||
jobCounter_.join("JobQueue", 1s, journal_);
|
||||
@@ -284,12 +299,14 @@ JobQueue::stop()
|
||||
bool
|
||||
JobQueue::isStopped() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return stopped_;
|
||||
}
|
||||
|
||||
void
|
||||
JobQueue::getNextJob(Job& job)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!jobSet_.empty(), "xrpl::JobQueue::getNextJob : non-empty jobs");
|
||||
|
||||
std::set<Job>::const_iterator iter;
|
||||
@@ -320,6 +337,7 @@ JobQueue::getNextJob(Job& job)
|
||||
void
|
||||
JobQueue::finishJob(JobType type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(type != JtInvalid, "xrpl::JobQueue::finishJob : valid input job type");
|
||||
|
||||
JobTypeData& data = getJobTypeData(type);
|
||||
@@ -341,6 +359,7 @@ JobQueue::finishJob(JobType type)
|
||||
void
|
||||
JobQueue::processTask(int instance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JobType type = JtInvalid;
|
||||
|
||||
{
|
||||
@@ -392,6 +411,7 @@ JobQueue::processTask(int instance)
|
||||
int
|
||||
JobQueue::getJobLimit(JobType type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JobTypeInfo const& j(JobTypes::instance().get(type));
|
||||
XRPL_ASSERT(j.type() != JtInvalid, "xrpl::JobQueue::getJobLimit : valid job type");
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/core/LoadMonitor.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
@@ -21,6 +22,7 @@ LoadEvent::LoadEvent(LoadMonitor& monitor, std::string name, bool shouldStart)
|
||||
|
||||
LoadEvent::~LoadEvent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (running_)
|
||||
stop();
|
||||
}
|
||||
@@ -28,30 +30,35 @@ LoadEvent::~LoadEvent()
|
||||
std::string const&
|
||||
LoadEvent::name() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::chrono::steady_clock::duration
|
||||
LoadEvent::waitTime() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return timeWaiting_;
|
||||
}
|
||||
|
||||
std::chrono::steady_clock::duration
|
||||
LoadEvent::runTime() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return timeRunning_;
|
||||
}
|
||||
|
||||
void
|
||||
LoadEvent::setName(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
void
|
||||
LoadEvent::start()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const now = std::chrono::steady_clock::now();
|
||||
|
||||
// If we had already called start, this call will
|
||||
@@ -65,6 +72,7 @@ LoadEvent::start()
|
||||
void
|
||||
LoadEvent::stop()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(running_, "xrpl::LoadEvent::stop : is running");
|
||||
|
||||
auto const now = std::chrono::steady_clock::now();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/basics/UptimeClock.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/LoadEvent.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
@@ -46,6 +47,7 @@ LoadMonitor::LoadMonitor(beast::Journal j)
|
||||
void
|
||||
LoadMonitor::update()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono_literals;
|
||||
auto now = UptimeClock::now();
|
||||
if (now == lastUpdate_) // current
|
||||
@@ -84,6 +86,7 @@ LoadMonitor::update()
|
||||
void
|
||||
LoadMonitor::addLoadSample(LoadEvent const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono;
|
||||
|
||||
auto const total = s.runTime() + s.waitTime();
|
||||
@@ -108,6 +111,7 @@ LoadMonitor::addLoadSample(LoadEvent const& s)
|
||||
void
|
||||
LoadMonitor::addSamples(int count, std::chrono::milliseconds latency)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(mutex_);
|
||||
|
||||
update();
|
||||
@@ -125,6 +129,7 @@ LoadMonitor::addSamples(int count, std::chrono::milliseconds latency)
|
||||
void
|
||||
LoadMonitor::setTargetLatency(std::chrono::milliseconds avg, std::chrono::milliseconds pk)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
targetLatencyAvg_ = avg;
|
||||
targetLatencyPk_ = pk;
|
||||
}
|
||||
@@ -132,6 +137,7 @@ LoadMonitor::setTargetLatency(std::chrono::milliseconds avg, std::chrono::millis
|
||||
bool
|
||||
LoadMonitor::isOverTarget(std::chrono::milliseconds avg, std::chrono::milliseconds peak)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono_literals;
|
||||
return (targetLatencyPk_ > 0ms && (peak > targetLatencyPk_)) ||
|
||||
(targetLatencyAvg_ > 0ms && (avg > targetLatencyAvg_));
|
||||
@@ -140,6 +146,7 @@ LoadMonitor::isOverTarget(std::chrono::milliseconds avg, std::chrono::millisecon
|
||||
bool
|
||||
LoadMonitor::isOver()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(mutex_);
|
||||
|
||||
update();
|
||||
@@ -154,6 +161,7 @@ LoadMonitor::isOver()
|
||||
LoadMonitor::Stats
|
||||
LoadMonitor::getStats()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono_literals;
|
||||
Stats stats;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||
#include <xrpl/beast/core/LockFreeStack.h>
|
||||
#include <xrpl/core/PerfLog.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -23,11 +24,13 @@ Workers::Workers(
|
||||
, pauseCount_(0)
|
||||
, runningTaskCount_(0)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
setNumberOfThreads(numberOfThreads);
|
||||
}
|
||||
|
||||
Workers::~Workers()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stop();
|
||||
|
||||
deleteWorkers(everyone_);
|
||||
@@ -36,6 +39,7 @@ Workers::~Workers()
|
||||
int
|
||||
Workers::getNumberOfThreads() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return numberOfThreads_;
|
||||
}
|
||||
|
||||
@@ -46,6 +50,7 @@ Workers::getNumberOfThreads() const noexcept
|
||||
void
|
||||
Workers::setNumberOfThreads(int numberOfThreads)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static int kINSTANCE{0};
|
||||
if (numberOfThreads_ == numberOfThreads)
|
||||
return;
|
||||
@@ -97,6 +102,7 @@ Workers::setNumberOfThreads(int numberOfThreads)
|
||||
void
|
||||
Workers::stop()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
setNumberOfThreads(0);
|
||||
|
||||
// Wait until all workers have paused AND no tasks are actively running.
|
||||
@@ -111,18 +117,21 @@ Workers::stop()
|
||||
void
|
||||
Workers::addTask()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
semaphore_.notify();
|
||||
}
|
||||
|
||||
int
|
||||
Workers::numberOfCurrentlyRunningTasks() const noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return runningTaskCount_.load();
|
||||
}
|
||||
|
||||
void
|
||||
Workers::deleteWorkers(beast::LockFreeStack<Worker>& stack)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (;;)
|
||||
{
|
||||
Worker const* const worker = stack.popFront();
|
||||
@@ -145,11 +154,13 @@ Workers::Worker::Worker(Workers& workers, std::string threadName, int const inst
|
||||
: workers_{workers}, threadName_{std::move(threadName)}, instance_{instance}
|
||||
|
||||
{
|
||||
TRACE_FUNC();
|
||||
thread_ = std::thread{&Workers::Worker::run, this};
|
||||
}
|
||||
|
||||
Workers::Worker::~Worker()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
{
|
||||
std::scoped_lock const lock{mutex_};
|
||||
++wakeCount_;
|
||||
@@ -163,6 +174,7 @@ Workers::Worker::~Worker()
|
||||
void
|
||||
Workers::Worker::notify()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock{mutex_};
|
||||
++wakeCount_;
|
||||
wakeup_.notify_one();
|
||||
@@ -171,6 +183,7 @@ Workers::Worker::notify()
|
||||
void
|
||||
Workers::Worker::run()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool shouldExit = true;
|
||||
do
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/crypto/RFC1751.h>
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
@@ -199,6 +200,7 @@ char const* RFC1751::dictionary[2048] = {
|
||||
unsigned long
|
||||
RFC1751::extract(char const* s, int start, int length)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
unsigned char cl = 0;
|
||||
unsigned char cc = 0;
|
||||
unsigned char cr = 0;
|
||||
@@ -226,6 +228,7 @@ RFC1751::extract(char const* s, int start, int length)
|
||||
void
|
||||
RFC1751::btoe(std::string& strHuman, std::string const& strData)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char caBuffer[9]; /* add in room for the parity 2 bits*/
|
||||
int p = 0, i = 0;
|
||||
|
||||
@@ -246,6 +249,7 @@ RFC1751::btoe(std::string& strHuman, std::string const& strData)
|
||||
void
|
||||
RFC1751::insert(char* s, int x, int start, int length)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
unsigned char cl = 0;
|
||||
unsigned char cc = 0;
|
||||
unsigned char cr = 0;
|
||||
@@ -283,6 +287,7 @@ RFC1751::insert(char* s, int x, int start, int length)
|
||||
void
|
||||
RFC1751::standard(std::string& strWord)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto& letter : strWord)
|
||||
{
|
||||
if (islower(static_cast<unsigned char>(letter)) != 0)
|
||||
@@ -308,6 +313,7 @@ RFC1751::standard(std::string& strWord)
|
||||
int
|
||||
RFC1751::wsrch(std::string const& strWord, int iMin, int iMax)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
int iResult = -1;
|
||||
|
||||
while (iResult < 0 && iMin != iMax)
|
||||
@@ -342,6 +348,7 @@ RFC1751::wsrch(std::string const& strWord, int iMin, int iMax)
|
||||
int
|
||||
RFC1751::etob(std::string& strData, std::vector<std::string> vsHuman)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (6 != vsHuman.size())
|
||||
return -1;
|
||||
|
||||
@@ -389,6 +396,7 @@ RFC1751::etob(std::string& strData, std::vector<std::string> vsHuman)
|
||||
int
|
||||
RFC1751::getKeyFromEnglish(std::string& strKey, std::string const& strHuman)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<std::string> vWords;
|
||||
std::string strFirst, strSecond;
|
||||
int rc = 0;
|
||||
@@ -419,6 +427,7 @@ RFC1751::getKeyFromEnglish(std::string& strKey, std::string const& strHuman)
|
||||
void
|
||||
RFC1751::getEnglishFromKey(std::string& strHuman, std::string const& strKey)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string strFirst, strSecond;
|
||||
|
||||
btoe(strFirst, strKey.substr(0, 8));
|
||||
@@ -430,6 +439,7 @@ RFC1751::getEnglishFromKey(std::string& strHuman, std::string const& strKey)
|
||||
std::string
|
||||
RFC1751::getWordFromBlob(void const* blob, size_t bytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This is a simple implementation of the Jenkins one-at-a-time hash
|
||||
// algorithm:
|
||||
// http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/crypto/csprng.h>
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/rand.h>
|
||||
@@ -15,6 +16,7 @@ namespace xrpl {
|
||||
|
||||
CsprngEngine::CsprngEngine()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This is not strictly necessary
|
||||
if (RAND_poll() != 1)
|
||||
Throw<std::runtime_error>("CSPRNG: Initial polling failed");
|
||||
@@ -22,6 +24,7 @@ CsprngEngine::CsprngEngine()
|
||||
|
||||
CsprngEngine::~CsprngEngine()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This cleanup function is not needed in newer versions of OpenSSL
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
RAND_cleanup();
|
||||
@@ -31,6 +34,7 @@ CsprngEngine::~CsprngEngine()
|
||||
void
|
||||
CsprngEngine::mixEntropy(void* buffer, std::size_t count)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::array<std::random_device::result_type, 128> entropy{};
|
||||
|
||||
{
|
||||
@@ -56,6 +60,7 @@ CsprngEngine::mixEntropy(void* buffer, std::size_t count)
|
||||
void
|
||||
CsprngEngine::operator()(void* ptr, std::size_t count)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// RAND_bytes is thread-safe on OpenSSL 1.1.0 and later when compiled
|
||||
// with thread support, so we don't need to grab a mutex.
|
||||
// https://mta.openssl.org/pipermail/openssl-users/2020-November/013146.html
|
||||
@@ -72,6 +77,7 @@ CsprngEngine::operator()(void* ptr, std::size_t count)
|
||||
CsprngEngine::result_type
|
||||
CsprngEngine::operator()()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
result_type ret = 0;
|
||||
(*this)(&ret, sizeof(result_type));
|
||||
return ret;
|
||||
@@ -80,6 +86,7 @@ CsprngEngine::operator()()
|
||||
CsprngEngine&
|
||||
cryptoPrng()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static CsprngEngine kENGINE;
|
||||
return kENGINE;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpl/crypto/secure_erase.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
@@ -9,6 +10,7 @@ namespace xrpl {
|
||||
void
|
||||
secureErase(void* dest, std::size_t bytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
OPENSSL_cleanse(dest, bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/json/JsonPropertyStream.h>
|
||||
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -8,6 +9,7 @@ namespace xrpl {
|
||||
|
||||
JsonPropertyStream::JsonPropertyStream() : topValue(json::ObjectValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.reserve(64);
|
||||
stack.push_back(&topValue);
|
||||
}
|
||||
@@ -15,12 +17,14 @@ JsonPropertyStream::JsonPropertyStream() : topValue(json::ObjectValue)
|
||||
json::Value const&
|
||||
JsonPropertyStream::top() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return topValue;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::mapBegin()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// top is array
|
||||
json::Value& top(*stack.back());
|
||||
json::Value& map(top.append(json::ObjectValue));
|
||||
@@ -30,6 +34,7 @@ JsonPropertyStream::mapBegin()
|
||||
void
|
||||
JsonPropertyStream::mapBegin(std::string const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// top is a map
|
||||
json::Value& top(*stack.back());
|
||||
json::Value& map(top[key] = json::ObjectValue);
|
||||
@@ -39,60 +44,70 @@ JsonPropertyStream::mapBegin(std::string const& key)
|
||||
void
|
||||
JsonPropertyStream::mapEnd()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.pop_back();
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, short v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, unsigned short v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, int v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, unsigned int v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, long v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = int(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, float v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, double v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& key, std::string const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
(*stack.back())[key] = v;
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::arrayBegin()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// top is array
|
||||
json::Value& top(*stack.back());
|
||||
json::Value& vec(top.append(json::ArrayValue));
|
||||
@@ -102,6 +117,7 @@ JsonPropertyStream::arrayBegin()
|
||||
void
|
||||
JsonPropertyStream::arrayBegin(std::string const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// top is a map
|
||||
json::Value& top(*stack.back());
|
||||
json::Value& vec(top[key] = json::ArrayValue);
|
||||
@@ -111,54 +127,63 @@ JsonPropertyStream::arrayBegin(std::string const& key)
|
||||
void
|
||||
JsonPropertyStream::arrayEnd()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.pop_back();
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(short v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(unsigned short v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(int v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(unsigned int v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(long v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(int(v));
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(float v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(double v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
void
|
||||
JsonPropertyStream::add(std::string const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stack.back()->append(v);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/json/Writer.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -12,6 +13,7 @@ namespace {
|
||||
void
|
||||
outputJson(json::Value const& value, Writer& writer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (value.type())
|
||||
{
|
||||
case json::NullValue: {
|
||||
@@ -74,6 +76,7 @@ outputJson(json::Value const& value, Writer& writer)
|
||||
void
|
||||
outputJson(json::Value const& value, Output const& out)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Writer writer(out);
|
||||
outputJson(value, writer);
|
||||
}
|
||||
@@ -81,6 +84,7 @@ outputJson(json::Value const& value, Output const& out)
|
||||
std::string
|
||||
jsonAsString(json::Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string s;
|
||||
Writer writer(stringOutput(s));
|
||||
outputJson(value, writer);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/ToString.h>
|
||||
#include <xrpl/json/Output.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
@@ -42,6 +43,7 @@ auto const kINTEGRAL_FLOATS_BECOME_INTS = false;
|
||||
size_t
|
||||
lengthWithoutTrailingZeros(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto dotPos = s.find('.');
|
||||
if (dotPos == std::string::npos)
|
||||
return s.size();
|
||||
@@ -75,12 +77,14 @@ public:
|
||||
[[nodiscard]] bool
|
||||
empty() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return stack_.empty();
|
||||
}
|
||||
|
||||
void
|
||||
start(CollectionType ct)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char const ch = (ct == CollectionType::Array) ? kOPEN_BRACKET : kOPEN_BRACE;
|
||||
output({&ch, 1});
|
||||
stack_.emplace(Collection{.type = ct});
|
||||
@@ -89,6 +93,7 @@ public:
|
||||
void
|
||||
output(boost::beast::string_view const& bytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
markStarted();
|
||||
output_(bytes);
|
||||
}
|
||||
@@ -96,6 +101,7 @@ public:
|
||||
void
|
||||
stringOutput(boost::beast::string_view const& bytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
markStarted();
|
||||
std::size_t position = 0, writtenUntil = 0;
|
||||
|
||||
@@ -122,6 +128,7 @@ public:
|
||||
void
|
||||
markStarted()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
check(!isFinished(), "isFinished() in output.");
|
||||
isStarted_ = true;
|
||||
}
|
||||
@@ -129,6 +136,7 @@ public:
|
||||
void
|
||||
nextCollectionEntry(CollectionType type, std::string const& message)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
check(!empty(), "empty () in " + message);
|
||||
|
||||
auto t = stack_.top().type;
|
||||
@@ -151,6 +159,7 @@ public:
|
||||
void
|
||||
writeObjectTag(std::string const& tag)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
#ifndef NDEBUG
|
||||
// Make sure we haven't already seen this tag.
|
||||
auto& tags = stack_.top().tags;
|
||||
@@ -165,12 +174,14 @@ public:
|
||||
[[nodiscard]] bool
|
||||
isFinished() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isStarted_ && empty();
|
||||
}
|
||||
|
||||
void
|
||||
finish()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
check(!empty(), "Empty stack in finish()");
|
||||
|
||||
auto isArray = stack_.top().type == CollectionType::Array;
|
||||
@@ -182,6 +193,7 @@ public:
|
||||
void
|
||||
finishAll()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isStarted_)
|
||||
{
|
||||
while (!isFinished())
|
||||
@@ -192,6 +204,7 @@ public:
|
||||
[[nodiscard]] Output const&
|
||||
getOutput() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return output_;
|
||||
}
|
||||
|
||||
@@ -226,18 +239,21 @@ Writer::Writer(Output const& output) : impl_(std::make_unique<Impl>(output))
|
||||
|
||||
Writer::~Writer()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (impl_)
|
||||
impl_->finishAll();
|
||||
}
|
||||
|
||||
Writer::Writer(Writer&& w) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_ = std::move(w.impl_);
|
||||
}
|
||||
|
||||
Writer&
|
||||
Writer::operator=(Writer&& w) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_ = std::move(w.impl_);
|
||||
return *this;
|
||||
}
|
||||
@@ -245,18 +261,21 @@ Writer::operator=(Writer&& w) noexcept
|
||||
void
|
||||
Writer::output(char const* s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->stringOutput(s);
|
||||
}
|
||||
|
||||
void
|
||||
Writer::output(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->stringOutput(s);
|
||||
}
|
||||
|
||||
void
|
||||
Writer::output(json::Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->markStarted();
|
||||
outputJson(value, impl_->getOutput());
|
||||
}
|
||||
@@ -264,6 +283,7 @@ Writer::output(json::Value const& value)
|
||||
void
|
||||
Writer::output(float f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto s = xrpl::to_string(f);
|
||||
impl_->output({s.data(), lengthWithoutTrailingZeros(s)});
|
||||
}
|
||||
@@ -271,6 +291,7 @@ Writer::output(float f)
|
||||
void
|
||||
Writer::output(double f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto s = xrpl::to_string(f);
|
||||
impl_->output({s.data(), lengthWithoutTrailingZeros(s)});
|
||||
}
|
||||
@@ -278,24 +299,28 @@ Writer::output(double f)
|
||||
void
|
||||
Writer::output(std::nullptr_t)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->output("null");
|
||||
}
|
||||
|
||||
void
|
||||
Writer::output(bool b)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->output(b ? "true" : "false");
|
||||
}
|
||||
|
||||
void
|
||||
Writer::implOutput(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->output(s);
|
||||
}
|
||||
|
||||
void
|
||||
Writer::finishAll()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (impl_)
|
||||
impl_->finishAll();
|
||||
}
|
||||
@@ -303,12 +328,14 @@ Writer::finishAll()
|
||||
void
|
||||
Writer::rawAppend()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->nextCollectionEntry(CollectionType::Array, "append");
|
||||
}
|
||||
|
||||
void
|
||||
Writer::rawSet(std::string const& tag)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
check(!tag.empty(), "Tag can't be empty");
|
||||
|
||||
impl_->nextCollectionEntry(CollectionType::Object, "set");
|
||||
@@ -318,12 +345,14 @@ Writer::rawSet(std::string const& tag)
|
||||
void
|
||||
Writer::startRoot(CollectionType type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->start(type);
|
||||
}
|
||||
|
||||
void
|
||||
Writer::startAppend(CollectionType type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->nextCollectionEntry(CollectionType::Array, "startAppend");
|
||||
impl_->start(type);
|
||||
}
|
||||
@@ -331,6 +360,7 @@ Writer::startAppend(CollectionType type)
|
||||
void
|
||||
Writer::startSet(CollectionType type, std::string const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
impl_->nextCollectionEntry(CollectionType::Object, "startSet");
|
||||
impl_->writeObjectTag(key);
|
||||
impl_->start(type);
|
||||
@@ -339,6 +369,7 @@ Writer::startSet(CollectionType type, std::string const& key)
|
||||
void
|
||||
Writer::finish()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (impl_)
|
||||
impl_->finish();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@@ -19,6 +20,7 @@ namespace json {
|
||||
static std::string
|
||||
codePointToUTF8(unsigned int cp)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string result;
|
||||
|
||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||
@@ -59,6 +61,7 @@ codePointToUTF8(unsigned int cp)
|
||||
bool
|
||||
Reader::parse(std::string const& document, Value& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
document_ = document;
|
||||
char const* begin = document_.c_str();
|
||||
char const* end = begin + document_.length();
|
||||
@@ -68,6 +71,7 @@ Reader::parse(std::string const& document, Value& root)
|
||||
bool
|
||||
Reader::parse(std::istream& sin, Value& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// std::istream_iterator<char> begin(sin);
|
||||
// std::istream_iterator<char> end;
|
||||
// Those would allow streamed input from a file, if parse() were a
|
||||
@@ -83,6 +87,7 @@ Reader::parse(std::istream& sin, Value& root)
|
||||
bool
|
||||
Reader::parse(char const* beginDoc, char const* endDoc, Value& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
begin_ = beginDoc;
|
||||
end_ = endDoc;
|
||||
current_ = begin_;
|
||||
@@ -115,6 +120,7 @@ Reader::parse(char const* beginDoc, char const* endDoc, Value& root)
|
||||
bool
|
||||
Reader::readValue(unsigned depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Token token{};
|
||||
skipCommentTokens(token);
|
||||
if (depth > kNEST_LIMIT)
|
||||
@@ -165,6 +171,7 @@ Reader::readValue(unsigned depth)
|
||||
void
|
||||
Reader::skipCommentTokens(Token& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
do
|
||||
{
|
||||
readToken(token);
|
||||
@@ -174,6 +181,7 @@ Reader::skipCommentTokens(Token& token)
|
||||
bool
|
||||
Reader::expectToken(TokenType type, Token& token, char const* message)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
readToken(token);
|
||||
|
||||
if (token.type != type)
|
||||
@@ -185,6 +193,7 @@ Reader::expectToken(TokenType type, Token& token, char const* message)
|
||||
bool
|
||||
Reader::readToken(Token& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
skipSpaces();
|
||||
token.start = current_;
|
||||
Char const c = getNextChar();
|
||||
@@ -274,6 +283,7 @@ Reader::readToken(Token& token)
|
||||
void
|
||||
Reader::skipSpaces()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
while (current_ != end_)
|
||||
{
|
||||
Char const c = *current_;
|
||||
@@ -292,6 +302,7 @@ Reader::skipSpaces()
|
||||
bool
|
||||
Reader::match(Location pattern, int patternLength)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (end_ - current_ < patternLength)
|
||||
return false;
|
||||
|
||||
@@ -310,6 +321,7 @@ Reader::match(Location pattern, int patternLength)
|
||||
bool
|
||||
Reader::readComment()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Char const c = getNextChar();
|
||||
|
||||
if (c == '*')
|
||||
@@ -324,6 +336,7 @@ Reader::readComment()
|
||||
bool
|
||||
Reader::readCStyleComment()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
while (current_ != end_)
|
||||
{
|
||||
Char const c = getNextChar();
|
||||
@@ -338,6 +351,7 @@ Reader::readCStyleComment()
|
||||
bool
|
||||
Reader::readCppStyleComment()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
while (current_ != end_)
|
||||
{
|
||||
Char const c = getNextChar();
|
||||
@@ -352,6 +366,7 @@ Reader::readCppStyleComment()
|
||||
Reader::TokenType
|
||||
Reader::readNumber()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static char const kEXTENDED_TOKENS[] = {'.', 'e', 'E', '+', '-'};
|
||||
|
||||
TokenType type = TokenInteger;
|
||||
@@ -383,6 +398,7 @@ Reader::readNumber()
|
||||
bool
|
||||
Reader::readString()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Char c = 0;
|
||||
|
||||
while (current_ != end_)
|
||||
@@ -405,6 +421,7 @@ Reader::readString()
|
||||
bool
|
||||
Reader::readObject(Token& tokenStart, unsigned depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Token tokenName{};
|
||||
std::string name;
|
||||
currentValue() = Value(ObjectValue);
|
||||
@@ -475,6 +492,7 @@ Reader::readObject(Token& tokenStart, unsigned depth)
|
||||
bool
|
||||
Reader::readArray(Token& tokenStart, unsigned depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
currentValue() = Value(ArrayValue);
|
||||
skipSpaces();
|
||||
|
||||
@@ -525,6 +543,7 @@ Reader::readArray(Token& tokenStart, unsigned depth)
|
||||
bool
|
||||
Reader::decodeNumber(Token& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Location current = token.start;
|
||||
bool const isNegative = *current == '-';
|
||||
|
||||
@@ -604,6 +623,7 @@ Reader::decodeNumber(Token& token)
|
||||
bool
|
||||
Reader::decodeDouble(Token& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
double value = 0;
|
||||
int const bufferSize = 32;
|
||||
int count = 0;
|
||||
@@ -640,6 +660,7 @@ Reader::decodeDouble(Token& token)
|
||||
bool
|
||||
Reader::decodeString(Token& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string decoded;
|
||||
|
||||
if (!decodeString(token, decoded))
|
||||
@@ -652,6 +673,7 @@ Reader::decodeString(Token& token)
|
||||
bool
|
||||
Reader::decodeString(Token& token, std::string& decoded)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
decoded.reserve(token.end - token.start - 2);
|
||||
Location current = token.start + 1; // skip '"'
|
||||
Location end = token.end - 1; // do not include '"'
|
||||
@@ -731,6 +753,7 @@ Reader::decodeString(Token& token, std::string& decoded)
|
||||
bool
|
||||
Reader::decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
|
||||
return false;
|
||||
|
||||
@@ -774,6 +797,7 @@ Reader::decodeUnicodeEscapeSequence(
|
||||
Location end,
|
||||
unsigned int& unicode)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (end - current < 4)
|
||||
{
|
||||
return addError(
|
||||
@@ -815,6 +839,7 @@ Reader::decodeUnicodeEscapeSequence(
|
||||
bool
|
||||
Reader::addError(std::string const& message, Token& token, Location extra)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ErrorInfo info;
|
||||
info.token = token;
|
||||
info.message = message;
|
||||
@@ -826,6 +851,7 @@ Reader::addError(std::string const& message, Token& token, Location extra)
|
||||
bool
|
||||
Reader::recoverFromError(TokenType skipUntilToken)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
int const errorCount = int(errors_.size());
|
||||
Token skip{};
|
||||
|
||||
@@ -845,6 +871,7 @@ Reader::recoverFromError(TokenType skipUntilToken)
|
||||
bool
|
||||
Reader::addErrorAndRecover(std::string const& message, Token& token, TokenType skipUntilToken)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
addError(message, token);
|
||||
return recoverFromError(skipUntilToken);
|
||||
}
|
||||
@@ -852,12 +879,14 @@ Reader::addErrorAndRecover(std::string const& message, Token& token, TokenType s
|
||||
Value&
|
||||
Reader::currentValue()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return *(nodes_.top());
|
||||
}
|
||||
|
||||
Reader::Char
|
||||
Reader::getNextChar()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (current_ == end_)
|
||||
return 0;
|
||||
|
||||
@@ -867,6 +896,7 @@ Reader::getNextChar()
|
||||
void
|
||||
Reader::getLocationLineAndColumn(Location location, int& line, int& column) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Location current = begin_;
|
||||
Location lastLineStart = current;
|
||||
line = 0;
|
||||
@@ -898,6 +928,7 @@ Reader::getLocationLineAndColumn(Location location, int& line, int& column) cons
|
||||
std::string
|
||||
Reader::getLocationLineAndColumn(Location location) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
int line = 0, column = 0;
|
||||
getLocationLineAndColumn(location, line, column);
|
||||
return "Line " + std::to_string(line) + ", Column " + std::to_string(column);
|
||||
@@ -906,6 +937,7 @@ Reader::getLocationLineAndColumn(Location location) const
|
||||
std::string
|
||||
Reader::getFormattedErrorMessages() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string formattedMessage;
|
||||
|
||||
for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
|
||||
@@ -924,6 +956,7 @@ Reader::getFormattedErrorMessages() const
|
||||
std::istream&
|
||||
operator>>(std::istream& sin, Value& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::Reader reader;
|
||||
bool const ok = reader.parse(sin, root);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/json/detail/json_assert.h>
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/json/json_writer.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -27,18 +28,21 @@ public:
|
||||
char*
|
||||
makeMemberName(char const* memberName) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return duplicateStringValue(memberName);
|
||||
}
|
||||
|
||||
void
|
||||
releaseMemberName(char* memberName) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
releaseStringValue(memberName);
|
||||
}
|
||||
|
||||
char*
|
||||
duplicateStringValue(char const* value, unsigned int length = Unknown) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
//@todo investigate this old optimization
|
||||
// if ( !value || value[0] == 0 )
|
||||
// return 0;
|
||||
@@ -56,6 +60,7 @@ public:
|
||||
void
|
||||
releaseStringValue(char* value) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (value != nullptr)
|
||||
free(value);
|
||||
}
|
||||
@@ -64,6 +69,7 @@ public:
|
||||
static ValueAllocator*&
|
||||
valueAllocator()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static ValueAllocator* kVALUE_ALLOCATOR = new DefaultValueAllocator; // NOLINT TODO
|
||||
return kVALUE_ALLOCATOR;
|
||||
}
|
||||
@@ -72,6 +78,7 @@ static struct DummyValueAllocatorInitializer
|
||||
{
|
||||
DummyValueAllocatorInitializer()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
valueAllocator(); // ensure valueAllocator() statics are initialized
|
||||
// before main().
|
||||
}
|
||||
@@ -112,6 +119,7 @@ Value::CZString::CZString(CZString const& other)
|
||||
|
||||
Value::CZString::~CZString()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if ((cstr_ != nullptr) && index_ == Duplicate)
|
||||
valueAllocator()->releaseMemberName(const_cast<char*>(cstr_));
|
||||
}
|
||||
@@ -119,6 +127,7 @@ Value::CZString::~CZString()
|
||||
bool
|
||||
Value::CZString::operator<(CZString const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if ((cstr_ != nullptr) && (other.cstr_ != nullptr))
|
||||
return strcmp(cstr_, other.cstr_) < 0;
|
||||
|
||||
@@ -128,6 +137,7 @@ Value::CZString::operator<(CZString const& other) const
|
||||
bool
|
||||
Value::CZString::operator==(CZString const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if ((cstr_ != nullptr) && (other.cstr_ != nullptr))
|
||||
return strcmp(cstr_, other.cstr_) == 0;
|
||||
|
||||
@@ -137,18 +147,21 @@ Value::CZString::operator==(CZString const& other) const
|
||||
int
|
||||
Value::CZString::index() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return index_;
|
||||
}
|
||||
|
||||
char const*
|
||||
Value::CZString::cStr() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return cstr_;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::CZString::isStaticString() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return index_ == NoDuplication;
|
||||
}
|
||||
|
||||
@@ -166,6 +179,7 @@ Value::CZString::isStaticString() const
|
||||
*/
|
||||
Value::Value(ValueType type) : type_(type)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -202,48 +216,57 @@ Value::Value(ValueType type) : type_(type)
|
||||
|
||||
Value::Value(Int value) : type_(IntValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.intVal = value;
|
||||
}
|
||||
|
||||
Value::Value(UInt value) : type_(UintValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.uintVal = value;
|
||||
}
|
||||
|
||||
Value::Value(double value) : type_(RealValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.realVal = value;
|
||||
}
|
||||
|
||||
Value::Value(char const* value) : type_(StringValue), allocated_(true)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.stringVal = valueAllocator()->duplicateStringValue(value);
|
||||
}
|
||||
|
||||
Value::Value(xrpl::Number const& value) : type_(StringValue), allocated_(true)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const tmp = to_string(value);
|
||||
value_.stringVal = valueAllocator()->duplicateStringValue(tmp.c_str(), tmp.length());
|
||||
}
|
||||
|
||||
Value::Value(std::string const& value) : type_(StringValue), allocated_(true)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.stringVal =
|
||||
valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length());
|
||||
}
|
||||
|
||||
Value::Value(StaticString const& value) : type_(StringValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.stringVal = const_cast<char*>(value.cStr());
|
||||
}
|
||||
|
||||
Value::Value(bool value) : type_(BooleanValue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_.boolVal = value;
|
||||
}
|
||||
|
||||
Value::Value(Value const& other) : type_(other.type_)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -281,6 +304,7 @@ Value::Value(Value const& other) : type_(other.type_)
|
||||
|
||||
Value::~Value()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -312,6 +336,7 @@ Value::~Value()
|
||||
Value&
|
||||
Value::operator=(Value const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value tmp(other);
|
||||
swap(tmp);
|
||||
return *this;
|
||||
@@ -320,6 +345,7 @@ Value::operator=(Value const& other)
|
||||
Value::Value(Value&& other) noexcept
|
||||
: value_(other.value_), type_(other.type_), allocated_(other.allocated_)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
other.type_ = NullValue;
|
||||
other.allocated_ = 0;
|
||||
}
|
||||
@@ -327,6 +353,7 @@ Value::Value(Value&& other) noexcept
|
||||
Value&
|
||||
Value::operator=(Value&& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value tmp(std::move(other));
|
||||
swap(tmp);
|
||||
return *this;
|
||||
@@ -335,6 +362,7 @@ Value::operator=(Value&& other)
|
||||
void
|
||||
Value::swap(Value& other) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::swap(value_, other.value_);
|
||||
|
||||
ValueType const temp = type_;
|
||||
@@ -349,12 +377,14 @@ Value::swap(Value& other) noexcept
|
||||
ValueType
|
||||
Value::type() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_;
|
||||
}
|
||||
|
||||
static int
|
||||
integerCmp(Int i, UInt ui)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// All negative numbers are less than all unsigned numbers.
|
||||
if (i < 0)
|
||||
return -1;
|
||||
@@ -368,6 +398,7 @@ integerCmp(Int i, UInt ui)
|
||||
bool
|
||||
operator<(Value const& x, Value const& y)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto signum = x.type_ - y.type_)
|
||||
{
|
||||
if (x.type_ == IntValue && y.type_ == UintValue)
|
||||
@@ -423,6 +454,7 @@ operator<(Value const& x, Value const& y)
|
||||
bool
|
||||
operator==(Value const& x, Value const& y)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (x.type_ != y.type_)
|
||||
{
|
||||
if (x.type_ == IntValue && y.type_ == UintValue)
|
||||
@@ -471,6 +503,7 @@ operator==(Value const& x, Value const& y)
|
||||
char const*
|
||||
Value::asCString() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(type_ == StringValue, "json::Value::asCString : valid type");
|
||||
return value_.stringVal;
|
||||
}
|
||||
@@ -478,6 +511,7 @@ Value::asCString() const
|
||||
std::string
|
||||
Value::asString() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -514,6 +548,7 @@ Value::asString() const
|
||||
Value::Int
|
||||
Value::asInt() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -557,6 +592,7 @@ Value::asInt() const
|
||||
UInt
|
||||
Value::asAbsUInt() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -616,6 +652,7 @@ Value::asAbsUInt() const
|
||||
Value::UInt
|
||||
Value::asUInt() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -659,6 +696,7 @@ Value::asUInt() const
|
||||
double
|
||||
Value::asDouble() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -693,6 +731,7 @@ Value::asDouble() const
|
||||
bool
|
||||
Value::asBool() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -727,6 +766,7 @@ Value::asBool() const
|
||||
bool
|
||||
Value::isConvertibleTo(ValueType other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -778,6 +818,7 @@ Value::isConvertibleTo(ValueType other) const
|
||||
Value::UInt
|
||||
Value::size() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case NullValue:
|
||||
@@ -813,6 +854,7 @@ Value::size() const
|
||||
Value::
|
||||
operator bool() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isNull())
|
||||
return false;
|
||||
|
||||
@@ -828,6 +870,7 @@ operator bool() const
|
||||
void
|
||||
Value::clear()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ArrayValue || type_ == ObjectValue,
|
||||
"json::Value::clear : valid type");
|
||||
@@ -867,6 +910,7 @@ Value::operator[](UInt index)
|
||||
Value const&
|
||||
Value::operator[](UInt index) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ArrayValue,
|
||||
"json::Value::operator[](UInt) const : valid type");
|
||||
@@ -892,6 +936,7 @@ Value::operator[](char const* key)
|
||||
Value&
|
||||
Value::resolveReference(char const* key, bool isStatic)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ObjectValue, "json::Value::resolveReference : valid type");
|
||||
|
||||
@@ -913,6 +958,7 @@ Value::resolveReference(char const* key, bool isStatic)
|
||||
Value
|
||||
Value::get(UInt index, Value const& defaultValue) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value const* value = &((*this)[index]);
|
||||
return value == &kNULL ? defaultValue : *value;
|
||||
}
|
||||
@@ -920,12 +966,14 @@ Value::get(UInt index, Value const& defaultValue) const
|
||||
bool
|
||||
Value::isValidIndex(UInt index) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return index < size();
|
||||
}
|
||||
|
||||
Value const&
|
||||
Value::operator[](char const* key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ObjectValue,
|
||||
"json::Value::operator[](const char*) const : valid type");
|
||||
@@ -951,6 +999,7 @@ Value::operator[](std::string const& key)
|
||||
Value const&
|
||||
Value::operator[](std::string const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (*this)[key.c_str()];
|
||||
}
|
||||
|
||||
@@ -963,24 +1012,28 @@ Value::operator[](StaticString const& key)
|
||||
Value const&
|
||||
Value::operator[](StaticString const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (*this)[key.cStr()];
|
||||
}
|
||||
|
||||
Value&
|
||||
Value::append(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (*this)[size()] = value;
|
||||
}
|
||||
|
||||
Value&
|
||||
Value::append(Value&& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (*this)[size()] = std::move(value);
|
||||
}
|
||||
|
||||
Value
|
||||
Value::get(char const* key, Value const& defaultValue) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value const* value = &((*this)[key]);
|
||||
return value == &kNULL ? defaultValue : *value;
|
||||
}
|
||||
@@ -988,12 +1041,14 @@ Value::get(char const* key, Value const& defaultValue) const
|
||||
Value
|
||||
Value::get(std::string const& key, Value const& defaultValue) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return get(key.c_str(), defaultValue);
|
||||
}
|
||||
|
||||
Value
|
||||
Value::removeMember(char const* key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ObjectValue, "json::Value::removeMember : valid type");
|
||||
|
||||
@@ -1014,12 +1069,14 @@ Value::removeMember(char const* key)
|
||||
Value
|
||||
Value::removeMember(std::string const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return removeMember(key.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isMember(char const* key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (type_ != ObjectValue)
|
||||
return false;
|
||||
|
||||
@@ -1030,18 +1087,21 @@ Value::isMember(char const* key) const
|
||||
bool
|
||||
Value::isMember(std::string const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isMember(key.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isMember(StaticString const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isMember(key.cStr());
|
||||
}
|
||||
|
||||
Value::Members
|
||||
Value::getMemberNames() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
type_ == NullValue || type_ == ObjectValue, "json::Value::getMemberNames : valid type");
|
||||
|
||||
@@ -1062,78 +1122,91 @@ Value::getMemberNames() const
|
||||
bool
|
||||
Value::isNull() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == NullValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isBool() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == BooleanValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isInt() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == IntValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isUInt() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == UintValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isIntegral() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == IntValue || type_ == UintValue || type_ == BooleanValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isDouble() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == RealValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isNumeric() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isIntegral() || isDouble();
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isString() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == StringValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isArray() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == ArrayValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isArrayOrNull() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == NullValue || type_ == ArrayValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isObject() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == ObjectValue;
|
||||
}
|
||||
|
||||
bool
|
||||
Value::isObjectOrNull() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_ == NullValue || type_ == ObjectValue;
|
||||
}
|
||||
|
||||
std::string
|
||||
Value::toStyledString() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
StyledWriter writer;
|
||||
return writer.write(*this);
|
||||
}
|
||||
@@ -1141,6 +1214,7 @@ Value::toStyledString() const
|
||||
Value::const_iterator
|
||||
Value::begin() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case ArrayValue:
|
||||
@@ -1159,6 +1233,7 @@ Value::begin() const
|
||||
Value::const_iterator
|
||||
Value::end() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case ArrayValue:
|
||||
@@ -1177,6 +1252,7 @@ Value::end() const
|
||||
Value::iterator
|
||||
Value::begin()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case ArrayValue:
|
||||
@@ -1194,6 +1270,7 @@ Value::begin()
|
||||
Value::iterator
|
||||
Value::end()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (type_)
|
||||
{
|
||||
case ArrayValue:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
namespace json {
|
||||
|
||||
@@ -25,24 +26,28 @@ ValueIteratorBase::ValueIteratorBase(Value::ObjectValues::iterator const& curren
|
||||
Value&
|
||||
ValueIteratorBase::deref() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return current_->second;
|
||||
}
|
||||
|
||||
void
|
||||
ValueIteratorBase::increment()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++current_;
|
||||
}
|
||||
|
||||
void
|
||||
ValueIteratorBase::decrement()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
--current_;
|
||||
}
|
||||
|
||||
ValueIteratorBase::difference_type
|
||||
ValueIteratorBase::computeDistance(SelfType const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Iterator for null value are initialized using the default
|
||||
// constructor, which initialize current_ to the default
|
||||
// std::map::iterator. As begin() and end() are two instance
|
||||
@@ -70,6 +75,7 @@ ValueIteratorBase::computeDistance(SelfType const& other) const
|
||||
bool
|
||||
ValueIteratorBase::isEqual(SelfType const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isNull_)
|
||||
{
|
||||
return other.isNull_;
|
||||
@@ -81,12 +87,14 @@ ValueIteratorBase::isEqual(SelfType const& other) const
|
||||
void
|
||||
ValueIteratorBase::copy(SelfType const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
current_ = other.current_;
|
||||
}
|
||||
|
||||
Value
|
||||
ValueIteratorBase::key() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value::CZString const czString = (*current_).first;
|
||||
|
||||
if (czString.cStr() != nullptr)
|
||||
@@ -103,6 +111,7 @@ ValueIteratorBase::key() const
|
||||
UInt
|
||||
ValueIteratorBase::index() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Value::CZString const czString = (*current_).first;
|
||||
|
||||
if (czString.cStr() == nullptr)
|
||||
@@ -114,6 +123,7 @@ ValueIteratorBase::index() const
|
||||
char const*
|
||||
ValueIteratorBase::memberName() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char const* name = (*current_).first.cStr();
|
||||
return (name != nullptr) ? name : "";
|
||||
}
|
||||
@@ -134,6 +144,7 @@ ValueConstIterator::ValueConstIterator(Value::ObjectValues::iterator const& curr
|
||||
ValueConstIterator&
|
||||
ValueConstIterator::operator=(ValueIteratorBase const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
copy(other);
|
||||
return *this;
|
||||
}
|
||||
@@ -160,6 +171,7 @@ ValueIterator::ValueIterator(ValueIterator const& other) = default;
|
||||
ValueIterator&
|
||||
ValueIterator::operator=(SelfType const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -18,12 +19,14 @@ namespace json {
|
||||
static bool
|
||||
isControlCharacter(char ch)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ch > 0 && ch <= 0x1F;
|
||||
}
|
||||
|
||||
static bool
|
||||
containsControlCharacter(char const* str)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
while (*str != 0)
|
||||
{
|
||||
if (isControlCharacter(*(str++)))
|
||||
@@ -35,6 +38,7 @@ containsControlCharacter(char const* str)
|
||||
static void
|
||||
uintToString(unsigned int value, char*& current)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
*--current = 0;
|
||||
|
||||
do
|
||||
@@ -47,6 +51,7 @@ uintToString(unsigned int value, char*& current)
|
||||
std::string
|
||||
valueToString(Int value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char buffer[32];
|
||||
char* current = buffer + sizeof(buffer); // NOLINT(misc-const-correctness)
|
||||
bool const isNegative = value < 0;
|
||||
@@ -66,6 +71,7 @@ valueToString(Int value)
|
||||
std::string
|
||||
valueToString(UInt value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
char buffer[32];
|
||||
char* current = buffer + sizeof(buffer); // NOLINT(misc-const-correctness)
|
||||
uintToString(value, current);
|
||||
@@ -76,6 +82,7 @@ valueToString(UInt value)
|
||||
std::string
|
||||
valueToString(double value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Allocate a buffer that is more than large enough to store the 16 digits
|
||||
// of precision requested below.
|
||||
char buffer[32];
|
||||
@@ -94,12 +101,14 @@ valueToString(double value)
|
||||
std::string
|
||||
valueToString(bool value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
std::string
|
||||
valueToQuotedString(char const* value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Not sure how to handle unicode...
|
||||
if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter(value))
|
||||
return std::string("\"") + value + "\"";
|
||||
@@ -178,6 +187,7 @@ valueToQuotedString(char const* value)
|
||||
std::string
|
||||
FastWriter::write(Value const& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
document_ = "";
|
||||
writeValue(root);
|
||||
return std::move(document_);
|
||||
@@ -186,6 +196,7 @@ FastWriter::write(Value const& root)
|
||||
void
|
||||
FastWriter::writeValue(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (value.type())
|
||||
{
|
||||
case NullValue:
|
||||
@@ -258,6 +269,7 @@ StyledWriter::StyledWriter() = default;
|
||||
std::string
|
||||
StyledWriter::write(Value const& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
document_ = "";
|
||||
addChildValues_ = false;
|
||||
indentString_ = "";
|
||||
@@ -269,6 +281,7 @@ StyledWriter::write(Value const& root)
|
||||
void
|
||||
StyledWriter::writeValue(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (value.type())
|
||||
{
|
||||
case NullValue:
|
||||
@@ -337,6 +350,7 @@ StyledWriter::writeValue(Value const& value)
|
||||
void
|
||||
StyledWriter::writeArrayValue(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
unsigned const size = value.size();
|
||||
|
||||
if (size == 0)
|
||||
@@ -400,6 +414,7 @@ StyledWriter::writeArrayValue(Value const& value)
|
||||
bool
|
||||
StyledWriter::isMultilineArray(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
int const size = value.size();
|
||||
bool isMultiLine = size * 3 >= rightMargin_;
|
||||
childValues_.clear();
|
||||
@@ -433,6 +448,7 @@ StyledWriter::isMultilineArray(Value const& value)
|
||||
void
|
||||
StyledWriter::pushValue(std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (addChildValues_)
|
||||
{
|
||||
childValues_.push_back(value);
|
||||
@@ -446,6 +462,7 @@ StyledWriter::pushValue(std::string const& value)
|
||||
void
|
||||
StyledWriter::writeIndent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!document_.empty())
|
||||
{
|
||||
char const last = document_[document_.length() - 1];
|
||||
@@ -463,6 +480,7 @@ StyledWriter::writeIndent()
|
||||
void
|
||||
StyledWriter::writeWithIndent(std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
writeIndent();
|
||||
document_ += value;
|
||||
}
|
||||
@@ -470,12 +488,14 @@ StyledWriter::writeWithIndent(std::string const& value)
|
||||
void
|
||||
StyledWriter::indent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
indentString_ += std::string(indentSize_, ' ');
|
||||
}
|
||||
|
||||
void
|
||||
StyledWriter::unindent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
int(indentString_.size()) >= indentSize_,
|
||||
"json::StyledWriter::unindent : maximum indent size");
|
||||
@@ -493,6 +513,7 @@ StyledStreamWriter::StyledStreamWriter(std::string indentation)
|
||||
void
|
||||
StyledStreamWriter::write(std::ostream& out, Value const& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
document_ = &out;
|
||||
addChildValues_ = false;
|
||||
indentString_ = "";
|
||||
@@ -504,6 +525,7 @@ StyledStreamWriter::write(std::ostream& out, Value const& root)
|
||||
void
|
||||
StyledStreamWriter::writeValue(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
switch (value.type())
|
||||
{
|
||||
case NullValue:
|
||||
@@ -572,6 +594,7 @@ StyledStreamWriter::writeValue(Value const& value)
|
||||
void
|
||||
StyledStreamWriter::writeArrayValue(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
unsigned const size = value.size();
|
||||
|
||||
if (size == 0)
|
||||
@@ -635,6 +658,7 @@ StyledStreamWriter::writeArrayValue(Value const& value)
|
||||
bool
|
||||
StyledStreamWriter::isMultilineArray(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
int const size = value.size();
|
||||
bool isMultiLine = size * 3 >= rightMargin_;
|
||||
childValues_.clear();
|
||||
@@ -668,6 +692,7 @@ StyledStreamWriter::isMultilineArray(Value const& value)
|
||||
void
|
||||
StyledStreamWriter::pushValue(std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (addChildValues_)
|
||||
{
|
||||
childValues_.push_back(value);
|
||||
@@ -681,6 +706,7 @@ StyledStreamWriter::pushValue(std::string const& value)
|
||||
void
|
||||
StyledStreamWriter::writeIndent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
/*
|
||||
Some comments in this method would have been nice. ;-)
|
||||
|
||||
@@ -699,6 +725,7 @@ StyledStreamWriter::writeIndent()
|
||||
void
|
||||
StyledStreamWriter::writeWithIndent(std::string const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
writeIndent();
|
||||
*document_ << value;
|
||||
}
|
||||
@@ -706,12 +733,14 @@ StyledStreamWriter::writeWithIndent(std::string const& value)
|
||||
void
|
||||
StyledStreamWriter::indent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
indentString_ += indentation_;
|
||||
}
|
||||
|
||||
void
|
||||
StyledStreamWriter::unindent()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
indentString_.size() >= indentation_.size(),
|
||||
"json::StyledStreamWriter::unindent : maximum indent size");
|
||||
@@ -721,6 +750,7 @@ StyledStreamWriter::unindent()
|
||||
std::ostream&
|
||||
operator<<(std::ostream& sout, Value const& root)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::StyledStreamWriter writer;
|
||||
writer.write(sout, root);
|
||||
return sout;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/json/to_string.h>
|
||||
|
||||
#include <xrpl/json/json_writer.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -9,12 +10,14 @@ namespace json {
|
||||
std::string
|
||||
to_string(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return FastWriter().write(value);
|
||||
}
|
||||
|
||||
std::string
|
||||
pretty(Value const& value)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return StyledWriter().write(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -29,6 +30,7 @@ AcceptedLedgerTx::AcceptedLedgerTx(
|
||||
, meta_(txn->getTransactionID(), ledger->seq(), *met)
|
||||
, affected_(meta_.getAffectedAccounts())
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!ledger->open(), "xrpl::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state");
|
||||
|
||||
Serializer s;
|
||||
@@ -73,6 +75,7 @@ AcceptedLedgerTx::AcceptedLedgerTx(
|
||||
std::string
|
||||
AcceptedLedgerTx::getEscMeta() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!rawMeta_.empty(), "xrpl::AcceptedLedgerTx::getEscMeta : metadata is set");
|
||||
return sqlBlobLiteral(rawMeta_);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -37,6 +38,7 @@ namespace xrpl::detail {
|
||||
void
|
||||
ApplyStateTable::apply(RawView& to) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
to.rawDestroyXRP(dropsDestroyed_);
|
||||
for (auto const& item : items_)
|
||||
{
|
||||
@@ -61,6 +63,7 @@ ApplyStateTable::apply(RawView& to) const
|
||||
std::size_t
|
||||
ApplyStateTable::size() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::size_t ret = 0;
|
||||
for (auto& item : items_)
|
||||
{
|
||||
@@ -86,6 +89,7 @@ ApplyStateTable::visit(
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto& item : items_)
|
||||
{
|
||||
switch (item.second.first)
|
||||
@@ -118,6 +122,7 @@ ApplyStateTable::apply(
|
||||
bool isDryRun,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Build metadata and insert
|
||||
auto const sTx = std::make_shared<Serializer>();
|
||||
tx.add(*sTx);
|
||||
@@ -287,6 +292,7 @@ ApplyStateTable::apply(
|
||||
bool
|
||||
ApplyStateTable::exists(ReadView const& base, Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.find(k.key);
|
||||
if (iter == items_.end())
|
||||
return base.exists(k);
|
||||
@@ -310,6 +316,7 @@ ApplyStateTable::succ(
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last) const -> std::optional<key_type>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::optional<key_type> next = key;
|
||||
items_t::const_iterator iter;
|
||||
// Find base successor that is
|
||||
@@ -342,6 +349,7 @@ ApplyStateTable::succ(
|
||||
std::shared_ptr<SLE const>
|
||||
ApplyStateTable::read(ReadView const& base, Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.find(k.key);
|
||||
if (iter == items_.end())
|
||||
return base.read(k);
|
||||
@@ -364,6 +372,7 @@ ApplyStateTable::read(ReadView const& base, Keylet const& k) const
|
||||
std::shared_ptr<SLE>
|
||||
ApplyStateTable::peek(ReadView const& base, Keylet const& k)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto iter = items_.lower_bound(k.key);
|
||||
if (iter == items_.end() || iter->first != k.key)
|
||||
{
|
||||
@@ -398,6 +407,7 @@ ApplyStateTable::peek(ReadView const& base, Keylet const& k)
|
||||
void
|
||||
ApplyStateTable::erase(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.find(sle->key());
|
||||
if (iter == items_.end())
|
||||
Throw<std::logic_error>("ApplyStateTable::erase: missing key");
|
||||
@@ -422,6 +432,7 @@ ApplyStateTable::erase(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyStateTable::rawErase(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std;
|
||||
auto const result = items_.emplace(
|
||||
piecewise_construct, forward_as_tuple(sle->key()), forward_as_tuple(Action::Erase, sle));
|
||||
@@ -447,6 +458,7 @@ ApplyStateTable::rawErase(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyStateTable::insert(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.lower_bound(sle->key());
|
||||
if (iter == items_.end() || iter->first != sle->key())
|
||||
{
|
||||
@@ -477,6 +489,7 @@ ApplyStateTable::insert(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyStateTable::replace(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.lower_bound(sle->key());
|
||||
if (iter == items_.end() || iter->first != sle->key())
|
||||
{
|
||||
@@ -506,6 +519,7 @@ ApplyStateTable::replace(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyStateTable::update(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.find(sle->key());
|
||||
if (iter == items_.end())
|
||||
Throw<std::logic_error>("ApplyStateTable::update: missing key");
|
||||
@@ -529,6 +543,7 @@ ApplyStateTable::update(ReadView const& base, std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyStateTable::destroyXRP(XRPAmount const& fee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
dropsDestroyed_ += fee;
|
||||
}
|
||||
|
||||
@@ -538,6 +553,7 @@ ApplyStateTable::destroyXRP(XRPAmount const& fee)
|
||||
void
|
||||
ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
key_type prevTxID;
|
||||
LedgerIndex prevLgrID = 0;
|
||||
|
||||
@@ -571,6 +587,7 @@ ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr<SLE> const& sle)
|
||||
std::shared_ptr<SLE>
|
||||
ApplyStateTable::getForMod(ReadView const& base, key_type const& key, Mods& mods, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
{
|
||||
auto miter = mods.find(key);
|
||||
if (miter != mods.end())
|
||||
@@ -621,6 +638,7 @@ ApplyStateTable::threadTx(
|
||||
Mods& mods,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sle = getForMod(base, keylet::account(to).key, mods, j);
|
||||
if (!sle)
|
||||
{
|
||||
@@ -644,6 +662,7 @@ ApplyStateTable::threadOwners(
|
||||
Mods& mods,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
LedgerEntryType const ledgerType{sle->getType()};
|
||||
switch (ledgerType)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -33,6 +34,7 @@ createRoot(
|
||||
uint256 const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto newRoot = std::make_shared<SLE>(directory);
|
||||
newRoot->setFieldH256(sfRootIndex, directory.key);
|
||||
describe(newRoot);
|
||||
@@ -48,6 +50,7 @@ createRoot(
|
||||
auto
|
||||
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint64_t const page = start->getFieldU64(sfIndexPrevious);
|
||||
|
||||
auto node = start;
|
||||
@@ -75,6 +78,7 @@ insertKey(
|
||||
STVector256& indexes,
|
||||
uint256 const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (preserveOrder)
|
||||
{
|
||||
if (std::ranges::find(indexes, key) != indexes.end())
|
||||
@@ -112,6 +116,7 @@ insertPage(
|
||||
Keylet const& directory,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// We rely on modulo arithmetic of unsigned integers (guaranteed in
|
||||
// [basic.fundamental] paragraph 2) to detect page representation overflow.
|
||||
// For signed integers this would be UB, hence static_assert here.
|
||||
@@ -168,6 +173,7 @@ ApplyView::dirAdd(
|
||||
uint256 const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto root = peek(directory);
|
||||
|
||||
if (!root)
|
||||
@@ -190,6 +196,7 @@ ApplyView::dirAdd(
|
||||
bool
|
||||
ApplyView::emptyDirDelete(Keylet const& directory)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto node = peek(directory);
|
||||
|
||||
if (!node)
|
||||
@@ -255,6 +262,7 @@ ApplyView::emptyDirDelete(Keylet const& directory)
|
||||
bool
|
||||
ApplyView::dirRemove(Keylet const& directory, std::uint64_t page, uint256 const& key, bool keepRoot)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto node = peek(keylet::page(directory, page));
|
||||
|
||||
if (!node)
|
||||
@@ -395,6 +403,7 @@ ApplyView::dirRemove(Keylet const& directory, std::uint64_t page, uint256 const&
|
||||
bool
|
||||
ApplyView::dirDelete(Keylet const& directory, std::function<void(uint256 const&)> const& callback)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::optional<std::uint64_t> pi;
|
||||
|
||||
do
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -24,30 +25,35 @@ ApplyViewBase::ApplyViewBase(ReadView const* base, ApplyFlags flags) : flags_(fl
|
||||
bool
|
||||
ApplyViewBase::open() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->open();
|
||||
}
|
||||
|
||||
LedgerHeader const&
|
||||
ApplyViewBase::header() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->header();
|
||||
}
|
||||
|
||||
Fees const&
|
||||
ApplyViewBase::fees() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->fees();
|
||||
}
|
||||
|
||||
Rules const&
|
||||
ApplyViewBase::rules() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->rules();
|
||||
}
|
||||
|
||||
bool
|
||||
ApplyViewBase::exists(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.exists(*base_, k);
|
||||
}
|
||||
|
||||
@@ -55,54 +61,63 @@ auto
|
||||
ApplyViewBase::succ(key_type const& key, std::optional<key_type> const& last) const
|
||||
-> std::optional<key_type>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.succ(*base_, key, last);
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
ApplyViewBase::read(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.read(*base_, k);
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::slesBegin() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->slesBegin();
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::slesEnd() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->slesEnd();
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::slesUpperBound(uint256 const& key) const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->slesUpperBound(key);
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::txsBegin() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->txsBegin();
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::txsEnd() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->txsEnd();
|
||||
}
|
||||
|
||||
bool
|
||||
ApplyViewBase::txExists(key_type const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->txExists(key);
|
||||
}
|
||||
|
||||
auto
|
||||
ApplyViewBase::txRead(key_type const& key) const -> tx_type
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->txRead(key);
|
||||
}
|
||||
|
||||
@@ -111,30 +126,35 @@ ApplyViewBase::txRead(key_type const& key) const -> tx_type
|
||||
ApplyFlags
|
||||
ApplyViewBase::flags() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return flags_;
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
ApplyViewBase::peek(Keylet const& k)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.peek(*base_, k);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::erase(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.erase(*base_, sle);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::insert(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.insert(*base_, sle);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::update(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.update(*base_, sle);
|
||||
}
|
||||
|
||||
@@ -143,24 +163,28 @@ ApplyViewBase::update(std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
ApplyViewBase::rawErase(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.rawErase(*base_, sle);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::rawInsert(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.insert(*base_, sle);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::rawReplace(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.replace(*base_, sle);
|
||||
}
|
||||
|
||||
void
|
||||
ApplyViewBase::rawDestroyXRP(XRPAmount const& fee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.destroyXRP(fee);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@@ -31,12 +32,14 @@ ApplyViewImpl::apply(
|
||||
bool isDryRun,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.apply(to, tx, ter, deliver_, parentBatchId, isDryRun, j);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
ApplyViewImpl::size()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.size();
|
||||
}
|
||||
|
||||
@@ -49,6 +52,7 @@ ApplyViewImpl::visit(
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.visit(to, func);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
@@ -17,6 +18,7 @@ BookDirs::BookDirs(ReadView const& view, Book const& book)
|
||||
, next_quality_(getQualityNext(root_))
|
||||
, key_(view_->succ(root_, next_quality_).value_or(beast::kZERO))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(root_ != beast::kZERO, "xrpl::BookDirs::BookDirs : nonzero root");
|
||||
if (key_ != beast::kZERO)
|
||||
{
|
||||
@@ -32,6 +34,7 @@ BookDirs::BookDirs(ReadView const& view, Book const& book)
|
||||
auto
|
||||
BookDirs::begin() const -> BookDirs::const_iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto it = BookDirs::const_iterator(*view_, root_, key_);
|
||||
if (key_ != beast::kZERO)
|
||||
{
|
||||
@@ -46,12 +49,14 @@ BookDirs::begin() const -> BookDirs::const_iterator
|
||||
auto
|
||||
BookDirs::end() const -> BookDirs::const_iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return BookDirs::const_iterator(*view_, root_, key_);
|
||||
}
|
||||
|
||||
bool
|
||||
BookDirs::const_iterator::operator==(BookDirs::const_iterator const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (view_ == nullptr || other.view_ == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -65,6 +70,7 @@ BookDirs::const_iterator::operator==(BookDirs::const_iterator const& other) cons
|
||||
BookDirs::const_iterator::reference
|
||||
BookDirs::const_iterator::operator*() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
index_ != beast::kZERO, "xrpl::BookDirs::const_iterator::operator* : nonzero index");
|
||||
if (!cache_)
|
||||
@@ -75,6 +81,7 @@ BookDirs::const_iterator::operator*() const
|
||||
BookDirs::const_iterator&
|
||||
BookDirs::const_iterator::operator++()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using beast::kZERO;
|
||||
|
||||
XRPL_ASSERT(index_ != kZERO, "xrpl::BookDirs::const_iterator::operator++ : nonzero index");
|
||||
@@ -104,6 +111,7 @@ BookDirs::const_iterator::operator++()
|
||||
BookDirs::const_iterator
|
||||
BookDirs::const_iterator::operator++(int)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
index_ != beast::kZERO, "xrpl::BookDirs::const_iterator::operator++(int) : nonzero index");
|
||||
const_iterator tmp(*this);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/MultiApiJson.h>
|
||||
#include <xrpl/server/InfoSub.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
@@ -13,6 +14,7 @@ namespace xrpl {
|
||||
void
|
||||
BookListeners::addSubscriber(InfoSub::ref sub)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(lock_);
|
||||
listeners_[sub->getSeq()] = sub;
|
||||
}
|
||||
@@ -20,6 +22,7 @@ BookListeners::addSubscriber(InfoSub::ref sub)
|
||||
void
|
||||
BookListeners::removeSubscriber(std::uint64_t seq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(lock_);
|
||||
listeners_.erase(seq);
|
||||
}
|
||||
@@ -27,6 +30,7 @@ BookListeners::removeSubscriber(std::uint64_t seq)
|
||||
void
|
||||
BookListeners::publish(MultiApiJson const& jvObj, hash_set<std::uint64_t>& havePublished)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(lock_);
|
||||
auto it = listeners_.cbegin();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -16,12 +17,14 @@ namespace xrpl::detail {
|
||||
bool
|
||||
CachedViewImpl::exists(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return read(k) != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
CachedViewImpl::read(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static CountedObjects::Counter kHITS{"CachedView::hit"};
|
||||
static CountedObjects::Counter kHITSEXPIRED{"CachedView::hitExpired"};
|
||||
static CountedObjects::Counter kMISSES{"CachedView::miss"};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
@@ -15,6 +16,7 @@ namespace xrpl {
|
||||
bool
|
||||
operator<(CanonicalTXSet::Key const& lhs, CanonicalTXSet::Key const& rhs)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (lhs.account_ < rhs.account_)
|
||||
return true;
|
||||
|
||||
@@ -33,6 +35,7 @@ operator<(CanonicalTXSet::Key const& lhs, CanonicalTXSet::Key const& rhs)
|
||||
uint256
|
||||
CanonicalTXSet::accountKey(AccountID const& account)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
uint256 ret = beast::kZERO;
|
||||
memcpy(ret.begin(), account.begin(), account.size());
|
||||
ret ^= salt_;
|
||||
@@ -42,6 +45,7 @@ CanonicalTXSet::accountKey(AccountID const& account)
|
||||
void
|
||||
CanonicalTXSet::insert(std::shared_ptr<STTx const> const& txn)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
map_.insert(
|
||||
std::make_pair(
|
||||
Key(accountKey(txn->getAccountID(sfAccount)),
|
||||
@@ -53,6 +57,7 @@ CanonicalTXSet::insert(std::shared_ptr<STTx const> const& txn)
|
||||
std::shared_ptr<STTx const>
|
||||
CanonicalTXSet::popAcctTransaction(std::shared_ptr<STTx const> const& tx)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Determining the next viable transaction for an account with Tickets:
|
||||
//
|
||||
// 1. Prioritize transactions with Sequences over transactions with
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
@@ -18,6 +19,7 @@ using const_iterator = Dir::ConstIterator;
|
||||
Dir::Dir(ReadView const& view, Keylet const& key)
|
||||
: view_(&view), root_(key), sle_(view_->read(root_))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (sle_ != nullptr)
|
||||
indexes_ = &sle_->getFieldV256(sfIndexes);
|
||||
}
|
||||
@@ -25,6 +27,7 @@ Dir::Dir(ReadView const& view, Keylet const& key)
|
||||
auto
|
||||
Dir::begin() const -> ConstIterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto it = ConstIterator(*view_, root_, root_);
|
||||
if (sle_ != nullptr)
|
||||
{
|
||||
@@ -43,12 +46,14 @@ Dir::begin() const -> ConstIterator
|
||||
auto
|
||||
Dir::end() const -> ConstIterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ConstIterator(*view_, root_, root_);
|
||||
}
|
||||
|
||||
bool
|
||||
const_iterator::operator==(ConstIterator const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (view_ == nullptr || other.view_ == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -61,6 +66,7 @@ const_iterator::operator==(ConstIterator const& other) const
|
||||
const_iterator::reference
|
||||
const_iterator::operator*() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(index_ != beast::kZERO, "xrpl::const_iterator::operator* : nonzero index");
|
||||
if (!cache_)
|
||||
cache_ = view_->read(keylet::child(index_));
|
||||
@@ -70,6 +76,7 @@ const_iterator::operator*() const
|
||||
const_iterator&
|
||||
const_iterator::operator++()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(index_ != beast::kZERO, "xrpl::const_iterator::operator++ : nonzero index");
|
||||
if (++it_ != std::end(*indexes_))
|
||||
{
|
||||
@@ -84,6 +91,7 @@ const_iterator::operator++()
|
||||
const_iterator
|
||||
const_iterator::operator++(int)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(index_ != beast::kZERO, "xrpl::const_iterator::operator++(int) : nonzero index");
|
||||
ConstIterator tmp(*this);
|
||||
++(*this);
|
||||
@@ -93,6 +101,7 @@ const_iterator::operator++(int)
|
||||
const_iterator&
|
||||
const_iterator::nextPage()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const next = sle_->getFieldU64(sfIndexNext);
|
||||
if (next == 0)
|
||||
{
|
||||
@@ -122,6 +131,7 @@ const_iterator::nextPage()
|
||||
std::size_t
|
||||
const_iterator::pageSize()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return indexes_->size();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <xrpl/shamap/SHAMapItem.h>
|
||||
#include <xrpl/shamap/SHAMapMissingNode.h>
|
||||
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -69,12 +70,14 @@ public:
|
||||
[[nodiscard]] std::unique_ptr<base_type>
|
||||
copy() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
equal(base_type const& impl) const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const p = dynamic_cast<SlesIterImpl const*>(&impl))
|
||||
return iter_ == p->iter_;
|
||||
return false;
|
||||
@@ -83,12 +86,14 @@ public:
|
||||
void
|
||||
increment() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++iter_;
|
||||
}
|
||||
|
||||
[[nodiscard]] SlesType::value_type
|
||||
dereference() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
SerialIter sit(iter_->slice());
|
||||
return std::make_shared<SLE const>(sit, iter_->key());
|
||||
}
|
||||
@@ -116,12 +121,14 @@ public:
|
||||
[[nodiscard]] std::unique_ptr<base_type>
|
||||
copy() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
equal(base_type const& impl) const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const p = dynamic_cast<TxsIterImpl const*>(&impl))
|
||||
return iter_ == p->iter_;
|
||||
return false;
|
||||
@@ -130,12 +137,14 @@ public:
|
||||
void
|
||||
increment() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++iter_;
|
||||
}
|
||||
|
||||
[[nodiscard]] TxsType::value_type
|
||||
dereference() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& item = *iter_;
|
||||
if (metadata_)
|
||||
return Ledger::deserializeTxPlusMeta(item);
|
||||
@@ -158,6 +167,7 @@ Ledger::Ledger(
|
||||
, rules_(std::move(rules))
|
||||
, j_(beast::Journal(beast::Journal::getNullSink()))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
header_.seq = 1;
|
||||
header_.drops = kINITIAL_XRP;
|
||||
header_.closeTimeResolution = kLEDGER_GENESIS_TIME_RESOLUTION;
|
||||
@@ -221,6 +231,7 @@ Ledger::Ledger(
|
||||
, header_(info)
|
||||
, j_(j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
loaded = true;
|
||||
|
||||
if (header_.txHash.isNonZero() && !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr))
|
||||
@@ -259,6 +270,7 @@ Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime)
|
||||
, rules_(prevLedger.rules_)
|
||||
, j_(beast::Journal(beast::Journal::getNullSink()))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
header_.seq = prevLedger.header_.seq + 1;
|
||||
header_.parentCloseTime = prevLedger.header_.closeTime;
|
||||
header_.hash = prevLedger.header().hash + uint256(1);
|
||||
@@ -286,6 +298,7 @@ Ledger::Ledger(LedgerHeader const& info, Rules rules, Family& family)
|
||||
, header_(info)
|
||||
, j_(beast::Journal(beast::Journal::getNullSink()))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
header_.hash = calculateLedgerHash(header_);
|
||||
}
|
||||
|
||||
@@ -302,6 +315,7 @@ Ledger::Ledger(
|
||||
, rules_(std::move(rules))
|
||||
, j_(beast::Journal(beast::Journal::getNullSink()))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
header_.seq = ledgerSeq;
|
||||
header_.closeTime = closeTime;
|
||||
header_.closeTimeResolution = kLEDGER_DEFAULT_TIME_RESOLUTION;
|
||||
@@ -311,6 +325,7 @@ Ledger::Ledger(
|
||||
void
|
||||
Ledger::setImmutable(bool rehash)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Force update, since this is the only
|
||||
// place the hash transitions to valid
|
||||
if (!immutable_ && rehash)
|
||||
@@ -334,6 +349,7 @@ Ledger::setAccepted(
|
||||
NetClock::duration closeResolution,
|
||||
bool correctCloseTime)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Used when we witnessed the consensus.
|
||||
XRPL_ASSERT(!open(), "xrpl::Ledger::setAccepted : valid ledger state");
|
||||
|
||||
@@ -346,6 +362,7 @@ Ledger::setAccepted(
|
||||
bool
|
||||
Ledger::addSLE(SLE const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const s = sle.getSerializer();
|
||||
return stateMap_.addItem(SHAMapNodeType::TnAccountState, makeShamapitem(sle.key(), s.slice()));
|
||||
}
|
||||
@@ -355,6 +372,7 @@ Ledger::addSLE(SLE const& sle)
|
||||
std::shared_ptr<STTx const>
|
||||
Ledger::deserializeTx(SHAMapItem const& item)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
SerialIter sit(item.slice());
|
||||
return std::make_shared<STTx const>(sit);
|
||||
}
|
||||
@@ -362,6 +380,7 @@ Ledger::deserializeTx(SHAMapItem const& item)
|
||||
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
|
||||
Ledger::deserializeTxPlusMeta(SHAMapItem const& item)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>> result;
|
||||
SerialIter sit(item.slice());
|
||||
{
|
||||
@@ -380,6 +399,7 @@ Ledger::deserializeTxPlusMeta(SHAMapItem const& item)
|
||||
bool
|
||||
Ledger::exists(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// VFALCO NOTE Perhaps check the type for debug builds?
|
||||
return stateMap_.hasItem(k.key);
|
||||
}
|
||||
@@ -387,12 +407,14 @@ Ledger::exists(Keylet const& k) const
|
||||
bool
|
||||
Ledger::exists(uint256 const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return stateMap_.hasItem(key);
|
||||
}
|
||||
|
||||
std::optional<uint256>
|
||||
Ledger::succ(uint256 const& key, std::optional<uint256> const& last) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto item = stateMap_.upperBound(key);
|
||||
if (item == stateMap_.end())
|
||||
return std::nullopt;
|
||||
@@ -404,6 +426,7 @@ Ledger::succ(uint256 const& key, std::optional<uint256> const& last) const
|
||||
std::shared_ptr<SLE const>
|
||||
Ledger::read(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (k.key == beast::kZERO)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
@@ -425,42 +448,49 @@ Ledger::read(Keylet const& k) const
|
||||
auto
|
||||
Ledger::slesBegin() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(stateMap_.begin());
|
||||
}
|
||||
|
||||
auto
|
||||
Ledger::slesEnd() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(stateMap_.end());
|
||||
}
|
||||
|
||||
auto
|
||||
Ledger::slesUpperBound(uint256 const& key) const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(stateMap_.upperBound(key));
|
||||
}
|
||||
|
||||
auto
|
||||
Ledger::txsBegin() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(!open(), txMap_.begin());
|
||||
}
|
||||
|
||||
auto
|
||||
Ledger::txsEnd() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(!open(), txMap_.end());
|
||||
}
|
||||
|
||||
bool
|
||||
Ledger::txExists(uint256 const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return txMap_.hasItem(key);
|
||||
}
|
||||
|
||||
auto
|
||||
Ledger::txRead(key_type const& key) const -> tx_type
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& item = txMap_.peekItem(key);
|
||||
if (!item)
|
||||
return {};
|
||||
@@ -475,6 +505,7 @@ Ledger::txRead(key_type const& key) const -> tx_type
|
||||
auto
|
||||
Ledger::digest(key_type const& key) const -> std::optional<digest_type>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
SHAMapHash digest;
|
||||
// VFALCO Unfortunately this loads the item
|
||||
// from the NodeStore needlessly.
|
||||
@@ -488,6 +519,7 @@ Ledger::digest(key_type const& key) const -> std::optional<digest_type>
|
||||
void
|
||||
Ledger::rawErase(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!stateMap_.delItem(sle->key()))
|
||||
logicError("Ledger::rawErase: key not found");
|
||||
}
|
||||
@@ -495,6 +527,7 @@ Ledger::rawErase(std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
Ledger::rawErase(uint256 const& key)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!stateMap_.delItem(key))
|
||||
logicError("Ledger::rawErase: key not found");
|
||||
}
|
||||
@@ -502,6 +535,7 @@ Ledger::rawErase(uint256 const& key)
|
||||
void
|
||||
Ledger::rawInsert(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Serializer ss;
|
||||
sle->add(ss);
|
||||
if (!stateMap_.addGiveItem(
|
||||
@@ -514,6 +548,7 @@ Ledger::rawInsert(std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
Ledger::rawReplace(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Serializer ss;
|
||||
sle->add(ss);
|
||||
if (!stateMap_.updateGiveItem(
|
||||
@@ -529,6 +564,7 @@ Ledger::rawTxInsert(
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsert : non-null metadata input");
|
||||
|
||||
// low-level - just add to table
|
||||
@@ -542,6 +578,7 @@ Ledger::rawTxInsert(
|
||||
bool
|
||||
Ledger::setup()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool ret = true;
|
||||
|
||||
try
|
||||
@@ -626,6 +663,7 @@ Ledger::setup()
|
||||
std::shared_ptr<SLE>
|
||||
Ledger::peek(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& value = stateMap_.peekItem(k.key);
|
||||
if (!value)
|
||||
return nullptr;
|
||||
@@ -638,6 +676,7 @@ Ledger::peek(Keylet const& k) const
|
||||
hash_set<PublicKey>
|
||||
Ledger::negativeUNL() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
hash_set<PublicKey> negUnl;
|
||||
if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfDisabledValidators))
|
||||
{
|
||||
@@ -663,6 +702,7 @@ Ledger::negativeUNL() const
|
||||
std::optional<PublicKey>
|
||||
Ledger::validatorToDisable() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToDisable))
|
||||
{
|
||||
auto d = sle->getFieldVL(sfValidatorToDisable);
|
||||
@@ -677,6 +717,7 @@ Ledger::validatorToDisable() const
|
||||
std::optional<PublicKey>
|
||||
Ledger::validatorToReEnable() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToReEnable))
|
||||
{
|
||||
auto d = sle->getFieldVL(sfValidatorToReEnable);
|
||||
@@ -691,6 +732,7 @@ Ledger::validatorToReEnable() const
|
||||
void
|
||||
Ledger::updateNegativeUNL()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto sle = peek(keylet::negativeUNL());
|
||||
if (!sle)
|
||||
return;
|
||||
@@ -740,6 +782,7 @@ Ledger::updateNegativeUNL()
|
||||
bool
|
||||
Ledger::walkLedger(beast::Journal j, bool parallel) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<SHAMapMissingNode> missingNodes1;
|
||||
std::vector<SHAMapMissingNode> missingNodes2;
|
||||
|
||||
@@ -791,6 +834,7 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const
|
||||
bool
|
||||
Ledger::isSensible() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (header_.hash.isZero())
|
||||
return false;
|
||||
if (header_.accountHash.isZero())
|
||||
@@ -807,6 +851,7 @@ Ledger::isSensible() const
|
||||
void
|
||||
Ledger::updateSkipList()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (header_.seq == 0) // genesis ledger has no previous ledger
|
||||
return;
|
||||
|
||||
@@ -880,17 +925,20 @@ Ledger::updateSkipList()
|
||||
bool
|
||||
Ledger::isFlagLedger() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ::xrpl::isFlagLedger(header_.seq);
|
||||
}
|
||||
bool
|
||||
Ledger::isVotingLedger() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ::xrpl::isVotingLedger(header_.seq + 1);
|
||||
}
|
||||
|
||||
void
|
||||
Ledger::unshare() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stateMap_.unshare();
|
||||
txMap_.unshare();
|
||||
}
|
||||
@@ -898,6 +946,7 @@ Ledger::unshare() const
|
||||
void
|
||||
Ledger::invariants() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
stateMap_.invariants();
|
||||
txMap_.invariants();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||
|
||||
@@ -39,12 +40,14 @@ public:
|
||||
[[nodiscard]] std::unique_ptr<base_type>
|
||||
copy() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(metadata_, iter_);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
equal(base_type const& impl) const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const p = dynamic_cast<TxsIterImpl const*>(&impl))
|
||||
return iter_ == p->iter_;
|
||||
return false;
|
||||
@@ -53,14 +56,17 @@ public:
|
||||
void
|
||||
increment() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++iter_;
|
||||
}
|
||||
|
||||
[[nodiscard]] value_type
|
||||
dereference() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_type result;
|
||||
{
|
||||
TRACE_FUNC();
|
||||
SerialIter sit(iter_->second.txn->slice());
|
||||
result.first = std::make_shared<STTx const>(sit);
|
||||
}
|
||||
@@ -97,6 +103,7 @@ OpenView::OpenView(OpenLedgerT, ReadView const* base, Rules rules, std::shared_p
|
||||
, base_(base)
|
||||
, hold_(std::move(hold))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
header_.validated = false;
|
||||
header_.accepted = false;
|
||||
header_.seq = base_->header().seq + 1;
|
||||
@@ -119,12 +126,14 @@ OpenView::OpenView(ReadView const* base, std::shared_ptr<void const> hold)
|
||||
std::size_t
|
||||
OpenView::txCount() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return baseTxCount_ + txs_.size();
|
||||
}
|
||||
|
||||
void
|
||||
OpenView::apply(TxsRawView& to) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.apply(to);
|
||||
for (auto const& item : txs_)
|
||||
to.rawTxInsert(item.first, item.second.txn, item.second.meta);
|
||||
@@ -135,24 +144,28 @@ OpenView::apply(TxsRawView& to) const
|
||||
LedgerHeader const&
|
||||
OpenView::header() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return header_;
|
||||
}
|
||||
|
||||
Fees const&
|
||||
OpenView::fees() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return base_->fees();
|
||||
}
|
||||
|
||||
Rules const&
|
||||
OpenView::rules() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return rules_;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenView::exists(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.exists(*base_, k);
|
||||
}
|
||||
|
||||
@@ -160,54 +173,63 @@ auto
|
||||
OpenView::succ(key_type const& key, std::optional<key_type> const& last) const
|
||||
-> std::optional<key_type>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.succ(*base_, key, last);
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
OpenView::read(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.read(*base_, k);
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::slesBegin() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.slesBegin(*base_);
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::slesEnd() const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.slesEnd(*base_);
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::slesUpperBound(uint256 const& key) const -> std::unique_ptr<SlesType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.slesUpperBound(*base_, key);
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::txsBegin() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(!open(), txs_.cbegin());
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::txsEnd() const -> std::unique_ptr<TxsType::iter_base>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<TxsIterImpl>(!open(), txs_.cend());
|
||||
}
|
||||
|
||||
bool
|
||||
OpenView::txExists(key_type const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return txs_.contains(key);
|
||||
}
|
||||
|
||||
auto
|
||||
OpenView::txRead(key_type const& key) const -> tx_type
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = txs_.find(key);
|
||||
if (iter == txs_.end())
|
||||
return base_->txRead(key);
|
||||
@@ -230,24 +252,28 @@ OpenView::txRead(key_type const& key) const -> tx_type
|
||||
void
|
||||
OpenView::rawErase(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.erase(sle);
|
||||
}
|
||||
|
||||
void
|
||||
OpenView::rawInsert(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.insert(sle);
|
||||
}
|
||||
|
||||
void
|
||||
OpenView::rawReplace(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.replace(sle);
|
||||
}
|
||||
|
||||
void
|
||||
OpenView::rawDestroyXRP(XRPAmount const& fee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
items_.destroyXRP(fee);
|
||||
// VFALCO Deduct from header_.totalDrops ?
|
||||
// What about child views?
|
||||
@@ -261,6 +287,7 @@ OpenView::rawTxInsert(
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const result = txs_.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(txn, metaData));
|
||||
if (!result.second)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -25,6 +26,7 @@ namespace detail {
|
||||
auto
|
||||
DeferredCredits::makeKeyIOU(AccountID const& a1, AccountID const& a2, Currency const& c) -> KeyIOU
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (a1 < a2)
|
||||
{
|
||||
return std::make_tuple(a1, a2, c);
|
||||
@@ -40,6 +42,7 @@ DeferredCredits::creditIOU(
|
||||
STAmount const& amount,
|
||||
STAmount const& preCreditSenderBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
sender != receiver, "xrpl::detail::DeferredCredits::creditIOU : sender is not receiver");
|
||||
XRPL_ASSERT(!amount.negative(), "xrpl::detail::DeferredCredits::creditIOU : positive amount");
|
||||
@@ -90,6 +93,7 @@ DeferredCredits::creditMPT(
|
||||
std::uint64_t preCreditBalanceHolder,
|
||||
std::int64_t preCreditBalanceIssuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
amount.holds<MPTIssue>(),
|
||||
"xrpl::detail::DeferredCredits::creditMPT : amount is for MPTIssue");
|
||||
@@ -153,6 +157,7 @@ DeferredCredits::issuerSelfDebitMPT(
|
||||
std::uint64_t amount,
|
||||
std::int64_t origBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& mptID = issue.getMptID();
|
||||
auto i = creditsMPT_.find(mptID);
|
||||
|
||||
@@ -172,6 +177,7 @@ DeferredCredits::issuerSelfDebitMPT(
|
||||
void
|
||||
DeferredCredits::ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const v = std::max(cur, next);
|
||||
auto r = ownerCounts_.emplace(id, v);
|
||||
if (!r.second)
|
||||
@@ -184,6 +190,7 @@ DeferredCredits::ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_
|
||||
std::optional<std::uint32_t>
|
||||
DeferredCredits::ownerCount(AccountID const& id) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto i = ownerCounts_.find(id);
|
||||
if (i != ownerCounts_.end())
|
||||
return i->second;
|
||||
@@ -197,6 +204,7 @@ DeferredCredits::adjustmentsIOU(
|
||||
AccountID const& other,
|
||||
Currency const& currency) const -> std::optional<AdjustmentIOU>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::optional<AdjustmentIOU> result;
|
||||
|
||||
KeyIOU const k = makeKeyIOU(main, other, currency);
|
||||
@@ -219,6 +227,7 @@ DeferredCredits::adjustmentsIOU(
|
||||
auto
|
||||
DeferredCredits::adjustmentsMPT(xrpl::MPTID const& mptID) const -> std::optional<AdjustmentMPT>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto i = creditsMPT_.find(mptID);
|
||||
if (i == creditsMPT_.end())
|
||||
return std::nullopt;
|
||||
@@ -228,6 +237,7 @@ DeferredCredits::adjustmentsMPT(xrpl::MPTID const& mptID) const -> std::optional
|
||||
void
|
||||
DeferredCredits::apply(DeferredCredits& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& i : creditsIOU_)
|
||||
{
|
||||
auto r = to.creditsIOU_.emplace(i);
|
||||
@@ -285,6 +295,7 @@ PaymentSandbox::balanceHookIOU(
|
||||
AccountID const& issuer,
|
||||
STAmount const& amount) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(amount.holds<Issue>(), "balanceHookIOU: amount is for Issue");
|
||||
|
||||
/*
|
||||
@@ -337,6 +348,7 @@ STAmount
|
||||
PaymentSandbox::balanceHookMPT(AccountID const& account, MPTIssue const& issue, std::int64_t amount)
|
||||
const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& issuer = issue.getIssuer();
|
||||
bool const accountIsHolder = account != issuer;
|
||||
|
||||
@@ -374,6 +386,7 @@ PaymentSandbox::balanceHookMPT(AccountID const& account, MPTIssue const& issue,
|
||||
STAmount
|
||||
PaymentSandbox::balanceHookSelfIssueMPT(xrpl::MPTIssue const& issue, std::int64_t amount) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::int64_t selfDebited = 0;
|
||||
std::int64_t lastBal = amount;
|
||||
for (auto curSB = this; curSB != nullptr; curSB = curSB->ps_)
|
||||
@@ -394,6 +407,7 @@ PaymentSandbox::balanceHookSelfIssueMPT(xrpl::MPTIssue const& issue, std::int64_
|
||||
std::uint32_t
|
||||
PaymentSandbox::ownerCountHook(AccountID const& account, std::uint32_t count) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint32_t result = count;
|
||||
for (auto curSB = this; curSB != nullptr; curSB = curSB->ps_)
|
||||
{
|
||||
@@ -410,6 +424,7 @@ PaymentSandbox::creditHookIOU(
|
||||
STAmount const& amount,
|
||||
STAmount const& preCreditBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(amount.holds<Issue>(), "creditHookIOU: amount is for Issue");
|
||||
|
||||
tab_.creditIOU(from, to, amount, preCreditBalance);
|
||||
@@ -423,6 +438,7 @@ PaymentSandbox::creditHookMPT(
|
||||
std::uint64_t preCreditBalanceHolder,
|
||||
std::int64_t preCreditBalanceIssuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(amount.holds<MPTIssue>(), "creditHookMPT: amount is for MPTIssue");
|
||||
|
||||
tab_.creditMPT(from, to, amount, preCreditBalanceHolder, preCreditBalanceIssuer);
|
||||
@@ -434,6 +450,7 @@ PaymentSandbox::issuerSelfDebitHookMPT(
|
||||
std::uint64_t amount,
|
||||
std::int64_t origBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(amount > 0, "PaymentSandbox::issuerSelfDebitHookMPT: amount must be > 0");
|
||||
|
||||
tab_.issuerSelfDebitMPT(issue, amount, origBalance);
|
||||
@@ -445,12 +462,14 @@ PaymentSandbox::adjustOwnerCountHook(
|
||||
std::uint32_t cur,
|
||||
std::uint32_t next)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
tab_.ownerCount(account, cur, next);
|
||||
}
|
||||
|
||||
void
|
||||
PaymentSandbox::apply(RawView& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!ps_, "xrpl::PaymentSandbox::apply : non-null sandbox");
|
||||
items_.apply(to);
|
||||
}
|
||||
@@ -458,6 +477,7 @@ PaymentSandbox::apply(RawView& to)
|
||||
void
|
||||
PaymentSandbox::apply(PaymentSandbox& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(ps_ == &to, "xrpl::PaymentSandbox::apply : matching sandbox");
|
||||
items_.apply(to);
|
||||
tab_.apply(to.tab_);
|
||||
@@ -466,6 +486,7 @@ PaymentSandbox::apply(PaymentSandbox& to)
|
||||
XRPAmount
|
||||
PaymentSandbox::xrpDestroyed() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return items_.dropsDestroyed();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -37,6 +38,7 @@ public:
|
||||
ReadView::SlesType::Iterator end0)
|
||||
: iter0_(std::move(iter0)), end0_(std::move(end0)), iter1_(iter1), end1_(end1)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (iter0_ != end0_)
|
||||
sle0_ = *iter0_;
|
||||
if (iter1_ != end1)
|
||||
@@ -49,12 +51,14 @@ public:
|
||||
std::unique_ptr<base_type>
|
||||
copy() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(*this);
|
||||
}
|
||||
|
||||
bool
|
||||
equal(base_type const& impl) const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const p = dynamic_cast<SlesIterImpl const*>(&impl))
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
@@ -70,6 +74,7 @@ public:
|
||||
void
|
||||
increment() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
sle1_ || sle0_,
|
||||
"xrpl::detail::RawStateTable::increment : either SLE is "
|
||||
@@ -106,6 +111,7 @@ public:
|
||||
value_type
|
||||
dereference() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!sle1_)
|
||||
{
|
||||
return sle0_;
|
||||
@@ -123,6 +129,7 @@ private:
|
||||
void
|
||||
inc0()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++iter0_;
|
||||
if (iter0_ == end0_)
|
||||
{
|
||||
@@ -137,6 +144,7 @@ private:
|
||||
void
|
||||
inc1()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
++iter1_;
|
||||
if (iter1_ == end1_)
|
||||
{
|
||||
@@ -151,6 +159,7 @@ private:
|
||||
void
|
||||
skip()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
while (iter1_ != end1_ && iter1_->second.action == Action::Erase &&
|
||||
sle0_->key() == sle1_->key())
|
||||
{
|
||||
@@ -169,6 +178,7 @@ private:
|
||||
void
|
||||
RawStateTable::apply(RawView& to) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
to.rawDestroyXRP(dropsDestroyed_);
|
||||
for (auto const& elem : items_)
|
||||
{
|
||||
@@ -191,6 +201,7 @@ RawStateTable::apply(RawView& to) const
|
||||
bool
|
||||
RawStateTable::exists(ReadView const& base, Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key");
|
||||
auto const iter = items_.find(k.key);
|
||||
if (iter == items_.end())
|
||||
@@ -211,6 +222,7 @@ auto
|
||||
RawStateTable::succ(ReadView const& base, key_type const& key, std::optional<key_type> const& last)
|
||||
const -> std::optional<key_type>
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::optional<key_type> next = key;
|
||||
items_t::const_iterator iter;
|
||||
// Find base successor that is
|
||||
@@ -243,6 +255,7 @@ RawStateTable::succ(ReadView const& base, key_type const& key, std::optional<key
|
||||
void
|
||||
RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// The base invariant is checked during apply
|
||||
auto const result = items_.emplace(
|
||||
std::piecewise_construct,
|
||||
@@ -269,6 +282,7 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
RawStateTable::insert(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const result = items_.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(sle->key()),
|
||||
@@ -294,6 +308,7 @@ RawStateTable::insert(std::shared_ptr<SLE> const& sle)
|
||||
void
|
||||
RawStateTable::replace(std::shared_ptr<SLE> const& sle)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const result = items_.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(sle->key()),
|
||||
@@ -316,6 +331,7 @@ RawStateTable::replace(std::shared_ptr<SLE> const& sle)
|
||||
std::shared_ptr<SLE const>
|
||||
RawStateTable::read(ReadView const& base, Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const iter = items_.find(k.key);
|
||||
if (iter == items_.end())
|
||||
return base.read(k);
|
||||
@@ -332,12 +348,14 @@ RawStateTable::read(ReadView const& base, Keylet const& k) const
|
||||
void
|
||||
RawStateTable::destroyXRP(XRPAmount const& fee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
dropsDestroyed_ += fee;
|
||||
}
|
||||
|
||||
std::unique_ptr<ReadView::SlesType::iter_base>
|
||||
RawStateTable::slesBegin(ReadView const& base) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(
|
||||
items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
|
||||
}
|
||||
@@ -345,6 +363,7 @@ RawStateTable::slesBegin(ReadView const& base) const
|
||||
std::unique_ptr<ReadView::SlesType::iter_base>
|
||||
RawStateTable::slesEnd(ReadView const& base) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(
|
||||
items_.end(), items_.end(), base.sles.end(), base.sles.end());
|
||||
}
|
||||
@@ -352,6 +371,7 @@ RawStateTable::slesEnd(ReadView const& base) const
|
||||
std::unique_ptr<ReadView::SlesType::iter_base>
|
||||
RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<SlesIterImpl>(
|
||||
items_.upper_bound(key), items_.end(), base.sles.upperBound(key), base.sles.end());
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
@@ -20,18 +21,21 @@ ReadView::SlesType::SlesType(ReadView const& view) : ReadViewFwdRange(view)
|
||||
auto
|
||||
ReadView::SlesType::begin() const -> Iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Iterator(view_, view_->slesBegin());
|
||||
}
|
||||
|
||||
auto
|
||||
ReadView::SlesType::end() const -> Iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Iterator(view_, view_->slesEnd());
|
||||
}
|
||||
|
||||
auto
|
||||
ReadView::SlesType::upperBound(key_type const& key) const -> Iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Iterator(view_, view_->slesUpperBound(key));
|
||||
}
|
||||
|
||||
@@ -42,24 +46,28 @@ ReadView::TxsType::TxsType(ReadView const& view) : ReadViewFwdRange(view)
|
||||
bool
|
||||
ReadView::TxsType::empty() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return begin() == end();
|
||||
}
|
||||
|
||||
auto
|
||||
ReadView::TxsType::begin() const -> Iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Iterator(view_, view_->txsBegin());
|
||||
}
|
||||
|
||||
auto
|
||||
ReadView::TxsType::end() const -> Iterator
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Iterator(view_, view_->txsEnd());
|
||||
}
|
||||
|
||||
Rules
|
||||
makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return makeRulesGivenLedger(ledger, current.presets());
|
||||
}
|
||||
|
||||
@@ -68,6 +76,7 @@ makeRulesGivenLedger(
|
||||
DigestAwareReadView const& ledger,
|
||||
std::unordered_set<uint256, beast::Uhash<>> const& presets)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Keylet const k = keylet::amendments();
|
||||
std::optional const digest = ledger.digest(k.key);
|
||||
if (digest)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -46,6 +47,7 @@ namespace xrpl {
|
||||
bool
|
||||
hasExpired(ReadView const& view, std::optional<std::uint32_t> const& exp)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using d = NetClock::duration;
|
||||
using tp = NetClock::time_point;
|
||||
|
||||
@@ -59,6 +61,7 @@ isVaultPseudoAccountFrozen(
|
||||
MPTIssue const& mptShare,
|
||||
int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!view.rules().enabled(featureSingleAssetVault))
|
||||
return false;
|
||||
|
||||
@@ -100,6 +103,7 @@ isLPTokenFrozen(
|
||||
Asset const& asset,
|
||||
Asset const& asset2)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isFrozen(view, account, asset) || isFrozen(view, account, asset2);
|
||||
}
|
||||
|
||||
@@ -110,6 +114,7 @@ areCompatible(
|
||||
beast::Journal::Stream& s,
|
||||
char const* reason)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool ret = true;
|
||||
|
||||
if (validLedger.header().seq < testLedger.header().seq)
|
||||
@@ -169,6 +174,7 @@ areCompatible(
|
||||
beast::Journal::Stream& s,
|
||||
char const* reason)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool ret = true;
|
||||
|
||||
if (testLedger.header().seq > validIndex)
|
||||
@@ -204,6 +210,7 @@ areCompatible(
|
||||
std::set<uint256>
|
||||
getEnabledAmendments(ReadView const& view)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::set<uint256> amendments;
|
||||
|
||||
if (auto const sle = view.read(keylet::amendments()))
|
||||
@@ -221,6 +228,7 @@ getEnabledAmendments(ReadView const& view)
|
||||
majorityAmendments_t
|
||||
getMajorityAmendments(ReadView const& view)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
majorityAmendments_t ret;
|
||||
|
||||
if (auto const sle = view.read(keylet::amendments()))
|
||||
@@ -243,6 +251,7 @@ getMajorityAmendments(ReadView const& view)
|
||||
std::optional<uint256>
|
||||
hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Easy cases...
|
||||
if (seq > ledger.seq())
|
||||
{
|
||||
@@ -311,6 +320,7 @@ dirLink(
|
||||
std::shared_ptr<SLE>& object,
|
||||
SF_UINT64 const& node)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const page =
|
||||
view.dirInsert(keylet::ownerDir(owner), object->key(), describeOwnerDir(owner));
|
||||
if (!page)
|
||||
@@ -342,6 +352,7 @@ withdrawToDestExceedsLimit(
|
||||
AccountID const& to,
|
||||
STAmount const& amount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& issuer = amount.getIssuer();
|
||||
if (from == to || to == issuer || isXRP(issuer))
|
||||
return tesSUCCESS;
|
||||
@@ -370,6 +381,7 @@ canWithdraw(
|
||||
STAmount const& amount,
|
||||
bool hasDestinationTag)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
|
||||
return ret;
|
||||
|
||||
@@ -393,6 +405,7 @@ canWithdraw(
|
||||
STAmount const& amount,
|
||||
bool hasDestinationTag)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const toSle = view.read(keylet::account(to));
|
||||
|
||||
return canWithdraw(view, from, to, toSle, amount, hasDestinationTag);
|
||||
@@ -401,6 +414,7 @@ canWithdraw(
|
||||
[[nodiscard]] TER
|
||||
canWithdraw(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const from = tx[sfAccount];
|
||||
auto const to = tx[~sfDestination].value_or(from);
|
||||
|
||||
@@ -418,6 +432,7 @@ doWithdraw(
|
||||
STAmount const& amount,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Create trust line or MPToken for the receiving account
|
||||
if (dstAcct == senderAcct)
|
||||
{
|
||||
@@ -460,6 +475,7 @@ cleanupOnAccountDelete(
|
||||
beast::Journal j,
|
||||
std::optional<uint16_t> maxNodesToDelete)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Delete all the entries in the account directory.
|
||||
std::shared_ptr<SLE> sleDirNode{};
|
||||
unsigned int uDirEntry{0};
|
||||
@@ -531,6 +547,7 @@ cleanupOnAccountDelete(
|
||||
bool
|
||||
after(NetClock::time_point now, std::uint32_t mark)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return now.time_since_epoch().count() > mark;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -45,6 +46,7 @@ namespace xrpl {
|
||||
STAmount
|
||||
ammLPTokens(STAmount const& asset1, STAmount const& asset2, Asset const& lptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// AMM invariant: sqrt(asset1 * asset2) >= LPTokensBalance
|
||||
auto const rounding =
|
||||
isFeatureEnabled(fixAMMv1_3) ? Number::RoundingMode::Downward : Number::getround();
|
||||
@@ -66,6 +68,7 @@ lpTokensOut(
|
||||
STAmount const& lptAMMBalance,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const f1 = feeMult(tfee);
|
||||
auto const f2 = feeMultHalf(tfee) / f1;
|
||||
Number const r = asset1Deposit / asset1Balance;
|
||||
@@ -99,6 +102,7 @@ ammAssetIn(
|
||||
STAmount const& lpTokens,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const f1 = feeMult(tfee);
|
||||
auto const f2 = feeMultHalf(tfee) / f1;
|
||||
auto const t1 = lpTokens / lptAMMBalance;
|
||||
@@ -128,6 +132,7 @@ lpTokensIn(
|
||||
STAmount const& lptAMMBalance,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Number const fr = asset1Withdraw / asset1Balance;
|
||||
auto const f1 = getFee(tfee);
|
||||
auto const c = fr * f1 + 2 - f1;
|
||||
@@ -159,6 +164,7 @@ ammAssetOut(
|
||||
STAmount const& lpTokens,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const f = getFee(tfee);
|
||||
Number const t1 = lpTokens / lptAMMBalance;
|
||||
if (!isFeatureEnabled(fixAMMv1_3))
|
||||
@@ -175,12 +181,14 @@ ammAssetOut(
|
||||
Number
|
||||
square(Number const& n)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return n * n;
|
||||
}
|
||||
|
||||
STAmount
|
||||
adjustLPTokens(STAmount const& lptAMMBalance, STAmount const& lpTokens, IsDeposit isDeposit)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Force rounding downward to ensure adjusted tokens are less or equal
|
||||
// to requested tokens.
|
||||
SaveNumberRoundMode const rm(Number::setround(Number::RoundingMode::Downward));
|
||||
@@ -199,6 +207,7 @@ adjustAmountsByLPTokens(
|
||||
std::uint16_t tfee,
|
||||
IsDeposit isDeposit)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// AMMv1_3 amendment adjusts tokens and amounts in deposit/withdraw
|
||||
if (isFeatureEnabled(fixAMMv1_3))
|
||||
return std::make_tuple(amount, amount2, lpTokens);
|
||||
@@ -269,6 +278,7 @@ adjustAmountsByLPTokens(
|
||||
Number
|
||||
solveQuadraticEq(Number const& a, Number const& b, Number const& c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (-b + root2(b * b - 4 * a * c)) / (2 * a);
|
||||
}
|
||||
|
||||
@@ -276,6 +286,7 @@ solveQuadraticEq(Number const& a, Number const& b, Number const& c)
|
||||
std::optional<Number>
|
||||
solveQuadraticEqSmallest(Number const& a, Number const& b, Number const& c)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const d = b * b - 4 * a * c;
|
||||
if (d < 0)
|
||||
return std::nullopt;
|
||||
@@ -292,6 +303,7 @@ solveQuadraticEqSmallest(Number const& a, Number const& b, Number const& c)
|
||||
STAmount
|
||||
multiply(STAmount const& amount, Number const& frac, Number::RoundingMode rm)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
NumberRoundModeGuard const g(rm);
|
||||
auto const t = amount * frac;
|
||||
return toSTAmount(amount.asset(), t, rm);
|
||||
@@ -305,6 +317,7 @@ getRoundedAsset(
|
||||
std::function<Number()> const& productCb,
|
||||
IsDeposit isDeposit)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return toSTAmount(balance.asset(), noRoundCb());
|
||||
|
||||
@@ -322,6 +335,7 @@ getRoundedLPTokens(
|
||||
Number const& frac,
|
||||
IsDeposit isDeposit)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return toSTAmount(balance.asset(), balance * frac);
|
||||
|
||||
@@ -338,6 +352,7 @@ getRoundedLPTokens(
|
||||
std::function<Number()> const& productCb,
|
||||
IsDeposit isDeposit)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return toSTAmount(lptAMMBalance.asset(), noRoundCb());
|
||||
|
||||
@@ -362,6 +377,7 @@ adjustAssetInByTokens(
|
||||
STAmount const& tokens,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return {tokens, amount};
|
||||
auto assetAdj = ammAssetIn(balance, lptAMMBalance, tokens, tfee);
|
||||
@@ -388,6 +404,7 @@ adjustAssetOutByTokens(
|
||||
STAmount const& tokens,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return {tokens, amount};
|
||||
auto assetAdj = ammAssetOut(balance, lptAMMBalance, tokens, tfee);
|
||||
@@ -412,6 +429,7 @@ adjustFracByTokens(
|
||||
STAmount const& tokens,
|
||||
Number const& frac)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
return frac;
|
||||
return tokens / lptAMMBalance;
|
||||
@@ -427,6 +445,7 @@ ammPoolHolds(
|
||||
AuthHandling authHandling,
|
||||
beast::Journal const j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const assetInBalance =
|
||||
accountHolds(view, ammAccountID, asset1, freezeHandling, authHandling, j);
|
||||
auto const assetOutBalance =
|
||||
@@ -444,6 +463,7 @@ ammHolds(
|
||||
AuthHandling authHandling,
|
||||
beast::Journal const j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const assets = [&]() -> std::optional<std::pair<Asset, Asset>> {
|
||||
auto const asset1 = ammSle[sfAsset];
|
||||
auto const asset2 = ammSle[sfAsset2];
|
||||
@@ -511,6 +531,7 @@ ammLPHolds(
|
||||
AccountID const& lpAccount,
|
||||
beast::Journal const j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This function looks similar to `accountHolds`. However, it only checks if
|
||||
// a LPToken holder has enough balance. On the other hand, `accountHolds`
|
||||
// checks if the underlying assets of LPToken are frozen with the
|
||||
@@ -559,12 +580,14 @@ ammLPHolds(
|
||||
AccountID const& lpAccount,
|
||||
beast::Journal const j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ammLPHolds(view, ammSle[sfAsset], ammSle[sfAsset2], ammSle[sfAccount], lpAccount, j);
|
||||
}
|
||||
|
||||
std::uint16_t
|
||||
getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono;
|
||||
XRPL_ASSERT(
|
||||
!view.rules().enabled(fixInnerObjTemplate) || ammSle.isFieldPresent(sfAuctionSlot),
|
||||
@@ -595,6 +618,7 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account)
|
||||
STAmount
|
||||
ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Get the actual AMM balance without factoring in the balance hook
|
||||
return asset.visit(
|
||||
[&](MPTIssue const& issue) {
|
||||
@@ -631,6 +655,7 @@ deleteAMMTrustLines(
|
||||
std::uint16_t maxTrustlinesToDelete,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return cleanupOnAccountDelete(
|
||||
sb,
|
||||
keylet::ownerDir(ammAccountID),
|
||||
@@ -667,6 +692,7 @@ deleteAMMTrustLines(
|
||||
static TER
|
||||
deleteAMMMPTokens(Sandbox& sb, AccountID const& ammAccountID, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return cleanupOnAccountDelete(
|
||||
sb,
|
||||
keylet::ownerDir(ammAccountID),
|
||||
@@ -712,6 +738,7 @@ deleteAMMMPTokens(Sandbox& sb, AccountID const& ammAccountID, beast::Journal j)
|
||||
TER
|
||||
deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto ammSle = sb.peek(keylet::amm(asset, asset2));
|
||||
if (!ammSle)
|
||||
{
|
||||
@@ -773,6 +800,7 @@ initializeFeeAuctionVote(
|
||||
Asset const& lptAsset,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& rules = view.rules();
|
||||
// AMM creator gets the voting slot.
|
||||
STArray voteSlots;
|
||||
@@ -822,6 +850,7 @@ initializeFeeAuctionVote(
|
||||
Expected<bool, TER>
|
||||
isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Liquidity Provider (LP) must have one LPToken trustline
|
||||
std::uint8_t nLPTokenTrustLines = 0;
|
||||
// AMM account has at most two IOU (pool tokens, not LPToken) trustlines.
|
||||
@@ -926,6 +955,7 @@ verifyAndAdjustLPTokenBalance(
|
||||
std::shared_ptr<SLE>& ammSle,
|
||||
AccountID const& account)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const res = isOnlyLiquidityProvider(sb, lpTokens.get<Issue>(), account);
|
||||
if (!res.has_value())
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -34,6 +35,7 @@ namespace xrpl {
|
||||
bool
|
||||
isGlobalFrozen(ReadView const& view, AccountID const& issuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(issuer))
|
||||
return false;
|
||||
if (auto const sle = view.read(keylet::account(issuer)))
|
||||
@@ -54,6 +56,7 @@ confineOwnerCount(
|
||||
std::optional<AccountID> const& id = std::nullopt,
|
||||
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint32_t adjusted{current + adjustment};
|
||||
if (adjustment > 0)
|
||||
{
|
||||
@@ -86,6 +89,7 @@ confineOwnerCount(
|
||||
XRPAmount
|
||||
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sle = view.read(keylet::account(id));
|
||||
if (sle == nullptr)
|
||||
return beast::kZERO;
|
||||
@@ -116,6 +120,7 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
|
||||
Rate
|
||||
transferRate(ReadView const& view, AccountID const& issuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sle = view.read(keylet::account(issuer));
|
||||
|
||||
if (sle && sle->isFieldPresent(sfTransferRate))
|
||||
@@ -131,6 +136,7 @@ adjustOwnerCount(
|
||||
std::int32_t amount,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!sle)
|
||||
return;
|
||||
XRPL_ASSERT(amount, "xrpl::adjustOwnerCount : nonzero amount input");
|
||||
@@ -145,6 +151,7 @@ adjustOwnerCount(
|
||||
AccountID
|
||||
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This number must not be changed without an amendment
|
||||
constexpr std::uint16_t kMAX_ACCOUNT_ATTEMPTS = 256;
|
||||
for (std::uint16_t i = 0; i < kMAX_ACCOUNT_ATTEMPTS; ++i)
|
||||
@@ -168,6 +175,7 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
|
||||
[[nodiscard]] std::vector<SField const*> const&
|
||||
getPseudoAccountFields()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static std::vector<SField const*> const kPSEUDO_FIELDS = []() {
|
||||
auto const ar = LedgerFormats::getInstance().findByType(ltACCOUNT_ROOT);
|
||||
if (!ar)
|
||||
@@ -196,6 +204,7 @@ isPseudoAccount(
|
||||
std::shared_ptr<SLE const> sleAcct,
|
||||
std::set<SField const*> const& pseudoFieldFilter)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& fields = getPseudoAccountFields();
|
||||
|
||||
// Intentionally use defensive coding here because it's cheap and makes the
|
||||
@@ -211,6 +220,7 @@ isPseudoAccount(
|
||||
Expected<std::shared_ptr<SLE>, TER>
|
||||
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
[[maybe_unused]]
|
||||
auto const& fields = getPseudoAccountFields();
|
||||
XRPL_ASSERT(
|
||||
@@ -253,6 +263,7 @@ createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const
|
||||
[[nodiscard]] TER
|
||||
checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (toSle == nullptr)
|
||||
return tecNO_DST;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
@@ -35,6 +36,7 @@ namespace credentials {
|
||||
bool
|
||||
checkExpired(std::shared_ptr<SLE const> const& sleCredential, NetClock::time_point const& closed)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint32_t const exp =
|
||||
(*sleCredential)[~sfExpiration].value_or(std::numeric_limits<std::uint32_t>::max());
|
||||
std::uint32_t const now = closed.time_since_epoch().count();
|
||||
@@ -44,6 +46,7 @@ checkExpired(std::shared_ptr<SLE const> const& sleCredential, NetClock::time_poi
|
||||
bool
|
||||
removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const closeTime = view.header().parentCloseTime;
|
||||
bool foundExpired = false;
|
||||
|
||||
@@ -68,6 +71,7 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j)
|
||||
TER
|
||||
deleteSLE(ApplyView& view, std::shared_ptr<SLE> const& sleCredential, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!sleCredential)
|
||||
return tecNO_ENTRY;
|
||||
|
||||
@@ -122,6 +126,7 @@ deleteSLE(ApplyView& view, std::shared_ptr<SLE> const& sleCredential, beast::Jou
|
||||
NotTEC
|
||||
checkFields(STTx const& tx, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!tx.isFieldPresent(sfCredentialIDs))
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -150,6 +155,7 @@ checkFields(STTx const& tx, beast::Journal j)
|
||||
TER
|
||||
valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!tx.isFieldPresent(sfCredentialIDs))
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -184,6 +190,7 @@ valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal
|
||||
TER
|
||||
validDomain(ReadView const& view, uint256 domainID, AccountID const& subject)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Note, permissioned domain objects can be deleted at any time
|
||||
auto const slePD = view.read(keylet::permissionedDomain(domainID));
|
||||
if (!slePD)
|
||||
@@ -225,6 +232,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject)
|
||||
TER
|
||||
authorizedDepositPreauth(ReadView const& view, STVector256 const& credIDs, AccountID const& dst)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::set<std::pair<AccountID, Slice>> sorted;
|
||||
std::vector<std::shared_ptr<SLE const>> lifeExtender;
|
||||
lifeExtender.reserve(credIDs.size());
|
||||
@@ -249,6 +257,7 @@ authorizedDepositPreauth(ReadView const& view, STVector256 const& credIDs, Accou
|
||||
std::set<std::pair<AccountID, Slice>>
|
||||
makeSorted(STArray const& credentials)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::set<std::pair<AccountID, Slice>> out;
|
||||
for (auto const& cred : credentials)
|
||||
{
|
||||
@@ -262,6 +271,7 @@ makeSorted(STArray const& credentials)
|
||||
NotTEC
|
||||
checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (credentials.empty() || (credentials.size() > maxSize))
|
||||
{
|
||||
JLOG(j.trace()) << "Malformed transaction: "
|
||||
@@ -308,6 +318,7 @@ checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j)
|
||||
TER
|
||||
verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const slePD = view.read(keylet::permissionedDomain(domainID));
|
||||
if (!slePD)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
@@ -347,6 +358,7 @@ verifyDepositPreauth(
|
||||
std::shared_ptr<SLE const> const& sleDst,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// If depositPreauth is enabled, then an account that requires
|
||||
// authorization has at least two ways to get a payment in:
|
||||
// 1. If src == dst, or
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -25,6 +26,7 @@ dirFirst(
|
||||
unsigned int& index,
|
||||
uint256& entry)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return detail::internalDirFirst(view, root, page, index, entry);
|
||||
}
|
||||
|
||||
@@ -36,6 +38,7 @@ dirNext(
|
||||
unsigned int& index,
|
||||
uint256& entry)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return detail::internalDirNext(view, root, page, index, entry);
|
||||
}
|
||||
|
||||
@@ -47,6 +50,7 @@ cdirFirst(
|
||||
unsigned int& index,
|
||||
uint256& entry)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return detail::internalDirFirst(view, root, page, index, entry);
|
||||
}
|
||||
|
||||
@@ -58,6 +62,7 @@ cdirNext(
|
||||
unsigned int& index,
|
||||
uint256& entry)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return detail::internalDirNext(view, root, page, index, entry);
|
||||
}
|
||||
|
||||
@@ -67,6 +72,7 @@ forEachItem(
|
||||
Keylet const& root,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::forEachItem : valid root type");
|
||||
|
||||
if (root.type != ltDIR_NODE)
|
||||
@@ -97,6 +103,7 @@ forEachItemAfter(
|
||||
unsigned int limit,
|
||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::forEachItemAfter : valid root type");
|
||||
|
||||
if (root.type != ltDIR_NODE)
|
||||
@@ -170,6 +177,7 @@ forEachItemAfter(
|
||||
bool
|
||||
dirIsEmpty(ReadView const& view, Keylet const& k)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sleNode = view.read(k);
|
||||
if (!sleNode)
|
||||
return true;
|
||||
@@ -184,6 +192,7 @@ dirIsEmpty(ReadView const& view, Keylet const& k)
|
||||
std::function<void(SLE::ref)>
|
||||
describeOwnerDir(AccountID const& account)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return [account](std::shared_ptr<SLE> const& sle) { (*sle)[sfOwner] = account; };
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/Units.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -31,6 +32,7 @@ namespace xrpl {
|
||||
bool
|
||||
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!rules.enabled(featureSingleAssetVault))
|
||||
return false;
|
||||
|
||||
@@ -46,6 +48,7 @@ checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
|
||||
LoanPaymentParts&
|
||||
LoanPaymentParts::operator+=(LoanPaymentParts const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
|
||||
other.principalPaid >= beast::kZERO,
|
||||
@@ -70,6 +73,7 @@ LoanPaymentParts::operator+=(LoanPaymentParts const& other)
|
||||
bool
|
||||
LoanPaymentParts::operator==(LoanPaymentParts const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return principalPaid == other.principalPaid && interestPaid == other.interestPaid &&
|
||||
valueChange == other.valueChange && feePaid == other.feePaid;
|
||||
}
|
||||
@@ -82,6 +86,7 @@ LoanPaymentParts::operator==(LoanPaymentParts const& other) const
|
||||
Number
|
||||
loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Need floating point math, since we're dividing by a large number
|
||||
return tenthBipsOfValue(Number(paymentInterval), interestRate) / kSECONDS_IN_YEAR;
|
||||
}
|
||||
@@ -93,6 +98,7 @@ loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval)
|
||||
bool
|
||||
isRounded(Asset const& asset, Number const& value, std::int32_t scale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return roundToAsset(asset, value, scale, Number::RoundingMode::Downward) ==
|
||||
roundToAsset(asset, value, scale, Number::RoundingMode::Upward);
|
||||
}
|
||||
@@ -102,6 +108,7 @@ namespace detail {
|
||||
void
|
||||
LoanStateDeltas::nonNegative()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (principal < beast::kZERO)
|
||||
principal = kNUM_ZERO;
|
||||
if (interest < beast::kZERO)
|
||||
@@ -117,6 +124,7 @@ LoanStateDeltas::nonNegative()
|
||||
Number
|
||||
computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return power(1 + periodicRate, paymentsRemaining);
|
||||
}
|
||||
|
||||
@@ -128,6 +136,7 @@ computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining)
|
||||
Number
|
||||
computePaymentFactor(Number const& periodicRate, std::uint32_t paymentsRemaining)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (paymentsRemaining == 0)
|
||||
return kNUM_ZERO;
|
||||
|
||||
@@ -151,6 +160,7 @@ loanPeriodicPayment(
|
||||
Number const& periodicRate,
|
||||
std::uint32_t paymentsRemaining)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (principalOutstanding == 0 || paymentsRemaining == 0)
|
||||
return 0;
|
||||
|
||||
@@ -172,6 +182,7 @@ loanPrincipalFromPeriodicPayment(
|
||||
Number const& periodicRate,
|
||||
std::uint32_t paymentsRemaining)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (paymentsRemaining == 0)
|
||||
return kNUM_ZERO;
|
||||
|
||||
@@ -193,6 +204,7 @@ computeInterestAndFeeParts(
|
||||
TenthBips16 managementFeeRate,
|
||||
std::int32_t loanScale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const fee = computeManagementFee(asset, interest, managementFeeRate, loanScale);
|
||||
|
||||
return std::make_pair(interest - fee, fee);
|
||||
@@ -210,6 +222,7 @@ loanLatePaymentInterest(
|
||||
NetClock::time_point parentCloseTime,
|
||||
std::uint32_t nextPaymentDueDate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (principalOutstanding == beast::kZERO)
|
||||
return kNUM_ZERO;
|
||||
|
||||
@@ -245,6 +258,7 @@ loanAccruedInterest(
|
||||
std::uint32_t prevPaymentDate,
|
||||
std::uint32_t paymentInterval)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (periodicRate == beast::kZERO)
|
||||
return kNUM_ZERO;
|
||||
|
||||
@@ -289,6 +303,7 @@ doPayment(
|
||||
UInt32OptionalProxy& nextDueDateProxy,
|
||||
std::uint32_t paymentInterval)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT_PARTS(nextDueDateProxy, "xrpl::detail::doPayment", "Next due date proxy set");
|
||||
|
||||
if (payment.specialCase == PaymentSpecialCase::Final)
|
||||
@@ -412,6 +427,7 @@ tryOverpayment(
|
||||
TenthBips16 const managementFeeRate,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Calculate what the loan state SHOULD be theoretically (at full precision)
|
||||
auto const theoreticalState = computeTheoreticalLoanState(
|
||||
periodicPayment, periodicRate, paymentRemaining, managementFeeRate);
|
||||
@@ -594,6 +610,7 @@ doOverpayment(
|
||||
TenthBips16 const managementFeeRate,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const loanState = constructLoanState(
|
||||
totalValueOutstandingProxy, principalOutstandingProxy, managementFeeOutstandingProxy);
|
||||
auto const periodicPayment = periodicPaymentProxy;
|
||||
@@ -712,6 +729,7 @@ computeLatePayment(
|
||||
TenthBips16 managementFeeRate,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Check if the due date has passed. If not, reject the payment as
|
||||
// being too soon
|
||||
if (!hasExpired(view, nextDueDate))
|
||||
@@ -812,6 +830,7 @@ computeFullPayment(
|
||||
TenthBips16 managementFeeRate,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Full payment must be made before the final scheduled payment.
|
||||
if (paymentRemaining <= 1)
|
||||
{
|
||||
@@ -906,6 +925,7 @@ computeFullPayment(
|
||||
Number
|
||||
PaymentComponents::trackedInterestPart() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return trackedValueDelta - (trackedPrincipalDelta + trackedManagementFeeDelta);
|
||||
}
|
||||
|
||||
@@ -939,6 +959,7 @@ computePaymentComponents(
|
||||
std::uint32_t paymentRemaining,
|
||||
TenthBips16 managementFeeRate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT_PARTS(
|
||||
isRounded(asset, totalValueOutstanding, scale) &&
|
||||
isRounded(asset, principalOutstanding, scale) &&
|
||||
@@ -1149,6 +1170,7 @@ computeOverpaymentComponents(
|
||||
TenthBips32 const overpaymentFeeRate,
|
||||
TenthBips16 const managementFeeRate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
overpayment > 0 && isRounded(asset, overpayment, loanScale),
|
||||
"xrpl::detail::computeOverpaymentComponents : valid overpayment "
|
||||
@@ -1200,6 +1222,7 @@ computeOverpaymentComponents(
|
||||
detail::LoanStateDeltas
|
||||
operator-(LoanState const& lhs, LoanState const& rhs)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
detail::LoanStateDeltas result{
|
||||
.principal = lhs.principalOutstanding - rhs.principalOutstanding,
|
||||
.interest = lhs.interestDue - rhs.interestDue,
|
||||
@@ -1212,6 +1235,7 @@ operator-(LoanState const& lhs, LoanState const& rhs)
|
||||
LoanState
|
||||
operator-(LoanState const& lhs, detail::LoanStateDeltas const& rhs)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
LoanState result{
|
||||
.valueOutstanding = lhs.valueOutstanding - rhs.total(),
|
||||
.principalOutstanding = lhs.principalOutstanding - rhs.principal,
|
||||
@@ -1225,6 +1249,7 @@ operator-(LoanState const& lhs, detail::LoanStateDeltas const& rhs)
|
||||
LoanState
|
||||
operator+(LoanState const& lhs, detail::LoanStateDeltas const& rhs)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
LoanState result{
|
||||
.valueOutstanding = lhs.valueOutstanding + rhs.total(),
|
||||
.principalOutstanding = lhs.principalOutstanding + rhs.principal,
|
||||
@@ -1244,6 +1269,7 @@ checkLoanGuards(
|
||||
LoanProperties const& properties,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const totalInterestOutstanding =
|
||||
properties.loanState.valueOutstanding - principalRequested;
|
||||
// Guard 1: if there is no computed total interest over the life of the
|
||||
@@ -1329,6 +1355,7 @@ computeFullPaymentInterest(
|
||||
std::uint32_t startDate,
|
||||
TenthBips32 closeInterestRate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const accruedInterest = detail::loanAccruedInterest(
|
||||
theoreticalPrincipalOutstanding,
|
||||
periodicRate,
|
||||
@@ -1384,6 +1411,7 @@ computeTheoreticalLoanState(
|
||||
std::uint32_t const paymentRemaining,
|
||||
TenthBips32 const managementFeeRate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (paymentRemaining == 0)
|
||||
{
|
||||
return LoanState{
|
||||
@@ -1443,6 +1471,7 @@ constructLoanState(
|
||||
Number const& principalOutstanding,
|
||||
Number const& managementFeeOutstanding)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This implementation is pretty trivial, but ensures the calculations
|
||||
// are consistent everywhere, and reduces copy/paste errors.
|
||||
return LoanState{
|
||||
@@ -1455,6 +1484,7 @@ constructLoanState(
|
||||
LoanState
|
||||
constructRoundedLoanState(SLE::const_ref loan)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return constructLoanState(
|
||||
loan->at(sfTotalValueOutstanding),
|
||||
loan->at(sfPrincipalOutstanding),
|
||||
@@ -1474,6 +1504,7 @@ computeManagementFee(
|
||||
TenthBips32 managementFeeRate,
|
||||
std::int32_t scale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return roundToAsset(
|
||||
asset, tenthBipsOfValue(value, managementFeeRate), scale, Number::RoundingMode::Downward);
|
||||
}
|
||||
@@ -1496,6 +1527,7 @@ computeLoanProperties(
|
||||
TenthBips32 managementFeeRate,
|
||||
std::int32_t minimumScale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const periodicRate = loanPeriodicRate(interestRate, paymentInterval);
|
||||
XRPL_ASSERT(interestRate == 0 || periodicRate > 0, "xrpl::computeLoanProperties : valid rate");
|
||||
return computeLoanProperties(
|
||||
@@ -1524,6 +1556,7 @@ computeLoanProperties(
|
||||
TenthBips32 managementFeeRate,
|
||||
std::int32_t minimumScale)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const periodicPayment =
|
||||
detail::loanPeriodicPayment(principalOutstanding, periodicRate, paymentsRemaining);
|
||||
|
||||
@@ -1608,6 +1641,7 @@ loanMakePayment(
|
||||
LoanPaymentType const paymentType,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace Lending;
|
||||
|
||||
auto principalOutstandingProxy = loan->at(sfPrincipalOutstanding);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
@@ -41,6 +42,7 @@ namespace xrpl {
|
||||
bool
|
||||
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const sle = view.read(keylet::mptIssuance(mptIssue.getMptID())))
|
||||
return sle->isFlag(lsfMPTLocked);
|
||||
return false;
|
||||
@@ -49,6 +51,7 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
|
||||
bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const sle = view.read(keylet::mptoken(mptIssue.getMptID(), account)))
|
||||
return sle->isFlag(lsfMPTLocked);
|
||||
return false;
|
||||
@@ -57,6 +60,7 @@ isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue cons
|
||||
bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isGlobalFrozen(view, mptIssue) || isIndividualFrozen(view, account, mptIssue) ||
|
||||
isVaultPseudoAccountFrozen(view, account, mptIssue, depth);
|
||||
}
|
||||
@@ -68,6 +72,7 @@ isAnyFrozen(
|
||||
MPTIssue const& mptIssue,
|
||||
int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isGlobalFrozen(view, mptIssue))
|
||||
return true;
|
||||
|
||||
@@ -89,6 +94,7 @@ isAnyFrozen(
|
||||
Rate
|
||||
transferRate(ReadView const& view, MPTID const& issuanceID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// fee is 0-50,000 (0-50%), rate is 1,000,000,000-2,000,000,000
|
||||
// For example, if transfer fee is 50% then 10,000 * 50,000 = 500,000
|
||||
// which represents 50% of 1,000,000,000
|
||||
@@ -106,6 +112,7 @@ transferRate(ReadView const& view, MPTID const& issuanceID)
|
||||
[[nodiscard]] TER
|
||||
canAddHolding(ReadView const& view, MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto mptID = mptIssue.getMptID();
|
||||
auto issuance = view.read(keylet::mptIssuance(mptID));
|
||||
if (!issuance)
|
||||
@@ -128,6 +135,7 @@ addEmptyHolding(
|
||||
MPTIssue const& mptIssue,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& mptID = mptIssue.getMptID();
|
||||
auto const mpt = view.peek(keylet::mptIssuance(mptID));
|
||||
if (!mpt)
|
||||
@@ -152,6 +160,7 @@ authorizeMPToken(
|
||||
std::uint32_t flags,
|
||||
std::optional<AccountID> holderID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sleAcct = view.peek(keylet::account(account));
|
||||
if (!sleAcct)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
@@ -271,6 +280,7 @@ removeEmptyHolding(
|
||||
MPTIssue const& mptIssue,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// If the account is the issuer, then no token should exist. MPTs do not
|
||||
// have the legacy ability to create such a situation, but check anyway. If
|
||||
// a token does exist, it will get deleted. If not, return success.
|
||||
@@ -305,6 +315,7 @@ requireAuth(
|
||||
AuthType authType,
|
||||
int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
|
||||
auto const sleIssuance = view.read(mptID);
|
||||
if (!sleIssuance)
|
||||
@@ -397,6 +408,7 @@ enforceMPTokenAuthorization(
|
||||
XRPAmount const& priorBalance, // for MPToken authorization
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sleIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
|
||||
if (!sleIssuance)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
@@ -496,6 +508,7 @@ canTransfer(
|
||||
AccountID const& from,
|
||||
AccountID const& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
|
||||
auto const sleIssuance = view.read(mptID);
|
||||
if (!sleIssuance)
|
||||
@@ -512,6 +525,7 @@ canTransfer(
|
||||
TER
|
||||
canTrade(ReadView const& view, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return asset.visit(
|
||||
[&](Issue const&) -> TER { return tesSUCCESS; },
|
||||
[&](MPTIssue const& mptIssue) -> TER {
|
||||
@@ -527,6 +541,7 @@ canTrade(ReadView const& view, Asset const& asset)
|
||||
TER
|
||||
lockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const mptIssue = amount.get<MPTIssue>();
|
||||
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
|
||||
auto sleIssuance = view.peek(mptID);
|
||||
@@ -626,6 +641,7 @@ unlockEscrowMPT(
|
||||
STAmount const& grossAmount,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!view.rules().enabled(fixTokenEscrowV1))
|
||||
{
|
||||
XRPL_ASSERT(netAmount == grossAmount, "xrpl::unlockEscrowMPT : netAmount == grossAmount");
|
||||
@@ -788,6 +804,7 @@ createMPToken(
|
||||
AccountID const& account,
|
||||
std::uint32_t const flags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
||||
|
||||
auto const ownerNode =
|
||||
@@ -814,6 +831,7 @@ checkCreateMPT(
|
||||
xrpl::AccountID const& holder,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (mptIssue.getIssuer() == holder)
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -839,12 +857,14 @@ checkCreateMPT(
|
||||
std::int64_t
|
||||
maxMPTAmount(SLE const& sleIssuance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return sleIssuance[~sfMaximumAmount].value_or(kMAX_MP_TOKEN_AMOUNT);
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
availableMPTAmount(SLE const& sleIssuance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const max = maxMPTAmount(sleIssuance);
|
||||
auto const outstanding = sleIssuance[sfOutstandingAmount];
|
||||
return max - outstanding;
|
||||
@@ -853,6 +873,7 @@ availableMPTAmount(SLE const& sleIssuance)
|
||||
std::int64_t
|
||||
availableMPTAmount(ReadView const& view, MPTID const& mptID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sle = view.read(keylet::mptIssuance(mptID));
|
||||
if (!sle)
|
||||
Throw<std::runtime_error>(transHuman(tecINTERNAL));
|
||||
@@ -866,6 +887,7 @@ isMPTOverflow(
|
||||
std::int64_t maximumAmount,
|
||||
AllowMPTOverflow allowOverflow)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint64_t const limit = (allowOverflow == AllowMPTOverflow::Yes)
|
||||
? std::numeric_limits<std::uint64_t>::max()
|
||||
: maximumAmount;
|
||||
@@ -875,6 +897,7 @@ isMPTOverflow(
|
||||
STAmount
|
||||
issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount amount{issue};
|
||||
|
||||
auto const sle = view.read(keylet::mptIssuance(issue));
|
||||
@@ -887,6 +910,7 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue)
|
||||
void
|
||||
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const available = availableMPTAmount(view, issue);
|
||||
view.issuerSelfDebitHookMPT(issue, amount, available);
|
||||
}
|
||||
@@ -894,6 +918,7 @@ issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amo
|
||||
static TER
|
||||
checkMPTAllowed(ReadView const& view, TxType txType, Asset const& asset, AccountID const& accountID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!asset.holds<MPTIssue>())
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -947,6 +972,7 @@ checkMPTTxAllowed(
|
||||
Asset const& asset,
|
||||
AccountID const& accountID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// use isDEXAllowed for payment/offer crossing
|
||||
XRPL_ASSERT(txType != ttPAYMENT, "xrpl::checkMPTTxAllowed : not payment");
|
||||
return checkMPTAllowed(view, txType, asset, accountID);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/protocol/nft.h>
|
||||
#include <xrpl/protocol/nftPageMask.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -44,6 +45,7 @@ namespace xrpl::nft {
|
||||
static std::shared_ptr<SLE const>
|
||||
locatePage(ReadView const& view, AccountID const& owner, uint256 const& id)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const first = keylet::nftpage(keylet::nftpageMin(owner), id);
|
||||
auto const last = keylet::nftpageMax(owner);
|
||||
|
||||
@@ -57,6 +59,7 @@ locatePage(ReadView const& view, AccountID const& owner, uint256 const& id)
|
||||
static std::shared_ptr<SLE>
|
||||
locatePage(ApplyView& view, AccountID const& owner, uint256 const& id)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const first = keylet::nftpage(keylet::nftpageMin(owner), id);
|
||||
auto const last = keylet::nftpageMax(owner);
|
||||
|
||||
@@ -74,6 +77,7 @@ getPageForToken(
|
||||
uint256 const& id,
|
||||
std::function<void(ApplyView&, AccountID const&)> const& createCallback)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const base = keylet::nftpageMin(owner);
|
||||
auto const first = keylet::nftpage(base, id);
|
||||
auto const last = keylet::nftpageMax(owner);
|
||||
@@ -212,6 +216,7 @@ getPageForToken(
|
||||
bool
|
||||
compareTokens(uint256 const& a, uint256 const& b)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// The sort of NFTokens needs to be fully deterministic, but the sort
|
||||
// is weird because we sort on the low 96-bits first. But if the low
|
||||
// 96-bits are identical we still need a fully deterministic sort.
|
||||
@@ -230,6 +235,7 @@ changeTokenURI(
|
||||
uint256 const& nftokenID,
|
||||
std::optional<xrpl::Slice> const& uri)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::shared_ptr<SLE> const page = locatePage(view, owner, nftokenID);
|
||||
|
||||
// If the page couldn't be found, the given NFT isn't owned by this account
|
||||
@@ -262,6 +268,7 @@ changeTokenURI(
|
||||
TER
|
||||
insertToken(ApplyView& view, AccountID owner, STObject&& nft)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(nft.isFieldPresent(sfNFTokenID), "xrpl::nft::insertToken : has NFT token");
|
||||
|
||||
// First, we need to locate the page the NFT belongs to, creating it
|
||||
@@ -298,6 +305,7 @@ insertToken(ApplyView& view, AccountID owner, STObject&& nft)
|
||||
static bool
|
||||
mergePages(ApplyView& view, std::shared_ptr<SLE> const& p1, std::shared_ptr<SLE> const& p2)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (p1->key() >= p2->key())
|
||||
Throw<std::runtime_error>("mergePages: pages passed in out of order!");
|
||||
|
||||
@@ -355,6 +363,7 @@ mergePages(ApplyView& view, std::shared_ptr<SLE> const& p1, std::shared_ptr<SLE>
|
||||
TER
|
||||
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::shared_ptr<SLE> const page = locatePage(view, owner, nftokenID);
|
||||
|
||||
// If the page couldn't be found, the given NFT isn't owned by this account
|
||||
@@ -372,6 +381,7 @@ removeToken(
|
||||
uint256 const& nftokenID,
|
||||
std::shared_ptr<SLE> const& curr)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// We found a page, but the given NFT may not be in it.
|
||||
auto arr = curr->getFieldArray(sfNFTokens);
|
||||
|
||||
@@ -535,6 +545,7 @@ removeToken(
|
||||
std::optional<STObject>
|
||||
findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::shared_ptr<SLE const> const page = locatePage(view, owner, nftokenID);
|
||||
|
||||
// If the page couldn't be found, the given NFT isn't owned by this account
|
||||
@@ -554,6 +565,7 @@ findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID
|
||||
std::optional<TokenAndPage>
|
||||
findTokenAndPage(ApplyView& view, AccountID const& owner, uint256 const& nftokenID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::shared_ptr<SLE> page = locatePage(view, owner, nftokenID);
|
||||
|
||||
// If the page couldn't be found, the given NFT isn't owned by this account
|
||||
@@ -575,6 +587,7 @@ findTokenAndPage(ApplyView& view, AccountID const& owner, uint256 const& nftoken
|
||||
std::size_t
|
||||
removeTokenOffersWithLimit(ApplyView& view, Keylet const& directory, std::size_t maxDeletableOffers)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (maxDeletableOffers == 0)
|
||||
return 0;
|
||||
|
||||
@@ -625,6 +638,7 @@ removeTokenOffersWithLimit(ApplyView& view, Keylet const& directory, std::size_t
|
||||
bool
|
||||
deleteTokenOffer(ApplyView& view, std::shared_ptr<SLE> const& offer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (offer->getType() != ltNFTOKEN_OFFER)
|
||||
return false;
|
||||
|
||||
@@ -653,6 +667,7 @@ deleteTokenOffer(ApplyView& view, std::shared_ptr<SLE> const& offer)
|
||||
bool
|
||||
repairNFTokenDirectoryLinks(ApplyView& view, AccountID const& owner)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool didRepair = false;
|
||||
|
||||
auto const last = keylet::nftpageMax(owner);
|
||||
@@ -780,6 +795,7 @@ tokenOfferCreatePreflight(
|
||||
std::optional<AccountID> const& owner,
|
||||
std::uint32_t txFlags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (amount.negative())
|
||||
{
|
||||
// An offer for a negative amount makes no sense.
|
||||
@@ -833,6 +849,7 @@ tokenOfferCreatePreclaim(
|
||||
std::optional<AccountID> const& owner,
|
||||
std::uint32_t txFlags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (((nftFlags & nft::kFLAG_CREATE_TRUST_LINES) == 0) && !amount.native() && (xferFee != 0u))
|
||||
{
|
||||
if (!view.exists(keylet::account(nftIssuer)))
|
||||
@@ -933,6 +950,7 @@ tokenOfferCreateApply(
|
||||
beast::Journal j,
|
||||
std::uint32_t txFlags)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Keylet const acctKeylet = keylet::account(acctID);
|
||||
if (auto const acct = view.read(acctKeylet);
|
||||
priorBalance < view.fees().accountReserve((*acct)[sfOwnerCount] + 1))
|
||||
@@ -999,6 +1017,7 @@ checkTrustlineAuthorized(
|
||||
beast::Journal const j,
|
||||
Issue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Only valid for custom currencies
|
||||
XRPL_ASSERT(!isXRP(issue.currency), "xrpl::nft::checkTrustlineAuthorized : valid to check.");
|
||||
|
||||
@@ -1051,6 +1070,7 @@ checkTrustlineDeepFrozen(
|
||||
beast::Journal const j,
|
||||
Issue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Only valid for custom currencies
|
||||
XRPL_ASSERT(!isXRP(issue.currency), "xrpl::nft::checkTrustlineDeepFrozen : valid to check.");
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/protocol/STArray.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -19,6 +20,7 @@ namespace xrpl {
|
||||
TER
|
||||
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!sle)
|
||||
return tesSUCCESS;
|
||||
auto offerIndex = sle->key();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -23,6 +24,7 @@ closeChannel(
|
||||
uint256 const& key,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
AccountID const src = (*slep)[sfAccount];
|
||||
// Remove PayChan from owner directory
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -19,6 +20,7 @@ namespace xrpl::permissioned_dex {
|
||||
bool
|
||||
accountInDomain(ReadView const& view, AccountID const& account, Domain const& domainID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sleDomain = view.read(keylet::permissionedDomain(domainID));
|
||||
if (!sleDomain)
|
||||
return false;
|
||||
@@ -48,6 +50,7 @@ offerInDomain(
|
||||
Domain const& domainID,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const sleOffer = view.read(keylet::offer(offerID));
|
||||
|
||||
// The following are defensive checks that should never happen, since this
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -45,6 +46,7 @@ creditLimit(
|
||||
AccountID const& issuer,
|
||||
Currency const& currency)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount result(Issue{currency, account});
|
||||
|
||||
auto sleRippleState = view.read(keylet::line(account, issuer, currency));
|
||||
@@ -66,6 +68,7 @@ creditLimit(
|
||||
IOUAmount
|
||||
creditLimit2(ReadView const& v, AccountID const& acc, AccountID const& iss, Currency const& cur)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return toAmount<IOUAmount>(creditLimit(v, acc, iss, cur));
|
||||
}
|
||||
|
||||
@@ -76,6 +79,7 @@ creditBalance(
|
||||
AccountID const& issuer,
|
||||
Currency const& currency)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount result(Issue{currency, account});
|
||||
|
||||
auto sleRippleState = view.read(keylet::line(account, issuer, currency));
|
||||
@@ -109,6 +113,7 @@ isIndividualFrozen(
|
||||
Currency const& currency,
|
||||
AccountID const& issuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(currency))
|
||||
return false;
|
||||
if (issuer != account)
|
||||
@@ -130,6 +135,7 @@ isFrozen(
|
||||
Currency const& currency,
|
||||
AccountID const& issuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(currency))
|
||||
return false;
|
||||
auto sle = view.read(keylet::account(issuer));
|
||||
@@ -152,6 +158,7 @@ isDeepFrozen(
|
||||
Currency const& currency,
|
||||
AccountID const& issuer)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(currency))
|
||||
{
|
||||
return false;
|
||||
@@ -197,6 +204,7 @@ trustCreate(
|
||||
std::uint32_t uQualityOut,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JLOG(j.trace()) << "trustCreate: " << to_string(uSrcAccountID) << ", "
|
||||
<< to_string(uDstAccountID) << ", " << saBalance.getFullText();
|
||||
|
||||
@@ -299,6 +307,7 @@ trustDelete(
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Detect legacy dirs.
|
||||
std::uint64_t const uLowNode = sleRippleState->getFieldU64(sfLowNode);
|
||||
std::uint64_t const uHighNode = sleRippleState->getFieldU64(sfHighNode);
|
||||
@@ -339,6 +348,7 @@ updateTrustLine(
|
||||
STAmount const& after,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!state)
|
||||
return false;
|
||||
std::uint32_t const flags(state->getFieldU32(sfFlags));
|
||||
@@ -387,6 +397,7 @@ issueIOU(
|
||||
Issue const& issue,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
!isXRP(account) && !isXRP(issue.account),
|
||||
"xrpl::issueIOU : neither account nor issuer is XRP");
|
||||
@@ -481,6 +492,7 @@ redeemIOU(
|
||||
Issue const& issue,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
!isXRP(account) && !isXRP(issue.account),
|
||||
"xrpl::redeemIOU : neither account nor issuer is XRP");
|
||||
@@ -553,6 +565,7 @@ redeemIOU(
|
||||
TER
|
||||
requireAuth(ReadView const& view, Issue const& issue, AccountID const& account, AuthType authType)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(issue) || issue.account == account)
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -582,6 +595,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
|
||||
TER
|
||||
canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (issue.native())
|
||||
return tesSUCCESS;
|
||||
|
||||
@@ -625,6 +639,7 @@ addEmptyHolding(
|
||||
Issue const& issue,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Every account can hold XRP. An issuer can issue directly.
|
||||
if (issue.native() || accountID == issue.getIssuer())
|
||||
return tesSUCCESS;
|
||||
@@ -678,6 +693,7 @@ removeEmptyHolding(
|
||||
Issue const& issue,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (issue.native())
|
||||
{
|
||||
auto const sle = view.read(keylet::account(accountID));
|
||||
@@ -741,6 +757,7 @@ deleteAMMTrustLine(
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!sleState || sleState->getType() != ltRIPPLE_STATE)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
@@ -789,6 +806,7 @@ deleteAMMMPToken(
|
||||
AccountID const& ammAccountID,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(ammAccountID), (*sleMpt)[sfOwnerNode], sleMpt->key(), false))
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
@@ -50,6 +51,7 @@ isLPTokenFrozen(
|
||||
bool
|
||||
isGlobalFrozen(ReadView const& view, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return asset.visit(
|
||||
[&](Issue const& issue) { return isGlobalFrozen(view, issue.getIssuer()); },
|
||||
[&](MPTIssue const& issue) { return isGlobalFrozen(view, issue); });
|
||||
@@ -58,6 +60,7 @@ isGlobalFrozen(ReadView const& view, Asset const& asset)
|
||||
bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return isIndividualFrozen(view, account, issue); }, asset.value());
|
||||
}
|
||||
@@ -65,6 +68,7 @@ isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const&
|
||||
bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return isFrozen(view, account, issue, depth); }, asset.value());
|
||||
}
|
||||
@@ -72,18 +76,21 @@ isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int
|
||||
TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return checkFrozen(view, account, issue); }, asset.value());
|
||||
}
|
||||
@@ -94,6 +101,7 @@ isAnyFrozen(
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
Issue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& account : accounts)
|
||||
{
|
||||
if (isFrozen(view, account, issue.currency, issue.account))
|
||||
@@ -109,6 +117,7 @@ isAnyFrozen(
|
||||
Asset const& asset,
|
||||
int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return asset.visit(
|
||||
[&](Issue const& issue) { return isAnyFrozen(view, accounts, issue); },
|
||||
[&](MPTIssue const& issue) { return isAnyFrozen(view, accounts, issue, depth); });
|
||||
@@ -117,6 +126,7 @@ isAnyFrozen(
|
||||
bool
|
||||
isDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Unlike IOUs, frozen / locked MPTs are not allowed to send or receive
|
||||
// funds, so checking "deep frozen" is the same as checking "frozen".
|
||||
return isFrozen(view, account, mptIssue, depth);
|
||||
@@ -125,6 +135,7 @@ isDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mpt
|
||||
bool
|
||||
isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return isDeepFrozen(view, account, issue, depth); },
|
||||
asset.value());
|
||||
@@ -133,12 +144,14 @@ isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset,
|
||||
TER
|
||||
checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
checkDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return checkDeepFrozen(view, account, issue); }, asset.value());
|
||||
}
|
||||
@@ -158,6 +171,7 @@ getLineIfUsable(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto sle = view.read(keylet::line(account, issuer, currency));
|
||||
|
||||
if (!sle)
|
||||
@@ -208,6 +222,7 @@ getTrustLineBalance(
|
||||
bool includeOppositeLimit,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount amount;
|
||||
if (sle)
|
||||
{
|
||||
@@ -246,6 +261,7 @@ accountHolds(
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount const amount;
|
||||
if (isXRP(currency))
|
||||
{
|
||||
@@ -276,6 +292,7 @@ accountHolds(
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return accountHolds(
|
||||
view, account, issue.currency, issue.account, zeroIfFrozen, j, includeFullBalance);
|
||||
}
|
||||
@@ -290,6 +307,7 @@ accountHolds(
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
bool const returnSpendable = (includeFullBalance == SpendableHandling::FullBalance);
|
||||
STAmount amount{mptIssue};
|
||||
auto const& issuer = mptIssue.getIssuer();
|
||||
@@ -361,6 +379,7 @@ accountHolds(
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return asset.visit(
|
||||
[&](Issue const& issue) {
|
||||
return accountHolds(view, account, issue, zeroIfFrozen, j, includeFullBalance);
|
||||
@@ -379,6 +398,7 @@ accountFunds(
|
||||
FreezeHandling freezeHandling,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(saDefault.holds<Issue>(), "xrpl::accountFunds: saDefault holds Issue");
|
||||
|
||||
if (!saDefault.native() && saDefault.getIssuer() == id)
|
||||
@@ -397,6 +417,7 @@ accountFunds(
|
||||
AuthHandling authHandling,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return saDefault.asset().visit(
|
||||
[&](Issue const&) { return accountFunds(view, id, saDefault, freezeHandling, j); },
|
||||
[&](MPTIssue const&) {
|
||||
@@ -414,6 +435,7 @@ accountFunds(
|
||||
Rate
|
||||
transferRate(ReadView const& view, STAmount const& amount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return amount.asset().visit(
|
||||
[&](Issue const& issue) { return transferRate(view, issue.getIssuer()); },
|
||||
[&](MPTIssue const& issue) { return transferRate(view, issue.getMptID()); });
|
||||
@@ -428,6 +450,7 @@ transferRate(ReadView const& view, STAmount const& amount)
|
||||
[[nodiscard]] TER
|
||||
canAddHolding(ReadView const& view, Issue const& issue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (issue.native())
|
||||
{
|
||||
return tesSUCCESS; // No special checks for XRP
|
||||
@@ -449,6 +472,7 @@ canAddHolding(ReadView const& view, Issue const& issue)
|
||||
[[nodiscard]] TER
|
||||
canAddHolding(ReadView const& view, Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER { return canAddHolding(view, issue); },
|
||||
asset.value());
|
||||
@@ -462,6 +486,7 @@ addEmptyHolding(
|
||||
Asset const& asset,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
||||
return addEmptyHolding(view, accountID, priorBalance, issue, journal);
|
||||
@@ -476,6 +501,7 @@ removeEmptyHolding(
|
||||
Asset const& asset,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
||||
return removeEmptyHolding(view, accountID, issue, journal);
|
||||
@@ -492,6 +518,7 @@ removeEmptyHolding(
|
||||
TER
|
||||
requireAuth(ReadView const& view, Asset const& asset, AccountID const& account, AuthType authType)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
||||
return requireAuth(view, issue, account, authType);
|
||||
@@ -502,6 +529,7 @@ requireAuth(ReadView const& view, Asset const& asset, AccountID const& account,
|
||||
TER
|
||||
canTransfer(ReadView const& view, Asset const& asset, AccountID const& from, AccountID const& to)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
||||
return canTransfer(view, issue, from, to);
|
||||
@@ -528,6 +556,7 @@ directSendNoFeeIOU(
|
||||
bool bCheckIssuer,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
AccountID const& issuer = saAmount.getIssuer();
|
||||
Currency const& currency = saAmount.get<Issue>().currency;
|
||||
|
||||
@@ -673,6 +702,7 @@ directSendNoLimitIOU(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& issuer = saAmount.getIssuer();
|
||||
|
||||
XRPL_ASSERT(
|
||||
@@ -722,6 +752,7 @@ directSendNoLimitMultiIOU(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& issuer = issue.getIssuer();
|
||||
|
||||
XRPL_ASSERT(!isXRP(senderID), "xrpl::directSendNoLimitMultiIOU : sender is not XRP");
|
||||
@@ -793,6 +824,7 @@ accountSendIOU(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (view.rules().enabled(fixAMMv1_1))
|
||||
{
|
||||
if (saAmount < beast::kZERO || saAmount.holds<MPTIssue>())
|
||||
@@ -910,6 +942,7 @@ accountSendMultiIOU(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT_PARTS(
|
||||
receivers.size() > 1, "xrpl::accountSendMultiIOU", "multiple recipients provided");
|
||||
|
||||
@@ -1036,6 +1069,7 @@ directSendNoFeeMPT(
|
||||
STAmount const& saAmount,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Do not check MPT authorization here - it must have been checked earlier
|
||||
auto const mptID = keylet::mptIssuance(saAmount.get<MPTIssue>().getMptID());
|
||||
auto const& issuer = saAmount.getIssuer();
|
||||
@@ -1117,6 +1151,7 @@ directSendNoLimitMPT(
|
||||
WaiveTransferFee waiveFee,
|
||||
AllowMPTOverflow allowOverflow)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::directSendNoLimitMPT : sender is not receiver");
|
||||
|
||||
// Safe to get MPT since directSendNoLimitMPT is only called by accountSendMPT
|
||||
@@ -1177,6 +1212,7 @@ directSendNoLimitMultiMPT(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& issuer = mptIssue.getIssuer();
|
||||
|
||||
auto const sle = view.read(keylet::mptIssuance(mptIssue.getMptID()));
|
||||
@@ -1297,6 +1333,7 @@ accountSendMPT(
|
||||
WaiveTransferFee waiveFee,
|
||||
AllowMPTOverflow allowOverflow)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
saAmount >= beast::kZERO && saAmount.holds<MPTIssue>(),
|
||||
"xrpl::accountSendMPT : minimum amount and MPT");
|
||||
@@ -1322,6 +1359,7 @@ accountSendMultiMPT(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
STAmount actual;
|
||||
|
||||
return directSendNoLimitMultiMPT(view, senderID, mptIssue, receivers, actual, j, waiveFee);
|
||||
@@ -1342,6 +1380,7 @@ directSendNoFee(
|
||||
bool bCheckIssuer,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return saAmount.asset().visit(
|
||||
[&](Issue const&) {
|
||||
return directSendNoFeeIOU(view, uSenderID, uReceiverID, saAmount, bCheckIssuer, j);
|
||||
@@ -1362,6 +1401,7 @@ accountSend(
|
||||
WaiveTransferFee waiveFee,
|
||||
AllowMPTOverflow allowOverflow)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return saAmount.asset().visit(
|
||||
[&](Issue const&) {
|
||||
return accountSendIOU(view, uSenderID, uReceiverID, saAmount, j, waiveFee);
|
||||
@@ -1381,6 +1421,7 @@ accountSendMulti(
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT_PARTS(
|
||||
receivers.size() > 1, "xrpl::accountSendMulti", "multiple recipients provided");
|
||||
return asset.visit(
|
||||
@@ -1400,6 +1441,7 @@ transferXRP(
|
||||
STAmount const& amount,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(from != beast::kZERO, "xrpl::transferXRP : nonzero from account");
|
||||
XRPL_ASSERT(to != beast::kZERO, "xrpl::transferXRP : nonzero to account");
|
||||
XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STNumber.h> // IWYU pragma: keep
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -18,6 +19,7 @@ assetsToSharesDeposit(
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& assets)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets");
|
||||
XRPL_ASSERT(
|
||||
assets.asset() == vault->at(sfAsset),
|
||||
@@ -45,6 +47,7 @@ sharesToAssetsDeposit(
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares");
|
||||
XRPL_ASSERT(
|
||||
shares.asset() == vault->at(sfShareMPTID),
|
||||
@@ -72,6 +75,7 @@ assetsToSharesWithdraw(
|
||||
STAmount const& assets,
|
||||
TruncateShares truncate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesWithdraw : non-negative assets");
|
||||
XRPL_ASSERT(
|
||||
assets.asset() == vault->at(sfAsset),
|
||||
@@ -98,6 +102,7 @@ sharesToAssetsWithdraw(
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsWithdraw : non-negative shares");
|
||||
XRPL_ASSERT(
|
||||
shares.asset() == vault->at(sfShareMPTID),
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/net/AutoSocket.h>
|
||||
#include <xrpl/net/HTTPClientSSLContext.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/completion_condition.hpp>
|
||||
@@ -42,12 +43,14 @@ HTTPClient::initializeSSLContext(
|
||||
bool sslVerify,
|
||||
beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
gHttpClientSslContext.emplace(sslVerifyDir, sslVerifyFile, sslVerify, j);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPClient::cleanupSSLContext()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
gHttpClientSslContext.reset();
|
||||
}
|
||||
|
||||
@@ -83,6 +86,7 @@ public:
|
||||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
|
||||
makeGet(std::string const& strPath, boost::asio::streambuf& sb, std::string const& strHost)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::ostream osRequest(&sb);
|
||||
|
||||
osRequest << "GET " << strPath
|
||||
@@ -107,6 +111,7 @@ public:
|
||||
int iStatus,
|
||||
std::string const& strData)> complete)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ssl_ = bSSL;
|
||||
deqSites_ = deqSites;
|
||||
build_ = build;
|
||||
@@ -128,6 +133,7 @@ public:
|
||||
int iStatus,
|
||||
std::string const& strData)> complete)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
complete_ = complete;
|
||||
timeout_ = timeout;
|
||||
|
||||
@@ -149,6 +155,7 @@ public:
|
||||
void
|
||||
httpsNext()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
JLOG(j_.trace()) << "Fetch: " << deqSites_[0];
|
||||
|
||||
auto query = std::make_shared<Query>(
|
||||
@@ -193,6 +200,7 @@ public:
|
||||
void
|
||||
handleDeadline(boost::system::error_code const& ecResult)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (ecResult == boost::asio::error::operation_aborted)
|
||||
{
|
||||
// Timer canceled because deadline no longer needed.
|
||||
@@ -229,6 +237,7 @@ public:
|
||||
void
|
||||
handleShutdown(boost::system::error_code const& ecResult)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (ecResult)
|
||||
{
|
||||
JLOG(j_.trace()) << "Shutdown error: " << deqSites_[0] << ": " << ecResult.message();
|
||||
@@ -240,6 +249,7 @@ public:
|
||||
boost::system::error_code const& ecResult,
|
||||
boost::asio::ip::tcp::resolver::results_type result)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!shutdown_)
|
||||
{
|
||||
shutdown_ = ecResult
|
||||
@@ -270,6 +280,7 @@ public:
|
||||
void
|
||||
handleConnect(boost::system::error_code const& ecResult)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!shutdown_)
|
||||
shutdown_ = ecResult;
|
||||
|
||||
@@ -313,6 +324,7 @@ public:
|
||||
void
|
||||
handleRequest(boost::system::error_code const& ecResult)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!shutdown_)
|
||||
shutdown_ = ecResult;
|
||||
|
||||
@@ -341,6 +353,7 @@ public:
|
||||
void
|
||||
handleWrite(boost::system::error_code const& ecResult, std::size_t bytesTransferred)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!shutdown_)
|
||||
shutdown_ = ecResult;
|
||||
|
||||
@@ -368,6 +381,7 @@ public:
|
||||
void
|
||||
handleHeader(boost::system::error_code const& ecResult, std::size_t bytesTransferred)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string strHeader{
|
||||
{std::istreambuf_iterator<char>(&header_)}, std::istreambuf_iterator<char>()};
|
||||
JLOG(j_.trace()) << "Header: \"" << strHeader << "\"";
|
||||
@@ -435,6 +449,7 @@ public:
|
||||
void
|
||||
handleData(boost::system::error_code const& ecResult, std::size_t bytesTransferred)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!shutdown_)
|
||||
shutdown_ = ecResult;
|
||||
|
||||
@@ -467,6 +482,7 @@ public:
|
||||
int iStatus = 0,
|
||||
std::string const& strData = "")
|
||||
{
|
||||
TRACE_FUNC();
|
||||
boost::system::error_code ecCancel;
|
||||
try
|
||||
{
|
||||
@@ -554,6 +570,7 @@ HTTPClient::get(
|
||||
complete,
|
||||
beast::Journal& j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto client = std::make_shared<HTTPClientImp>(ioContext, port, responseMax, j);
|
||||
client->get(bSSL, deqSites, strPath, timeout, complete);
|
||||
}
|
||||
@@ -572,6 +589,7 @@ HTTPClient::get(
|
||||
complete,
|
||||
beast::Journal& j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::deque<std::string> const deqSites(1, strSite);
|
||||
|
||||
auto client = std::make_shared<HTTPClientImp>(ioContext, port, responseMax, j);
|
||||
@@ -592,6 +610,7 @@ HTTPClient::request(
|
||||
complete,
|
||||
beast::Journal& j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::deque<std::string> const deqSites(1, strSite);
|
||||
|
||||
auto client = std::make_shared<HTTPClientImp>(ioContext, port, responseMax, j);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/net/RegisterSSLCerts.h>
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <boost/system/detail/error_code.hpp>
|
||||
@@ -23,6 +24,7 @@ namespace xrpl {
|
||||
void
|
||||
registerSSLCerts(boost::asio::ssl::context& ctx, boost::system::error_code& ec, beast::Journal j)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
#if BOOST_OS_WINDOWS
|
||||
auto certStoreDelete = [](void* h) {
|
||||
if (h != nullptr)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -16,17 +17,20 @@ namespace xrpl::NodeStore {
|
||||
BatchWriter::BatchWriter(Callback& callback, Scheduler& scheduler)
|
||||
: callback_(callback), scheduler_(scheduler)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
writeSet_.reserve(BatchWritePreallocationSize);
|
||||
}
|
||||
|
||||
BatchWriter::~BatchWriter()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
waitForWriting();
|
||||
}
|
||||
|
||||
void
|
||||
BatchWriter::store(std::shared_ptr<NodeObject> const& object)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::unique_lock<decltype(writeMutex_)> sl(writeMutex_);
|
||||
|
||||
// If the batch has reached its limit, we wait
|
||||
@@ -47,6 +51,7 @@ BatchWriter::store(std::shared_ptr<NodeObject> const& object)
|
||||
int
|
||||
BatchWriter::getWriteLoad()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const sl(writeMutex_);
|
||||
|
||||
return std::max(writeLoad_, static_cast<int>(writeSet_.size()));
|
||||
@@ -55,12 +60,14 @@ BatchWriter::getWriteLoad()
|
||||
void
|
||||
BatchWriter::performScheduledTask()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
writeBatch();
|
||||
}
|
||||
|
||||
void
|
||||
BatchWriter::writeBatch()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (;;)
|
||||
{
|
||||
std::vector<std::shared_ptr<NodeObject>> set;
|
||||
@@ -101,6 +108,7 @@ BatchWriter::writeBatch()
|
||||
void
|
||||
BatchWriter::waitForWriting()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::unique_lock<decltype(writeMutex_)> sl(writeMutex_);
|
||||
|
||||
while (writePending_)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/protocol/SystemParameters.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -42,6 +43,7 @@ Database::Database(
|
||||
, requestBundle_(get<int>(config, "rq_bundle", 4))
|
||||
, readThreads_(std::max(1, readThreads))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(readThreads, "xrpl::NodeStore::Database::Database : nonzero threads input");
|
||||
|
||||
if (earliestLedgerSeq_ < 1)
|
||||
@@ -124,6 +126,7 @@ Database::Database(
|
||||
|
||||
Database::~Database()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// NOTE!
|
||||
// Any derived class should call the stop() method in its
|
||||
// destructor. Otherwise, occasionally, the derived class may
|
||||
@@ -136,12 +139,14 @@ Database::~Database()
|
||||
bool
|
||||
Database::isStopping() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return readStopping_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void
|
||||
Database::stop()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
{
|
||||
std::scoped_lock const lock(readLock_);
|
||||
|
||||
@@ -179,6 +184,7 @@ Database::asyncFetch(
|
||||
std::uint32_t ledgerSeq,
|
||||
std::function<void(std::shared_ptr<NodeObject> const&)>&& cb)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(readLock_);
|
||||
|
||||
if (!isStopping())
|
||||
@@ -191,6 +197,7 @@ Database::asyncFetch(
|
||||
void
|
||||
Database::importInternal(Backend& dstBackend, Database& srcDB)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Batch batch;
|
||||
batch.reserve(BatchWritePreallocationSize);
|
||||
auto storeBatch = [&, fname = __func__]() {
|
||||
@@ -233,6 +240,17 @@ Database::fetchNodeObject(
|
||||
FetchType fetchType,
|
||||
bool duplicate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
|
||||
{
|
||||
std::scoped_lock const lock(negCacheMutex_);
|
||||
if (negCache_.count(hash))
|
||||
{
|
||||
++fetchTotalCount_;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FetchReport fetchReport(fetchType);
|
||||
|
||||
using namespace std::chrono;
|
||||
@@ -246,6 +264,12 @@ Database::fetchNodeObject(
|
||||
++fetchHitCount_;
|
||||
fetchSz_ += nodeObject->getData().size();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::scoped_lock const lock(negCacheMutex_);
|
||||
if (negCache_.size() < kNegCacheMax)
|
||||
negCache_.insert(hash);
|
||||
}
|
||||
++fetchTotalCount_;
|
||||
|
||||
fetchReport.elapsed = duration_cast<milliseconds>(dur);
|
||||
@@ -253,9 +277,24 @@ Database::fetchNodeObject(
|
||||
return nodeObject;
|
||||
}
|
||||
|
||||
void
|
||||
Database::negCacheErase(uint256 const& hash)
|
||||
{
|
||||
std::scoped_lock const lock(negCacheMutex_);
|
||||
negCache_.erase(hash);
|
||||
}
|
||||
|
||||
void
|
||||
Database::negCacheClear()
|
||||
{
|
||||
std::scoped_lock const lock(negCacheMutex_);
|
||||
negCache_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Database::getCountsJson(json::Value& obj)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(obj.isObject(), "xrpl::NodeStore::Database::getCountsJson : valid input type");
|
||||
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
@@ -25,10 +26,12 @@ namespace xrpl::NodeStore {
|
||||
void
|
||||
DatabaseNodeImp::store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
storeStats(1, data.size());
|
||||
|
||||
auto obj = NodeObject::createObject(type, std::move(data), hash);
|
||||
backend_->store(obj);
|
||||
negCacheErase(hash);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -37,6 +40,7 @@ DatabaseNodeImp::asyncFetch(
|
||||
std::uint32_t ledgerSeq,
|
||||
std::function<void(std::shared_ptr<NodeObject> const&)>&& callback)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Database::asyncFetch(hash, ledgerSeq, std::move(callback));
|
||||
}
|
||||
|
||||
@@ -47,6 +51,7 @@ DatabaseNodeImp::fetchNodeObject(
|
||||
FetchReport& fetchReport,
|
||||
bool duplicate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::shared_ptr<NodeObject> nodeObject = nullptr;
|
||||
Status status = Status::Ok;
|
||||
|
||||
@@ -84,6 +89,7 @@ DatabaseNodeImp::fetchNodeObject(
|
||||
std::vector<std::shared_ptr<NodeObject>>
|
||||
DatabaseNodeImp::fetchBatch(std::vector<uint256> const& hashes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace std::chrono;
|
||||
auto const before = steady_clock::now();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
@@ -33,7 +34,9 @@ DatabaseRotatingImp::DatabaseRotatingImp(
|
||||
: DatabaseRotating(scheduler, readThreads, config, j)
|
||||
, writableBackend_(std::move(writableBackend))
|
||||
, archiveBackend_(std::move(archiveBackend))
|
||||
, archiveHasData_(!get<bool>(config, "fresh_sync", false))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (writableBackend_)
|
||||
fdRequired_ += writableBackend_->fdRequired();
|
||||
if (archiveBackend_)
|
||||
@@ -45,6 +48,7 @@ DatabaseRotatingImp::rotate(
|
||||
std::unique_ptr<NodeStore::Backend>&& newBackend,
|
||||
std::function<void(std::string const& writableName, std::string const& archiveName)> const& f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Pass these two names to the callback function
|
||||
std::string const newWritableBackendName = newBackend->getName();
|
||||
std::string newArchiveBackendName;
|
||||
@@ -64,12 +68,15 @@ DatabaseRotatingImp::rotate(
|
||||
writableBackend_ = std::move(newBackend);
|
||||
}
|
||||
|
||||
archiveHasData_.store(true, std::memory_order_relaxed);
|
||||
negCacheClear();
|
||||
f(newWritableBackendName, newArchiveBackendName);
|
||||
}
|
||||
|
||||
std::string
|
||||
DatabaseRotatingImp::getName() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return writableBackend_->getName();
|
||||
}
|
||||
@@ -77,6 +84,7 @@ DatabaseRotatingImp::getName() const
|
||||
std::int32_t
|
||||
DatabaseRotatingImp::getWriteLoad() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return writableBackend_->getWriteLoad();
|
||||
}
|
||||
@@ -84,6 +92,7 @@ DatabaseRotatingImp::getWriteLoad() const
|
||||
void
|
||||
DatabaseRotatingImp::importDatabase(Database& source)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const backend = [&] {
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return writableBackend_;
|
||||
@@ -95,6 +104,7 @@ DatabaseRotatingImp::importDatabase(Database& source)
|
||||
void
|
||||
DatabaseRotatingImp::sync()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const lock(mutex_);
|
||||
writableBackend_->sync();
|
||||
}
|
||||
@@ -102,6 +112,7 @@ DatabaseRotatingImp::sync()
|
||||
void
|
||||
DatabaseRotatingImp::store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto nObj = NodeObject::createObject(type, std::move(data), hash);
|
||||
|
||||
auto const backend = [&] {
|
||||
@@ -111,6 +122,7 @@ DatabaseRotatingImp::store(NodeObjectType type, Blob&& data, uint256 const& hash
|
||||
|
||||
backend->store(nObj);
|
||||
storeStats(1, nObj->getData().size());
|
||||
negCacheErase(hash);
|
||||
}
|
||||
|
||||
std::shared_ptr<NodeObject>
|
||||
@@ -120,6 +132,7 @@ DatabaseRotatingImp::fetchNodeObject(
|
||||
FetchReport& fetchReport,
|
||||
bool duplicate)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto fetch = [&](std::shared_ptr<Backend> const& backend) {
|
||||
Status status = Status::Ok;
|
||||
std::shared_ptr<NodeObject> nodeObject;
|
||||
@@ -159,12 +172,14 @@ DatabaseRotatingImp::fetchNodeObject(
|
||||
|
||||
// Try to fetch from the writable backend
|
||||
nodeObject = fetch(writable);
|
||||
if (!nodeObject)
|
||||
if (!nodeObject && archiveHasData_.load(std::memory_order_relaxed))
|
||||
{
|
||||
// Otherwise try to fetch from the archive backend
|
||||
// Only try archive if it's known to have data
|
||||
nodeObject = fetch(archive);
|
||||
if (nodeObject)
|
||||
{
|
||||
archiveHasData_.store(true, std::memory_order_relaxed);
|
||||
|
||||
{
|
||||
// Refresh the writable backend pointer
|
||||
std::scoped_lock const lock(mutex_);
|
||||
@@ -186,6 +201,7 @@ DatabaseRotatingImp::fetchNodeObject(
|
||||
void
|
||||
DatabaseRotatingImp::forEach(std::function<void(std::shared_ptr<NodeObject>)> f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto [writable, archive] = [&] {
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return std::make_pair(writableBackend_, archiveBackend_);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@@ -14,6 +15,7 @@ namespace xrpl::NodeStore {
|
||||
|
||||
DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
/* Data format:
|
||||
|
||||
Bytes
|
||||
@@ -59,6 +61,7 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes)
|
||||
std::shared_ptr<NodeObject>
|
||||
DecodedBlob::createObject()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(success_, "xrpl::NodeStore::DecodedBlob::createObject : valid object type");
|
||||
|
||||
std::shared_ptr<NodeObject> object;
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Task.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
void
|
||||
DummyScheduler::scheduleTask(Task& task)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Invoke the task synchronously.
|
||||
task.performScheduledTask();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
@@ -26,6 +27,7 @@ namespace xrpl::NodeStore {
|
||||
ManagerImp&
|
||||
ManagerImp::instance()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static ManagerImp k_;
|
||||
return k_;
|
||||
}
|
||||
@@ -33,6 +35,7 @@ ManagerImp::instance()
|
||||
void
|
||||
ManagerImp::missingBackend()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Throw<std::runtime_error>(
|
||||
"Your xrpld.cfg is missing a [node_db] entry, "
|
||||
"please see the xrpld-example.cfg file!");
|
||||
@@ -53,6 +56,7 @@ registerMemoryFactory(Manager& manager);
|
||||
|
||||
ManagerImp::ManagerImp()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
registerNuDBFactory(*this);
|
||||
registerRocksDBFactory(*this);
|
||||
registerNullFactory(*this);
|
||||
@@ -66,6 +70,7 @@ ManagerImp::makeBackend(
|
||||
Scheduler& scheduler,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string const type{get(parameters, "type")};
|
||||
if (type.empty())
|
||||
missingBackend();
|
||||
@@ -88,6 +93,7 @@ ManagerImp::makeDatabase(
|
||||
Section const& config,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto backend{makeBackend(config, burstSize, scheduler, journal)};
|
||||
backend->open();
|
||||
return std::make_unique<DatabaseNodeImp>(
|
||||
@@ -97,6 +103,7 @@ ManagerImp::makeDatabase(
|
||||
void
|
||||
ManagerImp::insert(Factory& factory)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mutex_);
|
||||
list_.push_back(&factory);
|
||||
}
|
||||
@@ -104,6 +111,7 @@ ManagerImp::insert(Factory& factory)
|
||||
void
|
||||
ManagerImp::erase(Factory& factory)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mutex_);
|
||||
auto const iter =
|
||||
std::ranges::find_if(list_, [&factory](Factory* other) { return other == &factory; });
|
||||
@@ -114,6 +122,7 @@ ManagerImp::erase(Factory& factory)
|
||||
Factory*
|
||||
ManagerImp::find(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mutex_);
|
||||
auto const iter = std::ranges::find_if(
|
||||
list_, [&name](Factory* other) { return boost::iequals(name, other->getName()); });
|
||||
@@ -127,6 +136,7 @@ ManagerImp::find(std::string const& name)
|
||||
Manager&
|
||||
Manager::instance()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return ManagerImp::instance();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@@ -18,24 +19,28 @@ NodeObject::NodeObject(NodeObjectType type, Blob&& data, uint256 const& hash, Pr
|
||||
std::shared_ptr<NodeObject>
|
||||
NodeObject::createObject(NodeObjectType type, Blob&& data, uint256 const& hash)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_shared<NodeObject>(type, std::move(data), hash, PrivateAccess());
|
||||
}
|
||||
|
||||
NodeObjectType
|
||||
NodeObject::getType() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return type_;
|
||||
}
|
||||
|
||||
uint256 const&
|
||||
NodeObject::getHash() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return hash_;
|
||||
}
|
||||
|
||||
Blob const&
|
||||
NodeObject::getData() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
MemoryDB&
|
||||
open(std::string const& path)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::scoped_lock const _(mutex_);
|
||||
auto const result =
|
||||
map_.emplace(std::piecewise_construct, std::make_tuple(path), std::make_tuple());
|
||||
@@ -74,6 +76,7 @@ MemoryFactory* gMemoryFactory = nullptr;
|
||||
void
|
||||
registerMemoryFactory(Manager& manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static MemoryFactory kINSTANCE{manager};
|
||||
gMemoryFactory = &kINSTANCE;
|
||||
}
|
||||
@@ -93,6 +96,7 @@ public:
|
||||
MemoryBackend(size_t keyBytes, Section const& keyValues, beast::Journal journal)
|
||||
: name_(get(keyValues, "path")), journal_(journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
boost::ignore_unused(journal_); // Keep unused journal_ just in case.
|
||||
if (name_.empty())
|
||||
Throw<std::runtime_error>("Missing path in Memory backend");
|
||||
@@ -100,30 +104,35 @@ public:
|
||||
|
||||
~MemoryBackend() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
close();
|
||||
}
|
||||
|
||||
std::string
|
||||
getName() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return name_;
|
||||
}
|
||||
|
||||
void
|
||||
open(bool) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
db_ = &gMemoryFactory->open(name_);
|
||||
}
|
||||
|
||||
bool
|
||||
isOpen() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return static_cast<bool>(db_);
|
||||
}
|
||||
|
||||
void
|
||||
close() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
db_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -132,6 +141,7 @@ public:
|
||||
Status
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database");
|
||||
|
||||
std::scoped_lock const _(db_->mutex);
|
||||
@@ -149,6 +159,7 @@ public:
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
@@ -171,6 +182,7 @@ public:
|
||||
void
|
||||
store(std::shared_ptr<NodeObject> const& object) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::store : non-null database");
|
||||
std::scoped_lock const _(db_->mutex);
|
||||
db_->table.emplace(object->getHash(), object);
|
||||
@@ -179,6 +191,7 @@ public:
|
||||
void
|
||||
storeBatch(Batch const& batch) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
for (auto const& e : batch)
|
||||
store(e);
|
||||
}
|
||||
@@ -191,6 +204,7 @@ public:
|
||||
void
|
||||
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::forEach : non-null database");
|
||||
for (auto const& e : db_->table)
|
||||
f(e.second);
|
||||
@@ -199,6 +213,7 @@ public:
|
||||
int
|
||||
getWriteLoad() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -210,6 +225,7 @@ public:
|
||||
[[nodiscard]] int
|
||||
fdRequired() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -218,12 +234,14 @@ public:
|
||||
|
||||
MemoryFactory::MemoryFactory(Manager& manager) : manager_(manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
manager_.insert(*this);
|
||||
}
|
||||
|
||||
std::string
|
||||
MemoryFactory::getName() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return "Memory";
|
||||
}
|
||||
|
||||
@@ -235,6 +253,7 @@ MemoryFactory::createInstance(
|
||||
Scheduler& scheduler,
|
||||
beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<MemoryBackend>(keyBytes, keyValues, journal);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <xrpl/nodestore/detail/DecodedBlob.h>
|
||||
#include <xrpl/nodestore/detail/EncodedBlob.h>
|
||||
#include <xrpl/nodestore/detail/codec.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -78,6 +79,7 @@ public:
|
||||
, deletePath(false)
|
||||
, scheduler(scheduler)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (name.empty())
|
||||
Throw<std::runtime_error>("nodestore: Missing path in NuDB backend");
|
||||
}
|
||||
@@ -98,12 +100,14 @@ public:
|
||||
, deletePath(false)
|
||||
, scheduler(scheduler)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (name.empty())
|
||||
Throw<std::runtime_error>("nodestore: Missing path in NuDB backend");
|
||||
}
|
||||
|
||||
~NuDBBackend() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
try
|
||||
{
|
||||
// close can throw and we don't want the destructor to throw.
|
||||
@@ -119,18 +123,21 @@ public:
|
||||
std::string
|
||||
getName() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return name;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<std::size_t>
|
||||
getBlockSize() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
void
|
||||
open(bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace boost::filesystem;
|
||||
if (db.is_open())
|
||||
{
|
||||
@@ -169,18 +176,21 @@ public:
|
||||
bool
|
||||
isOpen() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return db.is_open();
|
||||
}
|
||||
|
||||
void
|
||||
open(bool createIfMissing) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
open(createIfMissing, kAPPNUM, nudb::make_uid(), nudb::make_salt());
|
||||
}
|
||||
|
||||
void
|
||||
close() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (db.is_open())
|
||||
{
|
||||
nudb::error_code ec;
|
||||
@@ -207,6 +217,7 @@ public:
|
||||
Status
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pno) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
Status status = Status::Ok;
|
||||
pno->reset();
|
||||
nudb::error_code ec;
|
||||
@@ -235,6 +246,7 @@ public:
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
@@ -257,6 +269,7 @@ public:
|
||||
void
|
||||
doInsert(std::shared_ptr<NodeObject> const& no)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
EncodedBlob const e(no);
|
||||
nudb::error_code ec;
|
||||
nudb::detail::buffer bf;
|
||||
@@ -269,6 +282,7 @@ public:
|
||||
void
|
||||
store(std::shared_ptr<NodeObject> const& no) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
BatchWriteReport report{};
|
||||
report.writeCount = 1;
|
||||
auto const start = std::chrono::steady_clock::now();
|
||||
@@ -281,6 +295,7 @@ public:
|
||||
void
|
||||
storeBatch(Batch const& batch) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
BatchWriteReport report{};
|
||||
report.writeCount = batch.size();
|
||||
auto const start = std::chrono::steady_clock::now();
|
||||
@@ -299,6 +314,7 @@ public:
|
||||
void
|
||||
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const dp = db.dat_path();
|
||||
auto const kp = db.key_path();
|
||||
auto const lp = db.log_path();
|
||||
@@ -336,18 +352,21 @@ public:
|
||||
int
|
||||
getWriteLoad() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
setDeletePath() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
deletePath = true;
|
||||
}
|
||||
|
||||
void
|
||||
verify() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const dp = db.dat_path();
|
||||
auto const kp = db.key_path();
|
||||
auto const lp = db.log_path();
|
||||
@@ -367,6 +386,7 @@ public:
|
||||
[[nodiscard]] int
|
||||
fdRequired() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -374,6 +394,7 @@ private:
|
||||
static std::size_t
|
||||
parseBlockSize(std::string const& name, Section const& keyValues, beast::Journal journal)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace boost::filesystem;
|
||||
auto const folder = path(name);
|
||||
auto const kp = (folder / "nudb.key").string();
|
||||
@@ -423,12 +444,14 @@ private:
|
||||
public:
|
||||
explicit NuDBFactory(Manager& manager) : manager_(manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
manager_.insert(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string
|
||||
getName() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return "NuDB";
|
||||
}
|
||||
|
||||
@@ -440,6 +463,7 @@ public:
|
||||
Scheduler& scheduler,
|
||||
beast::Journal journal) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<NuDBBackend>(keyBytes, keyValues, burstSize, scheduler, journal);
|
||||
}
|
||||
|
||||
@@ -452,6 +476,7 @@ public:
|
||||
nudb::context& context,
|
||||
beast::Journal journal) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<NuDBBackend>(
|
||||
keyBytes, keyValues, burstSize, scheduler, context, journal);
|
||||
}
|
||||
@@ -460,6 +485,7 @@ public:
|
||||
void
|
||||
registerNuDBFactory(Manager& manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static NuDBFactory const kINSTANCE{manager};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Types.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@@ -27,6 +28,7 @@ public:
|
||||
std::string
|
||||
getName() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@@ -38,6 +40,7 @@ public:
|
||||
bool
|
||||
isOpen() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,12 +52,14 @@ public:
|
||||
Status
|
||||
fetch(uint256 const&, std::shared_ptr<NodeObject>*) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Status::NotFound;
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -81,6 +86,7 @@ public:
|
||||
int
|
||||
getWriteLoad() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -93,6 +99,7 @@ public:
|
||||
[[nodiscard]] int
|
||||
fdRequired() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -109,18 +116,21 @@ private:
|
||||
public:
|
||||
explicit NullFactory(Manager& manager) : manager_(manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
manager_.insert(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string
|
||||
getName() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return "none";
|
||||
}
|
||||
|
||||
std::unique_ptr<Backend>
|
||||
createInstance(size_t, Section const&, std::size_t, Scheduler&, beast::Journal) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<NullBackend>();
|
||||
}
|
||||
};
|
||||
@@ -128,6 +138,7 @@ public:
|
||||
void
|
||||
registerNullFactory(Manager& manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static NullFactory const kINSTANCE{manager};
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <xrpl/nodestore/detail/BatchWriter.h>
|
||||
#include <xrpl/nodestore/detail/DecodedBlob.h>
|
||||
#include <xrpl/nodestore/detail/EncodedBlob.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
@@ -68,6 +69,7 @@ public:
|
||||
static void
|
||||
threadEntry(void* ptr)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ThreadParams const* const p(reinterpret_cast<ThreadParams*>(ptr));
|
||||
auto const f = p->f;
|
||||
|
||||
@@ -84,6 +86,7 @@ public:
|
||||
void
|
||||
StartThread(void (*f)(void*), void* a) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ThreadParams* const p(new ThreadParams(f, a));
|
||||
EnvWrapper::StartThread(&RocksDBEnv::threadEntry, p);
|
||||
}
|
||||
@@ -113,6 +116,7 @@ public:
|
||||
RocksDBEnv* env)
|
||||
: deletePath_(false), journal(journal), keyBytes(keyBytes), batch(*this, scheduler)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!getIfExists(keyValues, "path", name))
|
||||
Throw<std::runtime_error>("Missing path in RocksDBFactory backend");
|
||||
|
||||
@@ -223,12 +227,14 @@ public:
|
||||
|
||||
~RocksDBBackend() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
open(bool createIfMissing) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (db)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
@@ -253,12 +259,14 @@ public:
|
||||
bool
|
||||
isOpen() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return static_cast<bool>(db);
|
||||
}
|
||||
|
||||
void
|
||||
close() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (db)
|
||||
{
|
||||
db.reset();
|
||||
@@ -273,6 +281,7 @@ public:
|
||||
std::string
|
||||
getName() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -281,6 +290,7 @@ public:
|
||||
Status
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(db, "xrpl::NodeStore::RocksDBBackend::fetch : non-null database");
|
||||
pObject->reset();
|
||||
|
||||
@@ -333,6 +343,7 @@ public:
|
||||
std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256> const& hashes) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<std::shared_ptr<NodeObject>> results;
|
||||
results.reserve(hashes.size());
|
||||
for (auto const& h : hashes)
|
||||
@@ -355,12 +366,14 @@ public:
|
||||
void
|
||||
store(std::shared_ptr<NodeObject> const& object) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
batch.store(object);
|
||||
}
|
||||
|
||||
void
|
||||
storeBatch(Batch const& batch) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
db,
|
||||
"xrpl::NodeStore::RocksDBBackend::storeBatch : non-null "
|
||||
@@ -392,6 +405,7 @@ public:
|
||||
void
|
||||
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(db, "xrpl::NodeStore::RocksDBBackend::forEach : non-null database");
|
||||
rocksdb::ReadOptions const options;
|
||||
|
||||
@@ -425,12 +439,14 @@ public:
|
||||
int
|
||||
getWriteLoad() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return batch.getWriteLoad();
|
||||
}
|
||||
|
||||
void
|
||||
setDeletePath() override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
deletePath_ = true;
|
||||
}
|
||||
|
||||
@@ -439,6 +455,7 @@ public:
|
||||
void
|
||||
writeBatch(Batch const& batch) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
storeBatch(batch);
|
||||
}
|
||||
|
||||
@@ -446,6 +463,7 @@ public:
|
||||
[[nodiscard]] int
|
||||
fdRequired() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return fdMinRequired;
|
||||
}
|
||||
};
|
||||
@@ -462,12 +480,14 @@ public:
|
||||
|
||||
RocksDBFactory(Manager& manager) : manager_(manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
manager_.insert(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string
|
||||
getName() const override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return "RocksDB";
|
||||
}
|
||||
|
||||
@@ -479,6 +499,7 @@ public:
|
||||
Scheduler& scheduler,
|
||||
beast::Journal journal) override
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::make_unique<RocksDBBackend>(keyBytes, keyValues, scheduler, journal, &env);
|
||||
}
|
||||
};
|
||||
@@ -486,6 +507,7 @@ public:
|
||||
void
|
||||
registerRocksDBFactory(Manager& manager)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static RocksDBFactory const kINSTANCE{manager};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -28,6 +29,7 @@ namespace xrpl {
|
||||
Currency
|
||||
ammLPTCurrency(Asset const& asset1, Asset const& asset2)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// AMM LPToken is 0x03 plus 19 bytes of the hash
|
||||
std::int32_t constexpr kAMM_CURRENCY_CODE = 0x03;
|
||||
auto const& [minA, maxA] = std::minmax(asset1, asset2);
|
||||
@@ -52,12 +54,14 @@ ammLPTCurrency(Asset const& asset1, Asset const& asset2)
|
||||
Issue
|
||||
ammLPTIssue(Asset const& asset1, Asset const& asset2, AccountID const& ammAccountID)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Issue(ammLPTCurrency(asset1, asset2), ammAccountID);
|
||||
}
|
||||
|
||||
NotTEC
|
||||
invalidAMMAsset(Asset const& asset, std::optional<std::pair<Asset, Asset>> const& pair)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const err = asset.visit(
|
||||
[](MPTIssue const& issue) -> std::optional<NotTEC> {
|
||||
if (issue.getIssuer() == beast::kZERO)
|
||||
@@ -84,6 +88,7 @@ invalidAMMAssetPair(
|
||||
Asset const& asset2,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (asset1 == asset2)
|
||||
return temBAD_AMM_TOKENS;
|
||||
if (auto const res = invalidAMMAsset(asset1, pair))
|
||||
@@ -99,6 +104,7 @@ invalidAMMAmount(
|
||||
std::optional<std::pair<Asset, Asset>> const& pair,
|
||||
bool validZero)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (auto const res = invalidAMMAsset(amount.asset(), pair))
|
||||
return res;
|
||||
if (amount < beast::kZERO || (!validZero && amount == beast::kZERO))
|
||||
@@ -109,6 +115,7 @@ invalidAMMAmount(
|
||||
std::optional<std::uint8_t>
|
||||
ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// It should be impossible for expiration to be < TOTAL_TIME_SLOT_SECS,
|
||||
// but check just to be safe
|
||||
auto const expiration = auctionSlot[sfExpiration];
|
||||
@@ -128,6 +135,7 @@ ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot)
|
||||
bool
|
||||
ammEnabled(Rules const& rules)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return rules.enabled(featureAMM) && rules.enabled(fixUniversalNumber);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/protocol/tokens.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
@@ -43,6 +44,7 @@ private:
|
||||
public:
|
||||
AccountIdCache(std::size_t count) : cache_(count)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// This is non-binding, but we try to avoid wasting memory that
|
||||
// is caused by overallocation.
|
||||
cache_.shrink_to_fit();
|
||||
@@ -51,6 +53,7 @@ public:
|
||||
std::string
|
||||
toBase58(AccountID const& id)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const index = hasher_(id) % cache_.size();
|
||||
|
||||
PackedSpinlock sl(locks_, index % 64);
|
||||
@@ -85,6 +88,7 @@ static std::unique_ptr<detail::AccountIdCache> gAccountIdCache;
|
||||
void
|
||||
initAccountIdCache(std::size_t count)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!gAccountIdCache && count != 0)
|
||||
gAccountIdCache = std::make_unique<detail::AccountIdCache>(count);
|
||||
}
|
||||
@@ -92,6 +96,7 @@ initAccountIdCache(std::size_t count)
|
||||
std::string
|
||||
toBase58(AccountID const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (gAccountIdCache)
|
||||
return gAccountIdCache->toBase58(v);
|
||||
|
||||
@@ -102,6 +107,7 @@ template <>
|
||||
std::optional<AccountID>
|
||||
parseBase58(std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const result = decodeBase58Token(s, TokenType::AccountID);
|
||||
if (result.size() != AccountID::kBYTES)
|
||||
return std::nullopt;
|
||||
@@ -146,6 +152,7 @@ parseBase58(std::string const& s)
|
||||
AccountID
|
||||
calcAccountID(PublicKey const& pk)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static_assert(AccountID::kBYTES == sizeof(RipeshaHasher::result_type));
|
||||
|
||||
RipeshaHasher rsh;
|
||||
@@ -156,6 +163,7 @@ calcAccountID(PublicKey const& pk)
|
||||
AccountID const&
|
||||
xrpAccount()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static AccountID const kACCOUNT(beast::kZERO);
|
||||
return kACCOUNT;
|
||||
}
|
||||
@@ -163,6 +171,7 @@ xrpAccount()
|
||||
AccountID const&
|
||||
noAccount()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static AccountID const kACCOUNT(1);
|
||||
return kACCOUNT;
|
||||
}
|
||||
@@ -170,6 +179,7 @@ noAccount()
|
||||
bool
|
||||
toIssuer(AccountID& issuer, std::string const& s)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (issuer.parseHex(s))
|
||||
return true;
|
||||
auto const account = parseBase58<AccountID>(s);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
@@ -20,36 +21,42 @@ namespace xrpl {
|
||||
AccountID const&
|
||||
Asset::getIssuer() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit([&](auto&& issue) -> AccountID const& { return issue.getIssuer(); }, issue_);
|
||||
}
|
||||
|
||||
std::string
|
||||
Asset::getText() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit([&](auto&& issue) { return issue.getText(); }, issue_);
|
||||
}
|
||||
|
||||
void
|
||||
Asset::setJson(json::Value& jv) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::visit([&](auto&& issue) { issue.setJson(jv); }, issue_);
|
||||
}
|
||||
|
||||
STAmount
|
||||
Asset::operator()(Number const& number) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return STAmount{*this, number};
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(Asset const& asset)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return std::visit([&](auto const& issue) { return to_string(issue); }, asset.value());
|
||||
}
|
||||
|
||||
bool
|
||||
validJSONAsset(json::Value const& jv)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (jv.isMember(jss::mpt_issuance_id))
|
||||
return !(jv.isMember(jss::currency) || jv.isMember(jss::issuer));
|
||||
return jv.isMember(jss::currency);
|
||||
@@ -58,6 +65,7 @@ validJSONAsset(json::Value const& jv)
|
||||
Asset
|
||||
assetFromJson(json::Value const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!v.isMember(jss::currency) && !v.isMember(jss::mpt_issuance_id))
|
||||
Throw<std::runtime_error>("assetFromJson must contain currency or mpt_issuance_id");
|
||||
|
||||
@@ -69,6 +77,7 @@ assetFromJson(json::Value const& v)
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, Asset const& x)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::visit([&]<ValidIssueType TIss>(TIss const& issue) { os << issue; }, x.value());
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/protocol/Book.h>
|
||||
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
@@ -10,18 +11,21 @@ namespace xrpl {
|
||||
bool
|
||||
isConsistent(Book const& book)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isConsistent(book.in) && isConsistent(book.out) && book.in != book.out;
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(Book const& book)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return to_string(book.in) + "->" + to_string(book.out);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, Book const& x)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
os << to_string(x);
|
||||
return os;
|
||||
}
|
||||
@@ -29,6 +33,7 @@ operator<<(std::ostream& os, Book const& x)
|
||||
Book
|
||||
reversed(Book const& book)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Book(book.out, book.in, book.domain);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/beast/core/SemanticVersion.h>
|
||||
#include <xrpl/git/Git.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/SystemParameters.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/preprocessor/stringize.hpp> // IWYU pragma: keep
|
||||
|
||||
@@ -34,6 +35,7 @@ char const* const versionString = "3.2.0-b0"
|
||||
std::string
|
||||
buildVersionString()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string version = versionString;
|
||||
|
||||
#if defined(DEBUG) || defined(SANITIZERS)
|
||||
@@ -67,6 +69,7 @@ buildVersionString()
|
||||
std::string const&
|
||||
getVersionString()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static std::string const kVALUE = [] {
|
||||
std::string const s = buildVersionString();
|
||||
|
||||
@@ -81,6 +84,7 @@ getVersionString()
|
||||
std::string const&
|
||||
getFullVersionString()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static std::string const kVALUE = systemName() + "-" + getVersionString();
|
||||
return kVALUE;
|
||||
}
|
||||
@@ -91,6 +95,7 @@ static constexpr std::uint64_t kIMPLEMENTATION_VERSION_IDENTIFIER_MASK = 0xFFFF'
|
||||
std::uint64_t
|
||||
encodeSoftwareVersion(std::string_view versionStr)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::uint64_t c = kIMPLEMENTATION_VERSION_IDENTIFIER;
|
||||
|
||||
beast::SemanticVersion v;
|
||||
@@ -155,6 +160,7 @@ encodeSoftwareVersion(std::string_view versionStr)
|
||||
std::uint64_t
|
||||
getEncodedVersion()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static std::uint64_t const kCOOKIE = {encodeSoftwareVersion(getVersionString())};
|
||||
return kCOOKIE;
|
||||
}
|
||||
@@ -162,6 +168,7 @@ getEncodedVersion()
|
||||
bool
|
||||
isXrpldVersion(std::uint64_t version)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return (version & kIMPLEMENTATION_VERSION_IDENTIFIER_MASK) ==
|
||||
kIMPLEMENTATION_VERSION_IDENTIFIER;
|
||||
}
|
||||
@@ -169,6 +176,7 @@ isXrpldVersion(std::uint64_t version)
|
||||
bool
|
||||
isNewerVersion(std::uint64_t version)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXrpldVersion(version))
|
||||
return version > getEncodedVersion();
|
||||
return false;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
@@ -164,6 +165,7 @@ constexpr ErrorInfo kUNKNOWN_ERROR;
|
||||
void
|
||||
injectError(ErrorCodeI code, json::Value& json)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ErrorInfo const& info(getErrorInfo(code));
|
||||
json[jss::error] = info.token;
|
||||
json[jss::error_code] = info.code;
|
||||
@@ -173,6 +175,7 @@ injectError(ErrorCodeI code, json::Value& json)
|
||||
void
|
||||
injectError(ErrorCodeI code, std::string const& message, json::Value& json)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
ErrorInfo const& info(getErrorInfo(code));
|
||||
json[jss::error] = info.token;
|
||||
json[jss::error_code] = info.code;
|
||||
@@ -182,6 +185,7 @@ injectError(ErrorCodeI code, std::string const& message, json::Value& json)
|
||||
ErrorInfo const&
|
||||
getErrorInfo(ErrorCodeI code)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (code <= RpcSuccess || code > RpcLast)
|
||||
return detail::kUNKNOWN_ERROR;
|
||||
return detail::kSORTED_ERROR_INFOS[code - 1];
|
||||
@@ -190,6 +194,7 @@ getErrorInfo(ErrorCodeI code)
|
||||
json::Value
|
||||
makeError(ErrorCodeI code)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::Value json;
|
||||
injectError(code, json);
|
||||
return json;
|
||||
@@ -198,6 +203,7 @@ makeError(ErrorCodeI code)
|
||||
json::Value
|
||||
makeError(ErrorCodeI code, std::string const& message)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::Value json;
|
||||
injectError(code, message, json);
|
||||
return json;
|
||||
@@ -206,12 +212,14 @@ makeError(ErrorCodeI code, std::string const& message)
|
||||
bool
|
||||
containsError(json::Value const& json)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return json.isObject() && json.isMember(jss::error);
|
||||
}
|
||||
|
||||
int
|
||||
errorCodeHttpStatus(ErrorCodeI code)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return getErrorInfo(code).http_status;
|
||||
}
|
||||
|
||||
@@ -220,6 +228,7 @@ errorCodeHttpStatus(ErrorCodeI code)
|
||||
std::string
|
||||
rpcErrorString(json::Value const& jv)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(RPC::containsError(jv), "xrpl::RPC::rpcErrorString : input contains an error");
|
||||
return jv[jss::error].asString() + jv[jss::error_message].asString();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/multi_index/hashed_index.hpp>
|
||||
@@ -26,6 +27,7 @@ inline std::size_t
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
hash_value(xrpl::uint256 const& feature)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::size_t seed = 0;
|
||||
using namespace boost;
|
||||
for (auto const& n : feature)
|
||||
@@ -118,6 +120,7 @@ class FeatureCollections
|
||||
Feature const&
|
||||
getByIndex(size_t i) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (i >= features_.size())
|
||||
logicError("Invalid FeatureBitset index");
|
||||
auto const& sequence = features_.get<Feature::ByIndex>();
|
||||
@@ -126,6 +129,7 @@ class FeatureCollections
|
||||
size_t
|
||||
getIndex(Feature const& feature) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& sequence = features_.get<Feature::ByIndex>();
|
||||
auto const itTo = sequence.iterator_to(feature);
|
||||
return itTo - sequence.begin();
|
||||
@@ -133,6 +137,7 @@ class FeatureCollections
|
||||
Feature const*
|
||||
getByFeature(uint256 const& feature) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& featureIndex = features_.get<Feature::ByFeature>();
|
||||
auto const featureIt = featureIndex.find(feature);
|
||||
return featureIt == featureIndex.end() ? nullptr : &*featureIt;
|
||||
@@ -140,6 +145,7 @@ class FeatureCollections
|
||||
Feature const*
|
||||
getByName(std::string const& name) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& nameIndex = features_.get<Feature::ByName>();
|
||||
auto const nameIt = nameIndex.find(name);
|
||||
return nameIt == nameIndex.end() ? nullptr : &*nameIt;
|
||||
@@ -171,6 +177,7 @@ public:
|
||||
std::map<std::string, AmendmentSupport> const&
|
||||
allAmendments() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return all_;
|
||||
}
|
||||
|
||||
@@ -180,6 +187,7 @@ public:
|
||||
std::map<std::string, VoteBehavior> const&
|
||||
supportedAmendments() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return supported_;
|
||||
}
|
||||
|
||||
@@ -187,6 +195,7 @@ public:
|
||||
std::size_t
|
||||
numDownVotedAmendments() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return downVotes_;
|
||||
}
|
||||
|
||||
@@ -194,6 +203,7 @@ public:
|
||||
std::size_t
|
||||
numUpVotedAmendments() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return upVotes_;
|
||||
}
|
||||
};
|
||||
@@ -202,12 +212,14 @@ public:
|
||||
|
||||
FeatureCollections::FeatureCollections()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
features_.reserve(xrpl::detail::kNUM_FEATURES);
|
||||
}
|
||||
|
||||
std::optional<uint256>
|
||||
FeatureCollections::getRegisteredFeature(std::string const& name) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
readOnly_.load(), "xrpl::FeatureCollections::getRegisteredFeature : startup completed");
|
||||
Feature const* feature = getByName(name);
|
||||
@@ -219,6 +231,7 @@ FeatureCollections::getRegisteredFeature(std::string const& name) const
|
||||
void
|
||||
check(bool condition, char const* logicErrorMessage)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!condition)
|
||||
logicError(logicErrorMessage);
|
||||
}
|
||||
@@ -226,6 +239,7 @@ check(bool condition, char const* logicErrorMessage)
|
||||
uint256
|
||||
FeatureCollections::registerFeature(std::string const& name, Supported support, VoteBehavior vote)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
check(!readOnly_, "Attempting to register a feature after startup.");
|
||||
check(
|
||||
support == Supported::Yes || vote == VoteBehavior::DefaultNo,
|
||||
@@ -275,6 +289,7 @@ FeatureCollections::registerFeature(std::string const& name, Supported support,
|
||||
bool
|
||||
FeatureCollections::registrationIsDone()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
readOnly_ = true;
|
||||
return true;
|
||||
}
|
||||
@@ -282,6 +297,7 @@ FeatureCollections::registrationIsDone()
|
||||
size_t
|
||||
FeatureCollections::featureToBitsetIndex(uint256 const& f) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
readOnly_.load(), "xrpl::FeatureCollections::featureToBitsetIndex : startup completed");
|
||||
|
||||
@@ -295,6 +311,7 @@ FeatureCollections::featureToBitsetIndex(uint256 const& f) const
|
||||
uint256 const&
|
||||
FeatureCollections::bitsetIndexToFeature(size_t i) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
readOnly_.load(), "xrpl::FeatureCollections::bitsetIndexToFeature : startup completed");
|
||||
Feature const& feature = getByIndex(i);
|
||||
@@ -304,6 +321,7 @@ FeatureCollections::bitsetIndexToFeature(size_t i) const
|
||||
std::string
|
||||
FeatureCollections::featureToName(uint256 const& f) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(readOnly_.load(), "xrpl::FeatureCollections::featureToName : startup completed");
|
||||
Feature const* feature = getByFeature(f);
|
||||
return (feature != nullptr) ? feature->name : to_string(f);
|
||||
@@ -317,6 +335,7 @@ FeatureCollections gFeatureCollections;
|
||||
std::map<std::string, AmendmentSupport> const&
|
||||
allAmendments()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.allAmendments();
|
||||
}
|
||||
|
||||
@@ -326,6 +345,7 @@ allAmendments()
|
||||
std::map<std::string, VoteBehavior> const&
|
||||
detail::supportedAmendments()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.supportedAmendments();
|
||||
}
|
||||
|
||||
@@ -333,6 +353,7 @@ detail::supportedAmendments()
|
||||
std::size_t
|
||||
detail::numDownVotedAmendments()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.numDownVotedAmendments();
|
||||
}
|
||||
|
||||
@@ -340,6 +361,7 @@ detail::numDownVotedAmendments()
|
||||
std::size_t
|
||||
detail::numUpVotedAmendments()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.numUpVotedAmendments();
|
||||
}
|
||||
|
||||
@@ -348,12 +370,14 @@ detail::numUpVotedAmendments()
|
||||
std::optional<uint256>
|
||||
getRegisteredFeature(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.getRegisteredFeature(name);
|
||||
}
|
||||
|
||||
uint256
|
||||
registerFeature(std::string const& name, Supported support, VoteBehavior vote)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.registerFeature(name, support, vote);
|
||||
}
|
||||
|
||||
@@ -362,6 +386,7 @@ registerFeature(std::string const& name, Supported support, VoteBehavior vote)
|
||||
uint256
|
||||
retireFeature(std::string const& name)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return registerFeature(name, Supported::Yes, VoteBehavior::Obsolete);
|
||||
}
|
||||
|
||||
@@ -369,24 +394,28 @@ retireFeature(std::string const& name)
|
||||
bool
|
||||
registrationIsDone()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.registrationIsDone();
|
||||
}
|
||||
|
||||
size_t
|
||||
featureToBitsetIndex(uint256 const& f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.featureToBitsetIndex(f);
|
||||
}
|
||||
|
||||
uint256
|
||||
bitsetIndexToFeature(size_t i)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.bitsetIndexToFeature(i);
|
||||
}
|
||||
|
||||
std::string
|
||||
featureToName(uint256 const& f)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return gFeatureCollections.featureToName(f);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -23,6 +24,7 @@ namespace {
|
||||
LocalValue<bool>&
|
||||
getStaticSTNumberSwitchover()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static LocalValue<bool> kR{true};
|
||||
return kR;
|
||||
}
|
||||
@@ -31,12 +33,14 @@ getStaticSTNumberSwitchover()
|
||||
bool
|
||||
getSTNumberSwitchover()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return *getStaticSTNumberSwitchover();
|
||||
}
|
||||
|
||||
void
|
||||
setSTNumberSwitchover(bool v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
*getStaticSTNumberSwitchover() = v;
|
||||
}
|
||||
|
||||
@@ -52,6 +56,7 @@ static int constexpr kMAX_EXPONENT = STAmount::kMAX_OFFSET;
|
||||
IOUAmount
|
||||
IOUAmount::fromNumber(Number const& number)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// Need to create a default IOUAmount and assign directly so it doesn't try
|
||||
// to normalize, which calls fromNumber
|
||||
IOUAmount result{};
|
||||
@@ -63,12 +68,14 @@ IOUAmount::fromNumber(Number const& number)
|
||||
IOUAmount
|
||||
IOUAmount::minPositiveAmount()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return IOUAmount(kMIN_MANTISSA, kMIN_EXPONENT);
|
||||
}
|
||||
|
||||
void
|
||||
IOUAmount::normalize()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (mantissa_ == 0)
|
||||
{
|
||||
*this = beast::kZERO;
|
||||
@@ -121,6 +128,7 @@ IOUAmount::normalize()
|
||||
|
||||
IOUAmount::IOUAmount(Number const& other) : IOUAmount(fromNumber(other))
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (exponent_ > kMAX_EXPONENT)
|
||||
Throw<std::overflow_error>("value overflow");
|
||||
if (exponent_ < kMIN_EXPONENT)
|
||||
@@ -130,6 +138,7 @@ IOUAmount::IOUAmount(Number const& other) : IOUAmount(fromNumber(other))
|
||||
IOUAmount&
|
||||
IOUAmount::operator+=(IOUAmount const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (other == beast::kZERO)
|
||||
return *this;
|
||||
|
||||
@@ -176,12 +185,14 @@ IOUAmount::operator+=(IOUAmount const& other)
|
||||
std::string
|
||||
to_string(IOUAmount const& amount)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return to_string(Number{amount});
|
||||
}
|
||||
|
||||
IOUAmount
|
||||
mulRatio(IOUAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
using namespace boost::multiprecision;
|
||||
|
||||
if (den == 0u)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/protocol/nftPageMask.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <boost/endian/conversion.hpp>
|
||||
|
||||
@@ -95,12 +96,14 @@ template <class... Args>
|
||||
static uint256
|
||||
indexHash(LedgerNameSpace space, Args const&... args)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return sha512Half(safeCast<std::uint16_t>(space), args...);
|
||||
}
|
||||
|
||||
uint256
|
||||
getBookBase(Book const& book)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(isConsistent(book), "xrpl::getBookBase : input is consistent");
|
||||
|
||||
auto getIndexHash = [&book]<typename... Args>(Args... args) {
|
||||
@@ -143,6 +146,7 @@ getBookBase(Book const& book)
|
||||
uint256
|
||||
getQualityNext(uint256 const& uBase)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static constexpr uint256 kNEXT_QUALITY(
|
||||
"0000000000000000000000000000000000000000000000010000000000000000");
|
||||
return uBase + kNEXT_QUALITY;
|
||||
@@ -151,6 +155,7 @@ getQualityNext(uint256 const& uBase)
|
||||
std::uint64_t
|
||||
getQuality(uint256 const& uBase)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// VFALCO [base_uint] This assumes a certain storage format
|
||||
return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
|
||||
}
|
||||
@@ -158,12 +163,14 @@ getQuality(uint256 const& uBase)
|
||||
uint256
|
||||
getTicketIndex(AccountID const& account, std::uint32_t ticketSeq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return indexHash(LedgerNameSpace::Ticket, account, ticketSeq);
|
||||
}
|
||||
|
||||
uint256
|
||||
getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(ticketSeq.isTicket(), "xrpl::getTicketIndex : valid input");
|
||||
return getTicketIndex(account, ticketSeq.value());
|
||||
}
|
||||
@@ -171,6 +178,7 @@ getTicketIndex(AccountID const& account, SeqProxy ticketSeq)
|
||||
MPTID
|
||||
makeMptID(std::uint32_t sequence, AccountID const& account)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
MPTID u;
|
||||
sequence = boost::endian::native_to_big(sequence);
|
||||
memcpy(u.data(), &sequence, sizeof(sequence));
|
||||
@@ -185,18 +193,21 @@ namespace keylet {
|
||||
Keylet
|
||||
account(AccountID const& id) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return Keylet{ltACCOUNT_ROOT, indexHash(LedgerNameSpace::Account, id)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
child(uint256 const& key) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltCHILD, key};
|
||||
}
|
||||
|
||||
Keylet const&
|
||||
skip() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static Keylet const kRET{ltLEDGER_HASHES, indexHash(LedgerNameSpace::SkipList)};
|
||||
return kRET;
|
||||
}
|
||||
@@ -204,6 +215,7 @@ skip() noexcept
|
||||
Keylet
|
||||
skip(LedgerIndex ledger) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {
|
||||
ltLEDGER_HASHES,
|
||||
indexHash(
|
||||
@@ -213,6 +225,7 @@ skip(LedgerIndex ledger) noexcept
|
||||
Keylet const&
|
||||
amendments() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static Keylet const kRET{ltAMENDMENTS, indexHash(LedgerNameSpace::Amendments)};
|
||||
return kRET;
|
||||
}
|
||||
@@ -220,6 +233,7 @@ amendments() noexcept
|
||||
Keylet const&
|
||||
fees() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static Keylet const kRET{ltFEE_SETTINGS, indexHash(LedgerNameSpace::FeeSettings)};
|
||||
return kRET;
|
||||
}
|
||||
@@ -227,6 +241,7 @@ fees() noexcept
|
||||
Keylet const&
|
||||
negativeUNL() noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static Keylet const kRET{ltNEGATIVE_UNL, indexHash(LedgerNameSpace::NegativeUnl)};
|
||||
return kRET;
|
||||
}
|
||||
@@ -234,12 +249,14 @@ negativeUNL() noexcept
|
||||
Keylet
|
||||
BookT::operator()(Book const& b) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDIR_NODE, getBookBase(b)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
line(AccountID const& id0, AccountID const& id1, Currency const& currency) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// There is code in TrustSet that calls us with id0 == id1, to allow users
|
||||
// to locate and delete such "weird" trustlines. If we remove that code, we
|
||||
// could enable this assert:
|
||||
@@ -263,12 +280,14 @@ line(AccountID const& id0, AccountID const& id1, Currency const& currency) noexc
|
||||
Keylet
|
||||
offer(AccountID const& id, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltOFFER, indexHash(LedgerNameSpace::Offer, id, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
quality(Keylet const& k, std::uint64_t q) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::quality : valid input type");
|
||||
|
||||
// Indexes are stored in big endian format: they print as hex as stored.
|
||||
@@ -287,6 +306,7 @@ quality(Keylet const& k, std::uint64_t q) noexcept
|
||||
Keylet
|
||||
NextT::operator()(Keylet const& k) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::next_t::operator() : valid input type");
|
||||
return {ltDIR_NODE, getQualityNext(k.key)};
|
||||
}
|
||||
@@ -294,12 +314,14 @@ NextT::operator()(Keylet const& k) const
|
||||
Keylet
|
||||
TicketT::operator()(AccountID const& id, std::uint32_t ticketSeq) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltTICKET, getTicketIndex(id, ticketSeq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
TicketT::operator()(AccountID const& id, SeqProxy ticketSeq) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltTICKET, getTicketIndex(id, ticketSeq)};
|
||||
}
|
||||
|
||||
@@ -309,24 +331,28 @@ TicketT::operator()(AccountID const& id, SeqProxy ticketSeq) const
|
||||
static Keylet
|
||||
signers(AccountID const& account, std::uint32_t page) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltSIGNER_LIST, indexHash(LedgerNameSpace::SignerList, account, page)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
signers(AccountID const& account) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return signers(account, 0);
|
||||
}
|
||||
|
||||
Keylet
|
||||
check(AccountID const& id, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltCHECK, indexHash(LedgerNameSpace::Check, id, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDEPOSIT_PREAUTH, indexHash(LedgerNameSpace::DepositPreauth, owner, preauthorized)};
|
||||
}
|
||||
|
||||
@@ -336,6 +362,7 @@ depositPreauth(
|
||||
AccountID const& owner,
|
||||
std::set<std::pair<AccountID, Slice>> const& authCreds) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<uint256> hashes;
|
||||
hashes.reserve(authCreds.size());
|
||||
for (auto const& o : authCreds)
|
||||
@@ -350,18 +377,21 @@ depositPreauth(
|
||||
Keylet
|
||||
unchecked(uint256 const& key) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltANY, key};
|
||||
}
|
||||
|
||||
Keylet
|
||||
ownerDir(AccountID const& id) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDIR_NODE, indexHash(LedgerNameSpace::OwnerDir, id)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
page(uint256 const& key, std::uint64_t index) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (index == 0)
|
||||
return {ltDIR_NODE, key};
|
||||
|
||||
@@ -371,18 +401,21 @@ page(uint256 const& key, std::uint64_t index) noexcept
|
||||
Keylet
|
||||
escrow(AccountID const& src, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltESCROW, indexHash(LedgerNameSpace::Escrow, src, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltPAYCHAN, indexHash(LedgerNameSpace::XRPPaymentChannel, src, dst, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
nftpageMin(AccountID const& owner)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::array<std::uint8_t, 32> buf{};
|
||||
std::memcpy(buf.data(), owner.data(), owner.size());
|
||||
return {ltNFTOKEN_PAGE, uint256{buf}};
|
||||
@@ -391,6 +424,7 @@ nftpageMin(AccountID const& owner)
|
||||
Keylet
|
||||
nftpageMax(AccountID const& owner)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
uint256 id = nft::kPAGE_MASK;
|
||||
std::memcpy(id.data(), owner.data(), owner.size());
|
||||
return {ltNFTOKEN_PAGE, id};
|
||||
@@ -399,6 +433,7 @@ nftpageMax(AccountID const& owner)
|
||||
Keylet
|
||||
nftpage(Keylet const& k, uint256 const& token)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(k.type == ltNFTOKEN_PAGE, "xrpl::keylet::nftpage : valid input type");
|
||||
return {ltNFTOKEN_PAGE, (k.key & ~nft::kPAGE_MASK) + (token & nft::kPAGE_MASK)};
|
||||
}
|
||||
@@ -406,24 +441,28 @@ nftpage(Keylet const& k, uint256 const& token)
|
||||
Keylet
|
||||
nftoffer(AccountID const& owner, std::uint32_t seq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NftokenOffer, owner, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
nftBuys(uint256 const& id) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDIR_NODE, indexHash(LedgerNameSpace::NftokenBuyOffers, id)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
nftSells(uint256 const& id) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDIR_NODE, indexHash(LedgerNameSpace::NftokenSellOffers, id)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
amm(Asset const& asset1, Asset const& asset2) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto const& [minA, maxA] = std::minmax(asset1, asset2);
|
||||
return std::visit(
|
||||
[]<ValidIssueType TIss1, ValidIssueType TIss2>(TIss1 const& issue1, TIss2 const& issue2) {
|
||||
@@ -458,18 +497,21 @@ amm(Asset const& asset1, Asset const& asset2) noexcept
|
||||
Keylet
|
||||
amm(uint256 const& id) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltAMM, id};
|
||||
}
|
||||
|
||||
Keylet
|
||||
delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDELEGATE, indexHash(LedgerNameSpace::Delegate, account, authorizedAccount)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// A door account can support multiple bridges. On the locking chain
|
||||
// there can only be one bridge per lockingChainCurrency. On the issuing
|
||||
// chain there can only be one bridge per issuingChainCurrency.
|
||||
@@ -480,6 +522,7 @@ bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType)
|
||||
Keylet
|
||||
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {
|
||||
ltXCHAIN_OWNED_CLAIM_ID,
|
||||
indexHash(
|
||||
@@ -494,6 +537,7 @@ xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq)
|
||||
Keylet
|
||||
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {
|
||||
ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
|
||||
indexHash(
|
||||
@@ -508,72 +552,84 @@ xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq)
|
||||
Keylet
|
||||
did(AccountID const& account) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltDID, indexHash(LedgerNameSpace::Did, account)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
oracle(AccountID const& account, std::uint32_t const& documentID) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltORACLE, indexHash(LedgerNameSpace::Oracle, account, documentID)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
mptIssuance(std::uint32_t seq, AccountID const& issuer) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return mptIssuance(makeMptID(seq, issuer));
|
||||
}
|
||||
|
||||
Keylet
|
||||
mptIssuance(MPTID const& issuanceID) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltMPTOKEN_ISSUANCE, indexHash(LedgerNameSpace::MPTokenIssuance, issuanceID)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return mptoken(mptIssuance(issuanceID).key, holder);
|
||||
}
|
||||
|
||||
Keylet
|
||||
mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltMPTOKEN, indexHash(LedgerNameSpace::MPToken, issuanceKey, holder)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
credential(AccountID const& subject, AccountID const& issuer, Slice const& credType) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltCREDENTIAL, indexHash(LedgerNameSpace::Credential, subject, issuer, credType)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
vault(AccountID const& owner, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return vault(indexHash(LedgerNameSpace::Vault, owner, seq));
|
||||
}
|
||||
|
||||
Keylet
|
||||
loanbroker(AccountID const& owner, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return loanbroker(indexHash(LedgerNameSpace::LoanBroker, owner, seq));
|
||||
}
|
||||
|
||||
Keylet
|
||||
loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return loan(indexHash(LedgerNameSpace::Loan, loanBrokerID, loanSeq));
|
||||
}
|
||||
|
||||
Keylet
|
||||
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltPERMISSIONED_DOMAIN, indexHash(LedgerNameSpace::PermissionedDomain, account, seq)};
|
||||
}
|
||||
|
||||
Keylet
|
||||
permissionedDomain(uint256 const& domainID) noexcept
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return {ltPERMISSIONED_DOMAIN, domainID};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/SOTemplate.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
InnerObjectFormats::InnerObjectFormats()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// inner objects with the default fields have to be
|
||||
// constructed with STObject::makeInnerObject()
|
||||
|
||||
@@ -165,6 +167,7 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
InnerObjectFormats const&
|
||||
InnerObjectFormats::getInstance()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static InnerObjectFormats const kINSTANCE;
|
||||
return kINSTANCE;
|
||||
}
|
||||
@@ -172,6 +175,7 @@ InnerObjectFormats::getInstance()
|
||||
SOTemplate const*
|
||||
InnerObjectFormats::findSOTemplateBySField(SField const& sField) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
auto itemPtr = findByType(sField.getCode());
|
||||
if (itemPtr != nullptr)
|
||||
return &(itemPtr->getSOTemplate());
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
@@ -16,6 +17,7 @@ namespace xrpl {
|
||||
std::string
|
||||
Issue::getText() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::string ret;
|
||||
|
||||
ret.reserve(64);
|
||||
@@ -45,6 +47,7 @@ Issue::getText() const
|
||||
void
|
||||
Issue::setJson(json::Value& jv) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
jv[jss::currency] = to_string(currency);
|
||||
if (!isXRP(currency))
|
||||
jv[jss::issuer] = toBase58(account);
|
||||
@@ -53,24 +56,28 @@ Issue::setJson(json::Value& jv) const
|
||||
bool
|
||||
Issue::native() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return *this == xrpIssue();
|
||||
}
|
||||
|
||||
bool
|
||||
Issue::integral() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return native();
|
||||
}
|
||||
|
||||
bool
|
||||
isConsistent(Issue const& ac)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return isXRP(ac.currency) == isXRP(ac.account);
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(Issue const& ac)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (isXRP(ac.account))
|
||||
return to_string(ac.currency);
|
||||
|
||||
@@ -80,6 +87,7 @@ to_string(Issue const& ac)
|
||||
json::Value
|
||||
toJson(Issue const& is)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::Value jv;
|
||||
is.setJson(jv);
|
||||
return jv;
|
||||
@@ -88,6 +96,7 @@ toJson(Issue const& is)
|
||||
Issue
|
||||
issueFromJson(json::Value const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!v.isObject())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
@@ -139,6 +148,7 @@ issueFromJson(json::Value const& v)
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, Issue const& x)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
os << to_string(x);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
bool
|
||||
Keylet::check(STLedgerEntry const& sle) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
XRPL_ASSERT(
|
||||
sle.getType() != ltANY && sle.getType() != ltCHILD,
|
||||
"xrpl::Keylet::check : valid input type");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/SOTemplate.h>
|
||||
#include <xrpl/protocol/jss.h> // IWYU pragma: keep
|
||||
@@ -11,6 +12,7 @@ namespace xrpl {
|
||||
std::vector<SOElement> const&
|
||||
LedgerFormats::getCommonFields()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static auto const kCOMMON_FIELDS = std::vector<SOElement>{
|
||||
{sfLedgerIndex, SoeOptional},
|
||||
{sfLedgerEntryType, SoeRequired},
|
||||
@@ -21,6 +23,7 @@ LedgerFormats::getCommonFields()
|
||||
|
||||
LedgerFormats::LedgerFormats()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
#pragma push_macro("UNWRAP")
|
||||
#undef UNWRAP
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
@@ -41,6 +44,7 @@ LedgerFormats::LedgerFormats()
|
||||
LedgerFormats const&
|
||||
LedgerFormats::getInstance()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
static LedgerFormats const kINSTANCE;
|
||||
return kINSTANCE;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -13,6 +14,7 @@ namespace xrpl {
|
||||
void
|
||||
addRaw(LedgerHeader const& info, Serializer& s, bool includeHash)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
s.add32(info.seq);
|
||||
s.add64(info.drops.drops());
|
||||
s.addBitString(info.parentHash);
|
||||
@@ -30,6 +32,7 @@ addRaw(LedgerHeader const& info, Serializer& s, bool includeHash)
|
||||
LedgerHeader
|
||||
deserializeHeader(Slice data, bool hasHash)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
SerialIter sit(data.data(), data.size());
|
||||
|
||||
LedgerHeader header;
|
||||
@@ -53,12 +56,14 @@ deserializeHeader(Slice data, bool hasHash)
|
||||
LedgerHeader
|
||||
deserializePrefixedHeader(Slice data, bool hasHash)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return deserializeHeader(data + 4, hasHash);
|
||||
}
|
||||
|
||||
uint256
|
||||
calculateLedgerHash(LedgerHeader const& info)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// VFALCO This has to match addRaw in View.h.
|
||||
return sha512Half(
|
||||
HashPrefix::LedgerMaster,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
MPTAmount&
|
||||
MPTAmount::operator+=(MPTAmount const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_ += other.value();
|
||||
return *this;
|
||||
}
|
||||
@@ -12,6 +14,7 @@ MPTAmount::operator+=(MPTAmount const& other)
|
||||
MPTAmount&
|
||||
MPTAmount::operator-=(MPTAmount const& other)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
value_ -= other.value();
|
||||
return *this;
|
||||
}
|
||||
@@ -19,30 +22,35 @@ MPTAmount::operator-=(MPTAmount const& other)
|
||||
MPTAmount
|
||||
MPTAmount::operator-() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return MPTAmount{-value_};
|
||||
}
|
||||
|
||||
bool
|
||||
MPTAmount::operator==(MPTAmount const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return value_ == other.value_;
|
||||
}
|
||||
|
||||
bool
|
||||
MPTAmount::operator==(value_type other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return value_ == other;
|
||||
}
|
||||
|
||||
bool
|
||||
MPTAmount::operator<(MPTAmount const& other) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return value_ < other.value_;
|
||||
}
|
||||
|
||||
MPTAmount
|
||||
MPTAmount::minPositiveAmount()
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return MPTAmount{1};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
@@ -28,6 +29,7 @@ MPTIssue::MPTIssue(std::uint32_t sequence, AccountID const& account)
|
||||
AccountID const&
|
||||
MPTIssue::getIssuer() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// MPTID is concatenation of sequence + account
|
||||
static_assert(sizeof(MPTID) == (sizeof(std::uint32_t) + sizeof(AccountID)));
|
||||
// copy from id skipping the sequence
|
||||
@@ -40,18 +42,21 @@ MPTIssue::getIssuer() const
|
||||
std::string
|
||||
MPTIssue::getText() const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return to_string(mptID_);
|
||||
}
|
||||
|
||||
void
|
||||
MPTIssue::setJson(json::Value& jv) const
|
||||
{
|
||||
TRACE_FUNC();
|
||||
jv[jss::mpt_issuance_id] = to_string(mptID_);
|
||||
}
|
||||
|
||||
json::Value
|
||||
toJson(MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
json::Value jv;
|
||||
mptIssue.setJson(jv);
|
||||
return jv;
|
||||
@@ -60,12 +65,14 @@ toJson(MPTIssue const& mptIssue)
|
||||
std::string
|
||||
to_string(MPTIssue const& mptIssue)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
return to_string(mptIssue.getMptID());
|
||||
}
|
||||
|
||||
MPTIssue
|
||||
mptIssueFromJson(json::Value const& v)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!v.isObject())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
@@ -97,6 +104,7 @@ mptIssueFromJson(json::Value const& v)
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, MPTIssue const& x)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
os << to_string(x);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -17,6 +18,7 @@ insertNFTSyntheticInJson(
|
||||
std::shared_ptr<STTx const> const& transaction,
|
||||
TxMeta const& transactionMeta)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
insertNFTokenID(response[jss::meta], transaction, transactionMeta);
|
||||
insertNFTokenOfferID(response[jss::meta], transaction, transactionMeta);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/basics/TraceLog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
@@ -23,6 +24,7 @@ namespace xrpl {
|
||||
bool
|
||||
canHaveNFTokenID(std::shared_ptr<STTx const> const& serializedTx, TxMeta const& transactionMeta)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!serializedTx)
|
||||
return false;
|
||||
|
||||
@@ -40,6 +42,7 @@ canHaveNFTokenID(std::shared_ptr<STTx const> const& serializedTx, TxMeta const&
|
||||
std::optional<uint256>
|
||||
getNFTokenIDFromPage(TxMeta const& transactionMeta)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
// The metadata does not make it obvious which NFT was added. To figure
|
||||
// that out we gather up all of the previous NFT IDs and all of the final
|
||||
// NFT IDs and compare them to find what changed.
|
||||
@@ -112,6 +115,7 @@ getNFTokenIDFromPage(TxMeta const& transactionMeta)
|
||||
std::vector<uint256>
|
||||
getNFTokenIDFromDeletedOffer(TxMeta const& transactionMeta)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
std::vector<uint256> tokenIDResult;
|
||||
for (STObject const& node : transactionMeta.getNodes())
|
||||
{
|
||||
@@ -138,6 +142,7 @@ insertNFTokenID(
|
||||
std::shared_ptr<STTx const> const& transaction,
|
||||
TxMeta const& transactionMeta)
|
||||
{
|
||||
TRACE_FUNC();
|
||||
if (!canHaveNFTokenID(transaction, transactionMeta))
|
||||
return;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user