mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
Compare commits
223 Commits
pratik/ran
...
ripple/was
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d582ae7990 | ||
|
|
0dbe51c740 | ||
|
|
63fff4b518 | ||
|
|
d85bf722ea | ||
|
|
b664989cfb | ||
|
|
e77934302a | ||
|
|
ef7aeca6bf | ||
|
|
eec1d29b92 | ||
|
|
971ba2281e | ||
|
|
90357eeae1 | ||
|
|
597202a6f0 | ||
|
|
1600b3e7f3 | ||
|
|
ecee732187 | ||
|
|
ce2586c039 | ||
|
|
8cc2169939 | ||
|
|
826f613ad8 | ||
|
|
1259c1d5ca | ||
|
|
d2641d85bd | ||
|
|
75f66bd9fe | ||
|
|
7cd71cb659 | ||
|
|
9917f96166 | ||
|
|
e1cc82587b | ||
|
|
2cc9439fde | ||
|
|
52af9582e2 | ||
|
|
46e88dc732 | ||
|
|
bc24f2e211 | ||
|
|
7a7c993b15 | ||
|
|
9733ca8f91 | ||
|
|
18d5e3e226 | ||
|
|
b30b4e1d65 | ||
|
|
d435893602 | ||
|
|
00b0cf50f6 | ||
|
|
7ef256499c | ||
|
|
1338062be7 | ||
|
|
4fc1778ec8 | ||
|
|
65322d9e78 | ||
|
|
c5598a4284 | ||
|
|
0deb6bcadf | ||
|
|
9b013b559b | ||
|
|
1d4a3c00b8 | ||
|
|
4b34102e8e | ||
|
|
d006433579 | ||
|
|
a7ab8ee923 | ||
|
|
e0073a4402 | ||
|
|
2930ef217f | ||
|
|
9dbb301699 | ||
|
|
531e8b6ebd | ||
|
|
90397e1a52 | ||
|
|
888ca2e6d9 | ||
|
|
b6514b680f | ||
|
|
913e4b919e | ||
|
|
196e6a1b27 | ||
|
|
27468ddbcf | ||
|
|
bce5d91e45 | ||
|
|
654338fa66 | ||
|
|
9c25d18851 | ||
|
|
3a825a41e1 | ||
|
|
a9ebf786c6 | ||
|
|
5afe8cc321 | ||
|
|
bc5ec3c962 | ||
|
|
1775251e90 | ||
|
|
61bcb7621f | ||
|
|
a3f71b1774 | ||
|
|
4df7d1a4bb | ||
|
|
125df7a425 | ||
|
|
b08bcf5d21 | ||
|
|
dc413aef0c | ||
|
|
77dfd56ace | ||
|
|
953b9a3500 | ||
|
|
1d9ec84350 | ||
|
|
0392846a17 | ||
|
|
1b4a564369 | ||
|
|
fd524c4be9 | ||
|
|
495dda7f58 | ||
|
|
9c3c0280b1 | ||
|
|
f73d8a6cf2 | ||
|
|
6728ab52b7 | ||
|
|
77673663ca | ||
|
|
c1381f8ddd | ||
|
|
bd16f7989d | ||
|
|
65f9cf80c0 | ||
|
|
de55a5ebfc | ||
|
|
2ec4a1114e | ||
|
|
ba03a8a9d2 | ||
|
|
7c8279ec83 | ||
|
|
0418ffb26a | ||
|
|
b2627039f6 | ||
|
|
8f97ec3bde | ||
|
|
e85e7b1b1a | ||
|
|
803a344c65 | ||
|
|
4eb34f381a | ||
|
|
72fffb6e51 | ||
|
|
f7ee580f01 | ||
|
|
122d405750 | ||
|
|
c1c1b4ea67 | ||
|
|
977caea0a5 | ||
|
|
d7ed6d6512 | ||
|
|
f1f2e2629f | ||
|
|
917c610f96 | ||
|
|
317e533d81 | ||
|
|
4160677878 | ||
|
|
df98db1452 | ||
|
|
673476ef1b | ||
|
|
8bc6f9cd70 | ||
|
|
ba5debfecd | ||
|
|
f4a27c9b6d | ||
|
|
fd1cb318e3 | ||
|
|
8c3544a58c | ||
|
|
ed5139d4e3 | ||
|
|
42494dd4cf | ||
|
|
ce84cc8b44 | ||
|
|
9a9a7aab01 | ||
|
|
209a1a6ffa | ||
|
|
fc35a9f9c8 | ||
|
|
c5e50aa221 | ||
|
|
074b1f00d5 | ||
|
|
7a9d245950 | ||
|
|
1809fe07f2 | ||
|
|
409c67494a | ||
|
|
c626b6403a | ||
|
|
81cbc91927 | ||
|
|
1c812a6c4d | ||
|
|
0724927799 | ||
|
|
d83ec96848 | ||
|
|
375dd50b35 | ||
|
|
419d53ec4c | ||
|
|
d4d70d5675 | ||
|
|
6ab15f8377 | ||
|
|
91f3d51f3d | ||
|
|
9ed60b45f8 | ||
|
|
d5c53dcfd2 | ||
|
|
e94321fb41 | ||
|
|
bbc28b3b1c | ||
|
|
843e981c8a | ||
|
|
5aab274b7a | ||
|
|
2c30e41191 | ||
|
|
8ea5106b0b | ||
|
|
f57f67a8ae | ||
|
|
a98269f049 | ||
|
|
b66bc47ca9 | ||
|
|
0e9c7458bb | ||
|
|
1d89940653 | ||
|
|
1a1a6806ec | ||
|
|
1977df9c2e | ||
|
|
6c95548df5 | ||
|
|
69ab39d658 | ||
|
|
b9eb66eecc | ||
|
|
881087dd3d | ||
|
|
90e0bbd0fc | ||
|
|
b57df290de | ||
|
|
8a403f1241 | ||
|
|
6d2640871d | ||
|
|
c145598ff9 | ||
|
|
50e5608d86 | ||
|
|
7a7b96107c | ||
|
|
500bb68831 | ||
|
|
53eb0f60bc | ||
|
|
41205ae928 | ||
|
|
c33b0ae463 | ||
|
|
16087c9680 | ||
|
|
56bc6d58f6 | ||
|
|
ef5d335e09 | ||
|
|
25c3060fef | ||
|
|
ce9f0b38a4 | ||
|
|
35f7cbf772 | ||
|
|
0db564d261 | ||
|
|
427b7ea104 | ||
|
|
7bf6878b4b | ||
|
|
0bc1a115ff | ||
|
|
334bcfa5ef | ||
|
|
106dea4559 | ||
|
|
3ffdcf8114 | ||
|
|
4021a7eb28 | ||
|
|
0690fda0f1 | ||
|
|
d0cc48c6d3 | ||
|
|
d66e3c949e | ||
|
|
0c65a386b5 | ||
|
|
29f5430881 | ||
|
|
101f285bcd | ||
|
|
286dc6322b | ||
|
|
c9346cd40d | ||
|
|
1c5683ec78 | ||
|
|
9bee155d59 | ||
|
|
f34b05f4de | ||
|
|
97ce25f4ce | ||
|
|
9e14c14a26 | ||
|
|
c507880d8f | ||
|
|
3f8328bbf8 | ||
|
|
c10a5f9ef6 | ||
|
|
3c141de695 | ||
|
|
da2b9455f2 | ||
|
|
cb622488c0 | ||
|
|
32f971fec6 | ||
|
|
8dea76baa4 | ||
|
|
299fbe04c4 | ||
|
|
57fc1df7d7 | ||
|
|
eaba76f9e6 | ||
|
|
cb702cc238 | ||
|
|
b69b4a0a4a | ||
|
|
50d6072a73 | ||
|
|
d24cd50e61 | ||
|
|
9f5875158c | ||
|
|
c3dc33c861 | ||
|
|
6be8f2124c | ||
|
|
edfed06001 | ||
|
|
1c646dba91 | ||
|
|
6781068058 | ||
|
|
cfe57c1dfe | ||
|
|
c34d09a971 | ||
|
|
ebd90c4742 | ||
|
|
ba52d34828 | ||
|
|
1b6312afb3 | ||
|
|
bf32dc2e72 | ||
|
|
a15d65f7a2 | ||
|
|
2de8488855 | ||
|
|
129aa4bfaa | ||
|
|
b1d70db63b | ||
|
|
f03c3aafe4 | ||
|
|
51a9f106d1 | ||
|
|
bfc048e3fe | ||
|
|
83418644f7 | ||
|
|
dbc9dd5bfc | ||
|
|
45ab15d4b5 |
@@ -191,14 +191,11 @@ CheckOptions:
|
||||
readability-identifier-naming.ParameterCase: camelBack
|
||||
readability-identifier-naming.FunctionCase: camelBack
|
||||
readability-identifier-naming.MemberCase: camelBack
|
||||
readability-identifier-naming.PrivateMemberCase: camelBack
|
||||
readability-identifier-naming.PrivateMemberSuffix: _
|
||||
readability-identifier-naming.ProtectedMemberCase: camelBack
|
||||
readability-identifier-naming.ProtectedMemberSuffix: _
|
||||
readability-identifier-naming.PublicMemberCase: camelBack
|
||||
readability-identifier-naming.PublicMemberSuffix: ""
|
||||
readability-identifier-naming.GlobalFunctionIgnoredRegexp: "^(to_string|hash_append|tuple_hash)$"
|
||||
|
||||
HeaderFilterRegex: '^.*/(tests?|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
|
||||
HeaderFilterRegex: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
|
||||
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
|
||||
WarningsAsErrors: "*"
|
||||
|
||||
18
.github/actions/build-deps/action.yml
vendored
18
.github/actions/build-deps/action.yml
vendored
@@ -37,12 +37,12 @@ runs:
|
||||
run: |
|
||||
echo 'Installing dependencies.'
|
||||
conan install \
|
||||
--profile ci \
|
||||
--build="${BUILD_OPTION}" \
|
||||
--options:host='&:tests=True' \
|
||||
--options:host='&:xrpld=True' \
|
||||
--settings:all build_type="${BUILD_TYPE}" \
|
||||
--conf:all tools.build:jobs=${BUILD_NPROC} \
|
||||
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
|
||||
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
|
||||
.
|
||||
--profile ci \
|
||||
--build="${BUILD_OPTION}" \
|
||||
--options:host='&:tests=True' \
|
||||
--options:host='&:xrpld=True' \
|
||||
--settings:all build_type="${BUILD_TYPE}" \
|
||||
--conf:all tools.build:jobs=${BUILD_NPROC} \
|
||||
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
|
||||
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
|
||||
.
|
||||
|
||||
10
.github/actions/generate-version/action.yml
vendored
10
.github/actions/generate-version/action.yml
vendored
@@ -15,7 +15,7 @@ runs:
|
||||
shell: bash
|
||||
env:
|
||||
VERSION: ${{ github.ref_name }}
|
||||
run: echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
|
||||
run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
|
||||
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
|
||||
@@ -28,17 +28,17 @@ runs:
|
||||
echo 'Extracting version from BuildInfo.cpp.'
|
||||
VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')"
|
||||
if [[ -z "${VERSION}" ]]; then
|
||||
echo 'Unable to extract version from BuildInfo.cpp.'
|
||||
exit 1
|
||||
echo 'Unable to extract version from BuildInfo.cpp.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'Appending shortened commit hash to version.'
|
||||
SHA='${{ github.sha }}'
|
||||
VERSION="${VERSION}+${SHA:0:7}"
|
||||
|
||||
echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
|
||||
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Output version
|
||||
id: version
|
||||
shell: bash
|
||||
run: echo "version=${VERSION}" >>"${GITHUB_OUTPUT}"
|
||||
run: echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
403
.github/scripts/format-inline-bash.py
vendored
403
.github/scripts/format-inline-bash.py
vendored
@@ -1,403 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Format embedded shell snippets using the shfmt hook configured in
|
||||
.pre-commit-config.yaml.
|
||||
|
||||
Two shapes are recognised:
|
||||
|
||||
* YAML workflow/action files: literal block-scalar runs (`run: |`) and
|
||||
single-line runs (`run: some command`). A single-line run is upgraded to
|
||||
a `run: |` block scalar if shfmt's output spans multiple lines.
|
||||
|
||||
* Markdown files: ``` ```bash ``` fenced code blocks.
|
||||
|
||||
Any block that shfmt cannot parse is skipped with a warning on stderr, so
|
||||
the file is left untouched and surrounding blocks still get formatted.
|
||||
|
||||
For each occurrence the body is dedented, written to a temp .sh file,
|
||||
formatted via `pre-commit run shfmt --files <temp>` (falling back to
|
||||
`prek`), then re-indented and written back in place.
|
||||
|
||||
When invoked without arguments, every .yml/.yaml under .github/ plus every
|
||||
.md file in the repo is scanned. When invoked with file arguments (the
|
||||
pre-commit case), only those files are processed.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
|
||||
_HOOK_RUNNER = next((cmd for cmd in ("pre-commit", "prek") if shutil.which(cmd)), None)
|
||||
if _HOOK_RUNNER is None:
|
||||
sys.exit("error: neither `pre-commit` nor `prek` found on PATH")
|
||||
|
||||
RUN_BLOCK_RE = re.compile(r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]*\|[+-]?[ \t]*$")
|
||||
RUN_INLINE_RE = re.compile(
|
||||
r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]+" r"(?P<value>(?!\|[+-]?[ \t]*$)\S.*?)[ \t]*$"
|
||||
)
|
||||
MD_BASH_OPEN_RE = re.compile(r"^(?P<indent>[ ]{0,3})`{3}bash[ \t]*$")
|
||||
MD_FENCE_CLOSE_RE = re.compile(r"^[ ]{0,3}`{3,}[ \t]*$")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BlockRun:
|
||||
"""A `run: |` block scalar; `body_start:body_end` slices into `lines`."""
|
||||
|
||||
body_start: int
|
||||
body_end: int
|
||||
body_indent: int
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class InlineRun:
|
||||
"""A single-line `run: value` at `line_idx`."""
|
||||
|
||||
line_idx: int
|
||||
prefix: str
|
||||
value: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MdBashBlock:
|
||||
"""A markdown ``` ```bash ``` fenced code block.
|
||||
|
||||
`body_start:body_end` slices into the file's lines; `open_line_idx`
|
||||
points at the opening fence line.
|
||||
"""
|
||||
|
||||
open_line_idx: int
|
||||
body_start: int
|
||||
body_end: int
|
||||
body_indent: int
|
||||
|
||||
|
||||
RunItem = Union[BlockRun, InlineRun]
|
||||
|
||||
|
||||
def _scan_block_body(
|
||||
lines: list[str], body_start: int, run_col: int
|
||||
) -> tuple[int | None, int]:
|
||||
"""Locate the body of a `run: |` block scalar starting at `body_start`.
|
||||
|
||||
Returns `(body_indent, scan_end)`. `scan_end` is the line index where the
|
||||
outer scanner should resume. `body_indent` is `None` when no body is
|
||||
present (the scalar is empty, or the next non-blank line has indent
|
||||
`<= run_col`).
|
||||
"""
|
||||
body_indent: int | None = None
|
||||
scan_end = len(lines)
|
||||
for idx in range(body_start, len(lines)):
|
||||
line = lines[idx]
|
||||
if line.strip() == "":
|
||||
continue
|
||||
indent = len(line) - len(line.lstrip(" "))
|
||||
if body_indent is None:
|
||||
if indent > run_col:
|
||||
body_indent = indent
|
||||
else:
|
||||
scan_end = idx
|
||||
break
|
||||
elif indent < body_indent:
|
||||
scan_end = idx
|
||||
break
|
||||
if body_indent is not None:
|
||||
while scan_end > body_start and lines[scan_end - 1].strip() == "":
|
||||
scan_end -= 1
|
||||
if scan_end <= body_start:
|
||||
body_indent = None
|
||||
return body_indent, scan_end
|
||||
|
||||
|
||||
def find_run_blocks(lines: list[str]) -> list[RunItem]:
|
||||
"""Return run items in document order."""
|
||||
items: list[RunItem] = []
|
||||
line_idx = 0
|
||||
while line_idx < len(lines):
|
||||
line = lines[line_idx]
|
||||
if block_match := RUN_BLOCK_RE.match(line):
|
||||
run_col = len(block_match.group("prefix"))
|
||||
body_start = line_idx + 1
|
||||
body_indent, scan_end = _scan_block_body(lines, body_start, run_col)
|
||||
if body_indent is not None:
|
||||
items.append(
|
||||
BlockRun(
|
||||
body_start=body_start,
|
||||
body_end=scan_end,
|
||||
body_indent=body_indent,
|
||||
)
|
||||
)
|
||||
line_idx = scan_end
|
||||
continue
|
||||
if inline_match := RUN_INLINE_RE.match(line):
|
||||
items.append(
|
||||
InlineRun(
|
||||
line_idx=line_idx,
|
||||
prefix=inline_match.group("prefix"),
|
||||
value=inline_match.group("value"),
|
||||
)
|
||||
)
|
||||
line_idx += 1
|
||||
return items
|
||||
|
||||
|
||||
def find_md_bash_blocks(lines: list[str]) -> list[MdBashBlock]:
|
||||
"""Return ``` ```bash ``` fenced code blocks in document order."""
|
||||
blocks: list[MdBashBlock] = []
|
||||
line_idx = 0
|
||||
while line_idx < len(lines):
|
||||
open_match = MD_BASH_OPEN_RE.match(lines[line_idx])
|
||||
if not open_match:
|
||||
line_idx += 1
|
||||
continue
|
||||
body_start = line_idx + 1
|
||||
close_idx = next(
|
||||
(
|
||||
j
|
||||
for j in range(body_start, len(lines))
|
||||
if MD_FENCE_CLOSE_RE.match(lines[j])
|
||||
),
|
||||
None,
|
||||
)
|
||||
if close_idx is None:
|
||||
line_idx = body_start
|
||||
continue
|
||||
body = lines[body_start:close_idx]
|
||||
non_blank = [b for b in body if b.strip()]
|
||||
body_indent = (
|
||||
min(len(b) - len(b.lstrip(" ")) for b in non_blank)
|
||||
if non_blank
|
||||
else len(open_match.group("indent"))
|
||||
)
|
||||
blocks.append(
|
||||
MdBashBlock(
|
||||
open_line_idx=line_idx,
|
||||
body_start=body_start,
|
||||
body_end=close_idx,
|
||||
body_indent=body_indent,
|
||||
)
|
||||
)
|
||||
line_idx = close_idx + 1
|
||||
return blocks
|
||||
|
||||
|
||||
def dedent(lines: list[str], n: int) -> list[str]:
|
||||
pad = " " * n
|
||||
return [
|
||||
(
|
||||
""
|
||||
if line.strip() == ""
|
||||
else (line[n:] if line.startswith(pad) else line.lstrip(" "))
|
||||
)
|
||||
for line in lines
|
||||
]
|
||||
|
||||
|
||||
def reindent(lines: list[str], n: int) -> list[str]:
|
||||
pad = " " * n
|
||||
return [pad + line if line else "" for line in lines]
|
||||
|
||||
|
||||
_SHFMT_ERR_RE = re.compile(r"\.sh:\d+:\d+:\s")
|
||||
_GHA_EXPR_RE = re.compile(r"\$\{\{.*?\}\}", re.DOTALL)
|
||||
_GHA_PLACEHOLDER_RE = re.compile(r"__GHA_EXPR_(\d+)__")
|
||||
|
||||
|
||||
def _encode_gha_exprs(text: str) -> tuple[str, list[str]]:
|
||||
"""Replace `${{ ... }}` expressions with bash-safe placeholder identifiers."""
|
||||
exprs: list[str] = []
|
||||
|
||||
def repl(match: re.Match[str]) -> str:
|
||||
exprs.append(match.group(0))
|
||||
return f"__GHA_EXPR_{len(exprs) - 1}__"
|
||||
|
||||
return _GHA_EXPR_RE.sub(repl, text), exprs
|
||||
|
||||
|
||||
def _decode_gha_exprs(text: str, exprs: list[str]) -> str:
|
||||
"""Restore `${{ ... }}` expressions from placeholder identifiers."""
|
||||
return _GHA_PLACEHOLDER_RE.sub(lambda m: exprs[int(m.group(1))], text)
|
||||
|
||||
|
||||
def shfmt_via_hook(tmp_path: Path) -> tuple[bool, str]:
|
||||
# `${{ ... }}` is not valid shell, so swap it for a placeholder identifier
|
||||
# that shfmt can parse, then restore it after formatting.
|
||||
encoded, exprs = _encode_gha_exprs(tmp_path.read_text())
|
||||
if exprs:
|
||||
tmp_path.write_text(encoded)
|
||||
res = subprocess.run(
|
||||
[_HOOK_RUNNER, "run", "shfmt", "--files", str(tmp_path)],
|
||||
cwd=REPO,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
output = res.stdout + res.stderr
|
||||
# shfmt emits parse errors as "<path>:<line>:<col>: <message>".
|
||||
parse_err = bool(_SHFMT_ERR_RE.search(output))
|
||||
# A non-zero exit that is neither a parse error nor pre-commit's "I had
|
||||
# to modify files" signal means the hook itself failed to run (missing
|
||||
# binary, install failure, bad config, ...). Surface that loudly rather
|
||||
# than silently treating it as a no-op.
|
||||
if (
|
||||
res.returncode != 0
|
||||
and not parse_err
|
||||
and "files were modified by this hook" not in output
|
||||
):
|
||||
sys.exit(
|
||||
f"error: `{_HOOK_RUNNER} run shfmt` failed with exit {res.returncode}:\n{output}"
|
||||
)
|
||||
if exprs and not parse_err:
|
||||
tmp_path.write_text(_decode_gha_exprs(tmp_path.read_text(), exprs))
|
||||
return not parse_err, output
|
||||
|
||||
|
||||
def _skip(path: Path, where: int, kind: str, output: str) -> None:
|
||||
print(
|
||||
f" shfmt could not parse {kind} at {path}:{where + 1} — skipped",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(f" {output.strip()}", file=sys.stderr)
|
||||
|
||||
|
||||
def process_yaml_file(path: Path, tmp_path: Path) -> int:
|
||||
text = path.read_text()
|
||||
had_nl = text.endswith("\n")
|
||||
lines = text.split("\n")
|
||||
if had_nl:
|
||||
lines = lines[:-1]
|
||||
items = find_run_blocks(lines)
|
||||
if not items:
|
||||
return 0
|
||||
changed = 0
|
||||
# Process in reverse so earlier indices remain valid as we splice.
|
||||
for item in reversed(items):
|
||||
if isinstance(item, BlockRun):
|
||||
body = lines[item.body_start : item.body_end]
|
||||
tmp_path.write_text("\n".join(dedent(body, item.body_indent)) + "\n")
|
||||
ok, output = shfmt_via_hook(tmp_path)
|
||||
if not ok:
|
||||
_skip(path, item.body_start, "block", output)
|
||||
continue
|
||||
formatted = tmp_path.read_text().rstrip("\n")
|
||||
new_body = reindent(formatted.split("\n"), item.body_indent)
|
||||
if new_body != body:
|
||||
lines[item.body_start : item.body_end] = new_body
|
||||
changed += 1
|
||||
else:
|
||||
tmp_path.write_text(item.value + "\n")
|
||||
ok, output = shfmt_via_hook(tmp_path)
|
||||
if not ok:
|
||||
_skip(path, item.line_idx, "inline run", output)
|
||||
continue
|
||||
formatted = tmp_path.read_text().rstrip("\n")
|
||||
if formatted == item.value:
|
||||
continue
|
||||
formatted_lines = formatted.split("\n")
|
||||
if len(formatted_lines) == 1:
|
||||
lines[item.line_idx] = f"{item.prefix}run: {formatted}"
|
||||
else:
|
||||
body_indent = len(item.prefix) + 2
|
||||
lines[item.line_idx : item.line_idx + 1] = [
|
||||
f"{item.prefix}run: |",
|
||||
*reindent(formatted_lines, body_indent),
|
||||
]
|
||||
changed += 1
|
||||
new_text = "\n".join(lines) + ("\n" if had_nl else "")
|
||||
if new_text != text:
|
||||
path.write_text(new_text)
|
||||
return changed
|
||||
|
||||
|
||||
def process_md_file(path: Path, tmp_path: Path) -> int:
|
||||
text = path.read_text()
|
||||
had_nl = text.endswith("\n")
|
||||
lines = text.split("\n")
|
||||
if had_nl:
|
||||
lines = lines[:-1]
|
||||
blocks = find_md_bash_blocks(lines)
|
||||
if not blocks:
|
||||
return 0
|
||||
changed = 0
|
||||
for block in reversed(blocks):
|
||||
body = lines[block.body_start : block.body_end]
|
||||
tmp_path.write_text("\n".join(dedent(body, block.body_indent)) + "\n")
|
||||
ok, output = shfmt_via_hook(tmp_path)
|
||||
if not ok:
|
||||
_skip(path, block.open_line_idx, "```bash block", output)
|
||||
continue
|
||||
formatted = tmp_path.read_text().rstrip("\n")
|
||||
formatted_lines = formatted.split("\n") if formatted else []
|
||||
new_body = reindent(formatted_lines, block.body_indent)
|
||||
if new_body != body:
|
||||
lines[block.body_start : block.body_end] = new_body
|
||||
changed += 1
|
||||
new_text = "\n".join(lines) + ("\n" if had_nl else "")
|
||||
if new_text != text:
|
||||
path.write_text(new_text)
|
||||
return changed
|
||||
|
||||
|
||||
def process_file(path: Path, tmp_path: Path) -> int:
|
||||
if path.suffix in (".yml", ".yaml"):
|
||||
return process_yaml_file(path, tmp_path)
|
||||
if path.suffix == ".md":
|
||||
return process_md_file(path, tmp_path)
|
||||
return 0
|
||||
|
||||
|
||||
def gather_files(argv: list[str]) -> list[Path]:
|
||||
"""Return YAML workflow/action files and markdown files that we should
|
||||
process — either the paths in `argv` or, when `argv` is empty, every
|
||||
such file in the repo (skipping `external/`)."""
|
||||
if argv:
|
||||
candidates: list[Path] = [
|
||||
(REPO / a).resolve() if not Path(a).is_absolute() else Path(a) for a in argv
|
||||
]
|
||||
else:
|
||||
gh = REPO / ".github"
|
||||
candidates = [
|
||||
*gh.rglob("*.yml"),
|
||||
*gh.rglob("*.yaml"),
|
||||
*(
|
||||
p
|
||||
for p in REPO.rglob("*.md")
|
||||
if "external" not in p.relative_to(REPO).parts
|
||||
),
|
||||
]
|
||||
return sorted(
|
||||
p
|
||||
for p in candidates
|
||||
if p.exists()
|
||||
and (
|
||||
(p.suffix in (".yml", ".yaml") and ".github" in p.parts)
|
||||
or p.suffix == ".md"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
files = gather_files(argv)
|
||||
if not files:
|
||||
return 0
|
||||
with tempfile.TemporaryDirectory(prefix="format-inline-bash-") as tmpdir:
|
||||
tmp_path = Path(tmpdir) / "shfmt.sh"
|
||||
total = 0
|
||||
for f in files:
|
||||
n = process_file(f, tmp_path)
|
||||
if n:
|
||||
print(f"{f.relative_to(REPO)}: reformatted {n} block(s)")
|
||||
total += n
|
||||
return 1 if total else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
0
.github/scripts/levelization/generate.py
vendored
Executable file → Normal file
0
.github/scripts/levelization/generate.py
vendored
Executable file → Normal file
2
.github/scripts/rename/binary.sh
vendored
2
.github/scripts/rename/binary.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
12
.github/scripts/rename/cmake.sh
vendored
12
.github/scripts/rename/cmake.sh
vendored
@@ -8,12 +8,12 @@ set -e
|
||||
SED_COMMAND=sed
|
||||
HEAD_COMMAND=head
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
SED_COMMAND=gsed
|
||||
if ! command -v ghead &>/dev/null; then
|
||||
if ! command -v ghead &> /dev/null; then
|
||||
echo "Error: ghead is not installed. Please install it using 'brew install coreutils'."
|
||||
exit 1
|
||||
fi
|
||||
@@ -74,10 +74,10 @@ if grep -q '"xrpld"' cmake/XrplCore.cmake; then
|
||||
# The script has been rerun, so just restore the name of the binary.
|
||||
${SED_COMMAND} -i 's/"xrpld"/"rippled"/' cmake/XrplCore.cmake
|
||||
elif ! grep -q '"rippled"' cmake/XrplCore.cmake; then
|
||||
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake >cmake.tmp
|
||||
echo ' # For the time being, we will keep the name of the binary as it was.' >>cmake.tmp
|
||||
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >>cmake.tmp
|
||||
tail -1 cmake/XrplCore.cmake >>cmake.tmp
|
||||
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake > cmake.tmp
|
||||
echo ' # For the time being, we will keep the name of the binary as it was.' >> cmake.tmp
|
||||
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >> cmake.tmp
|
||||
tail -1 cmake/XrplCore.cmake >> cmake.tmp
|
||||
mv cmake.tmp cmake/XrplCore.cmake
|
||||
fi
|
||||
|
||||
|
||||
2
.github/scripts/rename/config.sh
vendored
2
.github/scripts/rename/config.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
24
.github/scripts/rename/copyright.sh
vendored
24
.github/scripts/rename/copyright.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
@@ -62,37 +62,37 @@ done
|
||||
# restoring the verbiage that is already present in LICENSE.md. Ensure that if
|
||||
# the script is run multiple times, duplicate notices are not added.
|
||||
if ! grep -q 'Raw Material Software' include/xrpl/beast/core/CurrentThreadName.h; then
|
||||
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" >include/xrpl/beast/core/CurrentThreadName.h
|
||||
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" > include/xrpl/beast/core/CurrentThreadName.h
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/test/app/NetworkID_test.cpp; then
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" >src/test/app/NetworkID_test.cpp
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" > src/test/app/NetworkID_test.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/test/app/tx/apply_test.cpp; then
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" >src/test/app/tx/apply_test.cpp
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" > src/test/app/tx/apply_test.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/test/rpc/ManifestRPC_test.cpp; then
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" >src/test/rpc/ManifestRPC_test.cpp
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" > src/test/rpc/ManifestRPC_test.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" >src/test/rpc/ValidatorInfo_test.cpp
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/server_info/Manifest.cpp; then
|
||||
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" >src/xrpld/rpc/handlers/server_info/Manifest.cpp
|
||||
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp; then
|
||||
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" >src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
|
||||
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" >include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/spinlock.h; then
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" >include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Bougalis' include/xrpl/basics/tagged_integer.h; then
|
||||
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" >include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
|
||||
fi
|
||||
if ! grep -q 'Ritchford' include/xrpl/beast/utility/Zero.h; then
|
||||
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" >include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
|
||||
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
|
||||
fi
|
||||
|
||||
# Restore newlines and tabs in string literals in the affected file.
|
||||
|
||||
2
.github/scripts/rename/definitions.sh
vendored
2
.github/scripts/rename/definitions.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
2
.github/scripts/rename/docs.sh
vendored
2
.github/scripts/rename/docs.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
2
.github/scripts/rename/namespace.sh
vendored
2
.github/scripts/rename/namespace.sh
vendored
@@ -6,7 +6,7 @@ set -e
|
||||
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
|
||||
SED_COMMAND=sed
|
||||
if [[ "${OSTYPE}" == 'darwin'* ]]; then
|
||||
if ! command -v gsed &>/dev/null; then
|
||||
if ! command -v gsed &> /dev/null; then
|
||||
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
118
.github/workflows/build-nix-image.yml
vendored
118
.github/workflows/build-nix-image.yml
vendored
@@ -6,16 +6,14 @@ on:
|
||||
- develop
|
||||
paths:
|
||||
- ".github/workflows/build-nix-image.yml"
|
||||
- ".github/workflows/reusable-build-docker-image.yml"
|
||||
- "docker/**"
|
||||
- "docker/nix.Dockerfile"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "nix/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build-nix-image.yml"
|
||||
- ".github/workflows/reusable-build-docker-image.yml"
|
||||
- "docker/**"
|
||||
- "docker/nix.Dockerfile"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "nix/**"
|
||||
@@ -29,81 +27,75 @@ defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
UBUNTU_VERSION: "20.04"
|
||||
RHEL_VERSION: "9"
|
||||
DEBIAN_VERSION: "bookworm"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.distro.name }} (${{ matrix.target.platform }})
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# The base images are the oldest supported version of each distro
|
||||
# that we want to build images for.
|
||||
distro:
|
||||
- name: nixos
|
||||
base_image: nixos/nix:latest
|
||||
- name: ubuntu
|
||||
base_image: ubuntu:20.04
|
||||
- name: rhel
|
||||
base_image: registry.access.redhat.com/ubi9/ubi:latest
|
||||
- name: debian
|
||||
base_image: debian:bookworm
|
||||
target:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
uses: ./.github/workflows/reusable-build-docker-image.yml
|
||||
with:
|
||||
image_name: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro.name }}
|
||||
dockerfile: docker/nix.Dockerfile
|
||||
base_image: ${{ matrix.distro.base_image }}
|
||||
platform: ${{ matrix.target.platform }}
|
||||
runner: ${{ matrix.target.runner }}
|
||||
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
|
||||
|
||||
merge:
|
||||
name: Merge ${{ matrix.distro }} manifest
|
||||
needs: build
|
||||
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
|
||||
name: Build and push Nix image (${{ matrix.distro }})
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro: [nixos, ubuntu, rhel, debian]
|
||||
env:
|
||||
IMAGE_NAME: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro }}
|
||||
include:
|
||||
- distro: nixos
|
||||
- distro: ubuntu
|
||||
- distro: rhel
|
||||
- distro: debian
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha,prefix=sha-,format=short
|
||||
type=raw,value=latest
|
||||
- name: Determine base image
|
||||
id: vars
|
||||
run: |
|
||||
case "${{ matrix.distro }}" in
|
||||
nixos)
|
||||
echo "base_image=nixos/nix:latest" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
ubuntu)
|
||||
echo "base_image=ubuntu:${UBUNTU_VERSION}" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
rhel)
|
||||
echo "base_image=registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
debian)
|
||||
echo "base_image=debian:${DEBIAN_VERSION}" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create multi-arch manifests
|
||||
run: |
|
||||
for tag in $(jq -cr '.tags[]' <<<"$DOCKER_METADATA_OUTPUT_JSON"); do
|
||||
docker buildx imagetools create -t "$tag" "${tag}-amd64" "${tag}-arm64"
|
||||
done
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
with:
|
||||
images: ghcr.io/xrplf/ci/nix-${{ matrix.distro }}
|
||||
tags: |
|
||||
type=sha,prefix=sha-,format=short
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect "${IMAGE_NAME}:${{ steps.meta.outputs.version }}"
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||
with:
|
||||
context: .
|
||||
file: docker/nix.Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: BASE_IMAGE=${{ steps.vars.outputs.base_image }}
|
||||
|
||||
23
.github/workflows/check-pr-description.yml
vendored
23
.github/workflows/check-pr-description.yml
vendored
@@ -5,17 +5,8 @@ on:
|
||||
types:
|
||||
- checks_requested
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
branches:
|
||||
- develop
|
||||
- "release-*"
|
||||
- "release/*"
|
||||
- "staging/*"
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
check_description:
|
||||
@@ -29,11 +20,11 @@ jobs:
|
||||
env:
|
||||
PR_BODY: ${{ github.event.pull_request.body }}
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: printenv PR_BODY >pr_body.md
|
||||
run: printenv PR_BODY > pr_body.md
|
||||
|
||||
- name: Check PR description differs from template
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
python .github/scripts/check-pr-description.py \
|
||||
--template-file .github/pull_request_template.md \
|
||||
--pr-body-file pr_body.md
|
||||
run: >
|
||||
python .github/scripts/check-pr-description.py
|
||||
--template-file .github/pull_request_template.md
|
||||
--pr-body-file pr_body.md
|
||||
|
||||
15
.github/workflows/check-pr-title.yml
vendored
15
.github/workflows/check-pr-title.yml
vendored
@@ -5,19 +5,10 @@ on:
|
||||
types:
|
||||
- checks_requested
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
branches:
|
||||
- develop
|
||||
- "release-*"
|
||||
- "release/*"
|
||||
- "staging/*"
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
check_title:
|
||||
if: ${{ github.event.pull_request.draft != true }}
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@291206777251b4d493641b5afbdf7c23009d2988
|
||||
|
||||
2
.github/workflows/conflicting-pr.yml
vendored
2
.github/workflows/conflicting-pr.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if PRs are dirty
|
||||
uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0
|
||||
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
|
||||
with:
|
||||
dirtyLabel: "PR: has conflicts"
|
||||
repoToken: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
8
.github/workflows/on-pr.yml
vendored
8
.github/workflows/on-pr.yml
vendored
@@ -98,7 +98,7 @@ jobs:
|
||||
READY: ${{ contains(github.event.pull_request.labels.*.name, 'Ready to merge') }}
|
||||
MERGE: ${{ github.event_name == 'merge_group' }}
|
||||
run: |
|
||||
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >>"${GITHUB_OUTPUT}"
|
||||
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >> "${GITHUB_OUTPUT}"
|
||||
cat "${GITHUB_OUTPUT}"
|
||||
outputs:
|
||||
go: ${{ steps.go.outputs.go == 'true' }}
|
||||
@@ -168,9 +168,9 @@ jobs:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
|
||||
-F "client_payload[pr_url]=${PR_URL}"
|
||||
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
|
||||
-F "client_payload[pr_url]=${PR_URL}"
|
||||
|
||||
passed:
|
||||
if: failure() || cancelled()
|
||||
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@5e942d61bf32f7557a7c159cfac4712a687b3e3a
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# Build a single-platform Docker image. On push, the image is pushed to
|
||||
# GHCR with arch-suffixed tags (e.g. `:latest-amd64`, `:sha-abc-amd64`)
|
||||
# so the calling workflow can stitch per-arch builds into a multi-arch
|
||||
# manifest without needing to pass digests around.
|
||||
name: Reusable build Docker image (single platform)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_name:
|
||||
description: "Full image name without tag (e.g. 'ghcr.io/xrplf/xrpld/nix-ubuntu')"
|
||||
required: true
|
||||
type: string
|
||||
dockerfile:
|
||||
description: "Path to the Dockerfile, relative to the repository root"
|
||||
required: true
|
||||
type: string
|
||||
base_image:
|
||||
description: "Value passed to the Dockerfile as the BASE_IMAGE build arg"
|
||||
required: true
|
||||
type: string
|
||||
platform:
|
||||
description: "Docker platform string, e.g. linux/amd64"
|
||||
required: true
|
||||
type: string
|
||||
runner:
|
||||
description: "GitHub Actions runner label to build on"
|
||||
required: true
|
||||
type: string
|
||||
push:
|
||||
description: "Whether to push the image to GHCR"
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (${{ inputs.platform }})
|
||||
runs-on: ${{ inputs.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Determine arch
|
||||
id: vars
|
||||
env:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
run: |
|
||||
echo "arch=${PLATFORM##*/}" >>$GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: inputs.push
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ${{ inputs.image_name }}
|
||||
tags: |
|
||||
type=sha,prefix=sha-,format=short
|
||||
type=raw,value=latest
|
||||
flavor: |
|
||||
suffix=-${{ steps.vars.outputs.arch }},onlatest=true
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.dockerfile }}
|
||||
platforms: ${{ inputs.platform }}
|
||||
push: ${{ inputs.push }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: BASE_IMAGE=${{ inputs.base_image }}
|
||||
80
.github/workflows/reusable-build-test-config.yml
vendored
80
.github/workflows/reusable-build-test-config.yml
vendored
@@ -113,7 +113,7 @@ jobs:
|
||||
|
||||
- name: Set ccache log file
|
||||
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
|
||||
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >>"${GITHUB_ENV}"
|
||||
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
@@ -146,11 +146,11 @@ jobs:
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
|
||||
- name: Check protocol autogen files are up-to-date
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
@@ -172,32 +172,32 @@ jobs:
|
||||
cmake --build . --target code_gen
|
||||
DIFF=$(git -C .. status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
|
||||
if [ -n "${DIFF}" ]; then
|
||||
echo "::error::Generated protocol files are out of date"
|
||||
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
echo "::error::Generated protocol files are out of date"
|
||||
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build the binary
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_NPROC: ${{ runner.os == 'Linux' && '16' || steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}"
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Show ccache statistics
|
||||
if: ${{ inputs.ccache_enabled }}
|
||||
run: |
|
||||
ccache --show-stats -vv
|
||||
if [ '${{ runner.debug }}' = '1' ]; then
|
||||
cat "${CCACHE_LOGFILE}"
|
||||
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
|
||||
cat "${CCACHE_LOGFILE}"
|
||||
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
|
||||
fi
|
||||
|
||||
- name: Upload the binary (Linux)
|
||||
@@ -214,7 +214,7 @@ jobs:
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
./xrpld --definitions | python3 -m json.tool >server_definitions.json
|
||||
./xrpld --definitions | python3 -m json.tool > server_definitions.json
|
||||
|
||||
- name: Upload server definitions
|
||||
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-bookworm-gcc-13-amd64-release' }}
|
||||
@@ -231,10 +231,10 @@ jobs:
|
||||
run: |
|
||||
ldd ./xrpld
|
||||
if [ "$(ldd ./xrpld | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
|
||||
echo 'The binary is statically linked.'
|
||||
echo 'The binary is statically linked.'
|
||||
else
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify presence of instrumentation (Linux)
|
||||
@@ -250,12 +250,12 @@ jobs:
|
||||
run: |
|
||||
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
|
||||
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
|
||||
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
|
||||
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
|
||||
fi
|
||||
echo "ASAN_OPTIONS=${ASAN_OPTS}" >>${GITHUB_ENV}
|
||||
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >>${GITHUB_ENV}
|
||||
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >>${GITHUB_ENV}
|
||||
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >>${GITHUB_ENV}
|
||||
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${GITHUB_ENV}
|
||||
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
|
||||
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
|
||||
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
@@ -266,9 +266,9 @@ jobs:
|
||||
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
ctest \
|
||||
--output-on-failure \
|
||||
-C "${BUILD_TYPE}" \
|
||||
-j "${PARALLELISM}"
|
||||
--output-on-failure \
|
||||
-C "${BUILD_TYPE}" \
|
||||
-j "${PARALLELISM}"
|
||||
|
||||
- name: Run the embedded tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
@@ -278,7 +278,7 @@ jobs:
|
||||
run: |
|
||||
set -o pipefail
|
||||
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness
|
||||
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$((BUILD_NPROC - 2))
|
||||
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$(( BUILD_NPROC - 2 ))
|
||||
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
|
||||
|
||||
- name: Show test failure summary
|
||||
@@ -287,19 +287,19 @@ jobs:
|
||||
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
|
||||
run: |
|
||||
if [ ! -d "${WORKING_DIR}" ]; then
|
||||
echo "Working directory '${WORKING_DIR}' does not exist."
|
||||
exit 0
|
||||
echo "Working directory '${WORKING_DIR}' does not exist."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "${WORKING_DIR}"
|
||||
|
||||
if [ ! -f unittest.log ]; then
|
||||
echo "unittest.log not found; embedded tests may not have run."
|
||||
exit 0
|
||||
echo "unittest.log not found; embedded tests may not have run."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! grep -E "failed" unittest.log; then
|
||||
echo "Log present but no failure lines found in unittest.log."
|
||||
echo "Log present but no failure lines found in unittest.log."
|
||||
fi
|
||||
- name: Debug failure (Linux)
|
||||
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
|
||||
@@ -317,14 +317,14 @@ jobs:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target coverage
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target coverage
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ github.repository == 'XRPLF/rippled' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
|
||||
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
|
||||
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
|
||||
@@ -38,9 +38,9 @@ jobs:
|
||||
run: |
|
||||
DIFF=$(git status --porcelain)
|
||||
if [ -n "${DIFF}" ]; then
|
||||
# Print the differences to give the contributor a hint about what to
|
||||
# expect when running levelization on their own machine.
|
||||
git diff
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
# Print the differences to give the contributor a hint about what to
|
||||
# expect when running levelization on their own machine.
|
||||
git diff
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
10
.github/workflows/reusable-check-rename.yml
vendored
10
.github/workflows/reusable-check-rename.yml
vendored
@@ -48,9 +48,9 @@ jobs:
|
||||
run: |
|
||||
DIFF=$(git status --porcelain)
|
||||
if [ -n "${DIFF}" ]; then
|
||||
# Print the differences to give the contributor a hint about what to
|
||||
# expect when running the renaming scripts on their own machine.
|
||||
git diff
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
# Print the differences to give the contributor a hint about what to
|
||||
# expect when running the renaming scripts on their own machine.
|
||||
git diff
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
48
.github/workflows/reusable-clang-tidy.yml
vendored
48
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -70,13 +70,13 @@ jobs:
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
run: |
|
||||
cmake \
|
||||
-G 'Ninja' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
-Dtests=ON \
|
||||
-Dwerr=ON \
|
||||
-Dxrpld=ON \
|
||||
..
|
||||
-G 'Ninja' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
-Dtests=ON \
|
||||
-Dwerr=ON \
|
||||
-Dxrpld=ON \
|
||||
..
|
||||
|
||||
# clang-tidy needs headers generated from proto files
|
||||
- name: Build libxrpl.libpb
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
- name: Write issue header
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
cat >"${ISSUE_FILE}" <<EOF
|
||||
cat > "${ISSUE_FILE}" <<EOF
|
||||
## Clang-tidy Check Failed
|
||||
|
||||
### Clang-tidy Output:
|
||||
@@ -144,30 +144,30 @@ jobs:
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
if [ -f "${OUTPUT_FILE}" ]; then
|
||||
# Extract lines containing 'error:', 'warning:', or 'note:'
|
||||
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >filtered-output.txt || true
|
||||
# Extract lines containing 'error:', 'warning:', or 'note:'
|
||||
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" > filtered-output.txt || true
|
||||
|
||||
# If filtered output is empty, use original (might be a different error format)
|
||||
if [ ! -s filtered-output.txt ]; then
|
||||
cp "${OUTPUT_FILE}" filtered-output.txt
|
||||
fi
|
||||
# If filtered output is empty, use original (might be a different error format)
|
||||
if [ ! -s filtered-output.txt ]; then
|
||||
cp "${OUTPUT_FILE}" filtered-output.txt
|
||||
fi
|
||||
|
||||
# Truncate if too large
|
||||
head -c 60000 filtered-output.txt >>"${ISSUE_FILE}"
|
||||
if [ "$(wc -c <filtered-output.txt)" -gt 60000 ]; then
|
||||
echo "" >>"${ISSUE_FILE}"
|
||||
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
|
||||
fi
|
||||
# Truncate if too large
|
||||
head -c 60000 filtered-output.txt >> "${ISSUE_FILE}"
|
||||
if [ "$(wc -c < filtered-output.txt)" -gt 60000 ]; then
|
||||
echo "" >> "${ISSUE_FILE}"
|
||||
echo "... (output truncated, see artifacts for full output)" >> "${ISSUE_FILE}"
|
||||
fi
|
||||
|
||||
rm filtered-output.txt
|
||||
rm filtered-output.txt
|
||||
else
|
||||
echo "No output file found" >>"${ISSUE_FILE}"
|
||||
echo "No output file found" >> "${ISSUE_FILE}"
|
||||
fi
|
||||
|
||||
- name: Append issue footer
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
cat >>"${ISSUE_FILE}" <<EOF
|
||||
cat >> "${ISSUE_FILE}" <<EOF
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
|
||||
- name: Create issue
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
|
||||
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
|
||||
uses: XRPLF/actions/create-issue@36d450d12d301e8410c1b7936e5de70c291cbe36
|
||||
with:
|
||||
title: "Clang-tidy check failed"
|
||||
body_file: ${{ env.ISSUE_FILE }}
|
||||
|
||||
6
.github/workflows/reusable-package.yml
vendored
6
.github/workflows/reusable-package.yml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
id: generate
|
||||
working-directory: .github/scripts/strategy-matrix
|
||||
run: |
|
||||
./generate.py --packaging --config=linux.json >>"${GITHUB_OUTPUT}"
|
||||
./generate.py --packaging --config=linux.json >> "${GITHUB_OUTPUT}"
|
||||
|
||||
generate-version:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -58,7 +58,6 @@ jobs:
|
||||
|
||||
package:
|
||||
needs: [generate-matrix, generate-version]
|
||||
if: ${{ github.event.repository.visibility == 'public' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
@@ -89,7 +88,8 @@ jobs:
|
||||
run: ./package/build_pkg.sh
|
||||
|
||||
- name: Upload package artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: ${{ github.event.repository.visibility == 'public' }}
|
||||
with:
|
||||
name: ${{ matrix.artifact_name }}-pkg-${{ needs.generate-version.outputs.version }}
|
||||
path: |
|
||||
|
||||
@@ -42,4 +42,4 @@ jobs:
|
||||
env:
|
||||
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
|
||||
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
|
||||
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >>"${GITHUB_OUTPUT}"
|
||||
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"
|
||||
|
||||
@@ -37,50 +37,37 @@ repos:
|
||||
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
|
||||
rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=file]
|
||||
"types_or": [c++, c, proto]
|
||||
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
|
||||
|
||||
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
|
||||
rev: faadd6a9d852369ca94f4d15b2404c967ba8cb01 # frozen: 0.27.6
|
||||
- repo: https://github.com/BlankSpruce/gersemi
|
||||
rev: 0.26.0
|
||||
hooks:
|
||||
- id: gersemi
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
|
||||
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: [--end-of-line=auto]
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
|
||||
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/scop/pre-commit-shfmt
|
||||
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
|
||||
- repo: https://github.com/openstack/bashate
|
||||
rev: 5798d24d571676fc407e81df574c1ef57b520f23 # frozen: 2.1.1
|
||||
hooks:
|
||||
- id: shfmt
|
||||
args: [--write, --indent=4, --case-indent=true]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: format-inline-bash-workflows
|
||||
name: "format `run:` blocks in workflows/actions"
|
||||
entry: ./.github/scripts/format-inline-bash.py
|
||||
language: python
|
||||
files: ^\.github/(workflows|actions)/.*\.ya?ml$
|
||||
- id: format-inline-bash-markdown
|
||||
name: "format ```bash blocks in markdown"
|
||||
entry: ./.github/scripts/format-inline-bash.py
|
||||
language: python
|
||||
files: \.md$
|
||||
- id: bashate
|
||||
args: ["--ignore=E006"]
|
||||
|
||||
- repo: https://github.com/streetsidesoftware/cspell-cli
|
||||
rev: 4643f154907327ee0a2c7038f0296e0dd77d9776 # frozen: v10.0.0
|
||||
rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
|
||||
hooks:
|
||||
- id: cspell # Spell check changed files
|
||||
exclude: |
|
||||
|
||||
15
BUILD.md
15
BUILD.md
@@ -151,8 +151,8 @@ git init
|
||||
git remote add origin git@github.com:XRPLF/conan-center-index.git
|
||||
git sparse-checkout init
|
||||
for recipe in "${recipes[@]}"; do
|
||||
echo "Checking out recipe '${recipe}'..."
|
||||
git sparse-checkout add recipes/${recipe}
|
||||
echo "Checking out recipe '${recipe}'..."
|
||||
git sparse-checkout add recipes/${recipe}
|
||||
done
|
||||
git fetch origin master
|
||||
git checkout master
|
||||
@@ -180,7 +180,7 @@ the new recipe will be automatically pulled from the official Conan Center.
|
||||
|
||||
If you see an error similar to the following after running `conan profile show`:
|
||||
|
||||
```text
|
||||
```bash
|
||||
ERROR: Invalid setting '17' is not a valid 'settings.compiler.version' value.
|
||||
Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
|
||||
'9.0', '9.1', '10.0', '11.0', '12.0', '13', '13.0', '13.1', '14', '14.0', '15',
|
||||
@@ -427,19 +427,16 @@ install ccache --version 4.11.3 --allow-downgrade`.
|
||||
Single-config generators:
|
||||
|
||||
```
|
||||
cmake --build . --parallel N
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
Multi-config generators:
|
||||
|
||||
```
|
||||
cmake --build . --config Release --parallel N
|
||||
cmake --build . --config Debug --parallel N
|
||||
cmake --build . --config Release
|
||||
cmake --build . --config Debug
|
||||
```
|
||||
|
||||
Replace the `--parallel` parameter N with the desired number of parallel jobs. A common starting point is half of the number of available CPU
|
||||
cores.
|
||||
|
||||
5. Test xrpld.
|
||||
|
||||
Single-config generators:
|
||||
|
||||
@@ -93,6 +93,7 @@ find_package(OpenSSL REQUIRED)
|
||||
find_package(secp256k1 REQUIRED)
|
||||
find_package(SOCI REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(wasmi REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
|
||||
target_link_libraries(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# -ne 1 || "$1" == "--help" || "$1" == "-h" ]]; then
|
||||
name=$(basename $0)
|
||||
cat <<-USAGE
|
||||
name=$( basename $0 )
|
||||
cat <<- USAGE
|
||||
Usage: $name <username>
|
||||
|
||||
Where <username> is the Github username of the upstream repo. e.g. XRPLF
|
||||
@@ -14,7 +14,7 @@ fi
|
||||
shift
|
||||
user="$1"
|
||||
# Get the origin URL. Expect it be an SSH-style URL
|
||||
origin=$(git remote get-url origin)
|
||||
origin=$( git remote get-url origin )
|
||||
if [[ "${origin}" == "" ]]; then
|
||||
echo Invalid origin remote >&2
|
||||
exit 1
|
||||
@@ -22,11 +22,11 @@ fi
|
||||
# echo "Origin: ${origin}"
|
||||
# Parse the origin
|
||||
ifs_orig="${IFS}"
|
||||
IFS=':' read remote originpath <<<"${origin}"
|
||||
IFS=':' read remote originpath <<< "${origin}"
|
||||
# echo "Remote: ${remote}, Originpath: ${originpath}"
|
||||
IFS='@' read sshuser server <<<"${remote}"
|
||||
IFS='@' read sshuser server <<< "${remote}"
|
||||
# echo "SSHUser: ${sshuser}, Server: ${server}"
|
||||
IFS='/' read originuser repo <<<"${originpath}"
|
||||
IFS='/' read originuser repo <<< "${originpath}"
|
||||
# echo "Originuser: ${originuser}, Repo: ${repo}"
|
||||
if [[ "${sshuser}" == "" || "${server}" == "" || "${originuser}" == "" || "${repo}" == "" ]]; then
|
||||
echo "Can't parse origin URL: ${origin}" >&2
|
||||
@@ -35,9 +35,9 @@ fi
|
||||
upstream="https://${server}/${user}/${repo}"
|
||||
upstreampush="${remote}:${user}/${repo}"
|
||||
upstreamgroup="upstream upstream-push"
|
||||
current=$(git remote get-url upstream 2>/dev/null)
|
||||
currentpush=$(git remote get-url upstream-push 2>/dev/null)
|
||||
currentgroup=$(git config remotes.upstreams)
|
||||
current=$( git remote get-url upstream 2>/dev/null )
|
||||
currentpush=$( git remote get-url upstream-push 2>/dev/null )
|
||||
currentgroup=$( git config remotes.upstreams )
|
||||
if [[ "${current}" == "${upstream}" ]]; then
|
||||
echo "Upstream already set up correctly. Skip"
|
||||
elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${upstreampush}" ]]; then
|
||||
@@ -45,9 +45,9 @@ elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${u
|
||||
else
|
||||
if [[ "${current}" == "${upstreampush}" ]]; then
|
||||
echo "Upstream set to dangerous push URL. Update."
|
||||
_run git remote rename upstream upstream-push ||
|
||||
_run git remote remove upstream
|
||||
currentpush=$(git remote get-url upstream-push 2>/dev/null)
|
||||
_run git remote rename upstream upstream-push || \
|
||||
_run git remote remove upstream
|
||||
currentpush=$( git remote get-url upstream-push 2>/dev/null )
|
||||
fi
|
||||
_run git remote add upstream "${upstream}"
|
||||
fi
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# -lt 3 || "$1" == "--help" || "$1" = "-h" ]]; then
|
||||
name=$(basename $0)
|
||||
cat <<-USAGE
|
||||
name=$( basename $0 )
|
||||
cat <<- USAGE
|
||||
Usage: $name workbranch base/branch user/branch [user/branch [...]]
|
||||
|
||||
* workbranch will be created locally from base/branch
|
||||
@@ -16,7 +16,7 @@ fi
|
||||
work="$1"
|
||||
shift
|
||||
|
||||
branches=($(echo "${@}" | sed "s/:/\//"))
|
||||
branches=( $( echo "${@}" | sed "s/:/\//" ) )
|
||||
base="${branches[0]}"
|
||||
unset branches[0]
|
||||
|
||||
@@ -24,10 +24,10 @@ set -e
|
||||
|
||||
users=()
|
||||
for b in "${branches[@]}"; do
|
||||
users+=($(echo $b | cut -d/ -f1))
|
||||
users+=( $( echo $b | cut -d/ -f1 ) )
|
||||
done
|
||||
|
||||
users=($(printf '%s\n' "${users[@]}" | sort -u))
|
||||
users=( $( printf '%s\n' "${users[@]}" | sort -u ) )
|
||||
|
||||
git fetch --multiple upstreams "${users[@]}"
|
||||
git checkout -B "$work" --no-track "$base"
|
||||
@@ -40,7 +40,7 @@ done
|
||||
# Make sure the commits look right
|
||||
git log --show-signature "$base..HEAD"
|
||||
|
||||
parts=($(echo $base | sed "s/\// /"))
|
||||
parts=( $( echo $base | sed "s/\// /" ) )
|
||||
repo="${parts[0]}"
|
||||
b="${parts[1]}"
|
||||
push=$repo
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
if [[ "$repo" == "upstream" ]]; then
|
||||
repo="upstreams"
|
||||
fi
|
||||
cat <<PUSH
|
||||
cat << PUSH
|
||||
|
||||
-------------------------------------------------------------------
|
||||
This script will not push. Verify everything is correct, then push
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# -ne 3 || "$1" == "--help" || "$1" = "-h" ]]; then
|
||||
name=$(basename $0)
|
||||
cat <<-USAGE
|
||||
name=$( basename $0 )
|
||||
cat <<- USAGE
|
||||
Usage: $name workbranch base/branch version
|
||||
|
||||
* workbranch will be created locally from base/branch. If it exists,
|
||||
@@ -16,7 +16,7 @@ fi
|
||||
work="$1"
|
||||
shift
|
||||
|
||||
base=$(echo "$1" | sed "s/:/\//")
|
||||
base=$( echo "$1" | sed "s/:/\//" )
|
||||
shift
|
||||
|
||||
version=$1
|
||||
@@ -28,16 +28,16 @@ git fetch upstreams
|
||||
|
||||
git checkout -B "${work}" --no-track "${base}"
|
||||
|
||||
push=$(git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
|
||||
2>/dev/null) || true
|
||||
push=$( git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
|
||||
2>/dev/null ) || true
|
||||
if [[ "${push}" != "" ]]; then
|
||||
echo "Warning: ${push} may already exist."
|
||||
fi
|
||||
|
||||
build=$(find -name BuildInfo.cpp)
|
||||
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} >version.cpp &&
|
||||
diff "${build}" version.cpp && exit 1 ||
|
||||
mv -vi version.cpp ${build}
|
||||
build=$( find -name BuildInfo.cpp )
|
||||
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} > version.cpp && \
|
||||
diff "${build}" version.cpp && exit 1 || \
|
||||
mv -vi version.cpp ${build}
|
||||
|
||||
git diff
|
||||
|
||||
@@ -47,7 +47,7 @@ git commit -S -m "Set version to ${version}"
|
||||
|
||||
git log --oneline --first-parent ${base}^..
|
||||
|
||||
cat <<PUSH
|
||||
cat << PUSH
|
||||
|
||||
-------------------------------------------------------------------
|
||||
This script will not push. Verify everything is correct, then push
|
||||
|
||||
@@ -168,13 +168,7 @@ def main():
|
||||
if not os.environ.get("TIDY"):
|
||||
return 0
|
||||
|
||||
repo_root = Path(
|
||||
subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=Path(__file__).parent,
|
||||
text=True,
|
||||
).strip()
|
||||
)
|
||||
repo_root = Path(__file__).parent.parent
|
||||
files = staged_files(repo_root)
|
||||
if not files:
|
||||
return 0
|
||||
|
||||
@@ -953,21 +953,6 @@
|
||||
#
|
||||
# Optional keys for NuDB and RocksDB:
|
||||
#
|
||||
# cache_size Size of cache for database records. Default is 16384.
|
||||
# Setting this value to 0 will use the default value.
|
||||
#
|
||||
# cache_age Length of time in minutes to keep database records
|
||||
# cached. Default is 5 minutes. Setting this value to
|
||||
# 0 will use the default value.
|
||||
#
|
||||
# Note: if cache_size or cache_age is not specified,
|
||||
# default values will be used for the unspecified
|
||||
# parameter.
|
||||
#
|
||||
# Note: the cache will not be created if online_delete
|
||||
# is specified, because the rotating NodeStore does
|
||||
# not use this cache).
|
||||
#
|
||||
# fast_load Boolean. If set, load the last persisted ledger
|
||||
# from disk upon process start before syncing to
|
||||
# the network. This is likely to improve performance
|
||||
@@ -1481,7 +1466,10 @@ admin = 127.0.0.1
|
||||
protocol = http
|
||||
|
||||
[port_peer]
|
||||
port = 2459
|
||||
# Many servers still use the legacy port of 51235, so for backward-compatibility
|
||||
# we maintain that port number here. However, for new servers we recommend
|
||||
# changing this to the default port of 2459.
|
||||
port = 51235
|
||||
ip = 0.0.0.0
|
||||
# alternatively, to accept connections on IPv4 + IPv6, use:
|
||||
#ip = ::
|
||||
|
||||
@@ -67,6 +67,7 @@ target_link_libraries(
|
||||
Xrpl::opts
|
||||
Xrpl::syslibs
|
||||
secp256k1::secp256k1
|
||||
wasmi::wasmi
|
||||
xrpl.libpb
|
||||
xxHash::xxhash
|
||||
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# Python dependencies for XRP Ledger code generation scripts
|
||||
#
|
||||
# These packages are required to run the code generation scripts that
|
||||
# parse macro files and generate C++ wrapper classes.
|
||||
|
||||
# C preprocessor for Python - used to preprocess macro files
|
||||
pcpp>=1.30
|
||||
|
||||
# Parser combinator library - used to parse the macro DSL
|
||||
pyparsing>=3.0.0
|
||||
|
||||
# Template engine - used to generate C++ code from templates
|
||||
Mako>=1.2.2
|
||||
@@ -1,105 +1,13 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile requirements.in --generate-hashes --output-file requirements.txt
|
||||
mako==1.3.12 \
|
||||
--hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
|
||||
--hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
|
||||
# via -r requirements.in
|
||||
markupsafe==3.0.3 \
|
||||
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
|
||||
--hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \
|
||||
--hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \
|
||||
--hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \
|
||||
--hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \
|
||||
--hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \
|
||||
--hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \
|
||||
--hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \
|
||||
--hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \
|
||||
--hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \
|
||||
--hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \
|
||||
--hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \
|
||||
--hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \
|
||||
--hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \
|
||||
--hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \
|
||||
--hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \
|
||||
--hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \
|
||||
--hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \
|
||||
--hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \
|
||||
--hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \
|
||||
--hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \
|
||||
--hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \
|
||||
--hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \
|
||||
--hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \
|
||||
--hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \
|
||||
--hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \
|
||||
--hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \
|
||||
--hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \
|
||||
--hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \
|
||||
--hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \
|
||||
--hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \
|
||||
--hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \
|
||||
--hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \
|
||||
--hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \
|
||||
--hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \
|
||||
--hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \
|
||||
--hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \
|
||||
--hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \
|
||||
--hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \
|
||||
--hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \
|
||||
--hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \
|
||||
--hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \
|
||||
--hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \
|
||||
--hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \
|
||||
--hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \
|
||||
--hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \
|
||||
--hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \
|
||||
--hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \
|
||||
--hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \
|
||||
--hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \
|
||||
--hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \
|
||||
--hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \
|
||||
--hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \
|
||||
--hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \
|
||||
--hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \
|
||||
--hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \
|
||||
--hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \
|
||||
--hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \
|
||||
--hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \
|
||||
--hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \
|
||||
--hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \
|
||||
--hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \
|
||||
--hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \
|
||||
--hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \
|
||||
--hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \
|
||||
--hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \
|
||||
--hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \
|
||||
--hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \
|
||||
--hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \
|
||||
--hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \
|
||||
--hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \
|
||||
--hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
|
||||
--hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \
|
||||
--hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \
|
||||
--hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \
|
||||
--hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \
|
||||
--hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \
|
||||
--hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \
|
||||
--hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \
|
||||
--hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \
|
||||
--hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \
|
||||
--hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \
|
||||
--hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \
|
||||
--hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \
|
||||
--hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \
|
||||
--hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \
|
||||
--hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \
|
||||
--hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \
|
||||
--hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50
|
||||
# via mako
|
||||
pcpp==1.30 \
|
||||
--hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \
|
||||
--hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1
|
||||
# via -r requirements.in
|
||||
pyparsing==3.3.2 \
|
||||
--hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
|
||||
--hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
|
||||
# via -r requirements.in
|
||||
# Python dependencies for XRP Ledger code generation scripts
|
||||
#
|
||||
# These packages are required to run the code generation scripts that
|
||||
# parse macro files and generate C++ wrapper classes.
|
||||
|
||||
# C preprocessor for Python - used to preprocess macro files
|
||||
pcpp>=1.30
|
||||
|
||||
# Parser combinator library - used to parse the macro DSL
|
||||
pyparsing>=3.0.0
|
||||
|
||||
# Template engine - used to generate C++ code from templates
|
||||
Mako>=1.2.2
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
* @brief Construct a ${name} ledger entry wrapper from an existing SLE object.
|
||||
* @throws std::runtime_error if the ledger entry type doesn't match.
|
||||
*/
|
||||
explicit ${name}(SLE::const_pointer sle)
|
||||
explicit ${name}(std::shared_ptr<SLE const> sle)
|
||||
: LedgerEntryBase(std::move(sle))
|
||||
{
|
||||
// Verify ledger entry type
|
||||
@@ -168,7 +168,7 @@ ${field['typeData']['setter_type']} ${field['paramName']}${',' if i < len(requir
|
||||
* @param sle The existing ledger entry to copy from.
|
||||
* @throws std::runtime_error if the ledger entry type doesn't match.
|
||||
*/
|
||||
${name}Builder(SLE::const_pointer sle)
|
||||
${name}Builder(std::shared_ptr<SLE const> sle)
|
||||
{
|
||||
if (sle->at(sfLedgerEntryType) != ${tag})
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
"requires": [
|
||||
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
||||
|
||||
"wasmi/1.0.9#1fecdab9b90c96698eb35ea99ca4f5cb%1772227278.324",
|
||||
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
|
||||
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
|
||||
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
|
||||
|
||||
@@ -34,6 +34,7 @@ class Xrpl(ConanFile):
|
||||
"openssl/3.6.2",
|
||||
"secp256k1/0.7.1",
|
||||
"soci/4.0.3",
|
||||
"wasmi/1.0.9",
|
||||
"zlib/1.3.2",
|
||||
]
|
||||
|
||||
@@ -214,6 +215,7 @@ class Xrpl(ConanFile):
|
||||
"soci::soci",
|
||||
"secp256k1::secp256k1",
|
||||
"sqlite3::sqlite",
|
||||
"wasmi::wasmi",
|
||||
"xxhash::xxhash",
|
||||
"zlib::zlib",
|
||||
]
|
||||
|
||||
@@ -7,6 +7,8 @@ ignorePaths:
|
||||
- cmake/**
|
||||
- LICENSE.md
|
||||
- .clang-tidy
|
||||
- src/test/app/wasm_fixtures/**/*.wat
|
||||
- src/test/app/wasm_fixtures/*.c
|
||||
language: en
|
||||
allowCompoundWords: true # TODO (#6334)
|
||||
ignoreRandomStrings: true
|
||||
@@ -65,6 +67,7 @@ words:
|
||||
- Btrfs
|
||||
- Buildx
|
||||
- canonicality
|
||||
- cdylib
|
||||
- changespq
|
||||
- checkme
|
||||
- choco
|
||||
@@ -93,7 +96,6 @@ words:
|
||||
- daria
|
||||
- dcmake
|
||||
- dearmor
|
||||
- dedented
|
||||
- deleteme
|
||||
- demultiplexer
|
||||
- deserializaton
|
||||
@@ -200,13 +202,11 @@ words:
|
||||
- nonxrp
|
||||
- noreplace
|
||||
- noripple
|
||||
- nostdinc
|
||||
- notifempty
|
||||
- nudb
|
||||
- nullptr
|
||||
- nunl
|
||||
- Nyffenegger
|
||||
- onlatest
|
||||
- ostr
|
||||
- pargs
|
||||
- partitioner
|
||||
@@ -257,7 +257,6 @@ words:
|
||||
- sfields
|
||||
- shamap
|
||||
- shamapitem
|
||||
- shfmt
|
||||
- shlibs
|
||||
- sidechain
|
||||
- SIGGOOD
|
||||
@@ -271,6 +270,7 @@ words:
|
||||
- STATSDCOLLECTOR
|
||||
- stissue
|
||||
- stnum
|
||||
- stnumber
|
||||
- stobj
|
||||
- stobject
|
||||
- stpath
|
||||
@@ -302,7 +302,6 @@ words:
|
||||
- unauthorizing
|
||||
- unergonomic
|
||||
- unfetched
|
||||
- unfindable
|
||||
- unflatten
|
||||
- unfund
|
||||
- unimpair
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Verify that every tool expected in the Nix CI env is present and runnable.
|
||||
set -euo pipefail
|
||||
|
||||
ccache --version
|
||||
clang --version
|
||||
clang++ --version
|
||||
clang-format --version
|
||||
cmake --version
|
||||
conan --version
|
||||
g++ --version
|
||||
gcc --version
|
||||
gcovr --version
|
||||
git --version
|
||||
less --version
|
||||
make --version
|
||||
mold --version
|
||||
ninja --version
|
||||
perl --version
|
||||
pkg-config --version
|
||||
pre-commit --version
|
||||
python3 --version
|
||||
run-clang-tidy --help
|
||||
vim --version
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Install sanitizer runtime libraries required to run binaries compiled with:
|
||||
# -fsanitize=address → libasan.so.8
|
||||
# -fsanitize=thread → libtsan.so.2
|
||||
# -fsanitize=undefined → libubsan.so.1
|
||||
#
|
||||
# The exact SONAMEs required depend on the compiler toolchain used to build the
|
||||
# test binaries (see nix/ci-env.nix). If the toolchain is bumped and SONAMEs
|
||||
# change, update the list below (or detect them from the binaries).
|
||||
#
|
||||
# Supported base images:
|
||||
# debian:bookworm
|
||||
# ubuntu:20.04
|
||||
# rhel:9
|
||||
# nixos/nix — tests are skipped; this script is not called
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ ! -f /etc/os-release ]; then
|
||||
echo "ERROR: /etc/os-release not found; cannot detect OS" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. /etc/os-release
|
||||
|
||||
echo "Detected OS: ${ID} ${VERSION_ID:-}"
|
||||
|
||||
case "${ID}" in
|
||||
debian)
|
||||
apt-get update -y
|
||||
apt-get install -y --no-install-recommends \
|
||||
libasan8 \
|
||||
libtsan2 \
|
||||
libubsan1
|
||||
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
;;
|
||||
|
||||
ubuntu)
|
||||
apt-get update -y
|
||||
apt-get install -y --no-install-recommends \
|
||||
gnupg \
|
||||
software-properties-common
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
apt-get update -y
|
||||
apt-get install -y --no-install-recommends \
|
||||
libasan8 \
|
||||
libtsan2 \
|
||||
libubsan1
|
||||
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
;;
|
||||
|
||||
rhel | centos | rocky | almalinux)
|
||||
dnf install -y \
|
||||
libasan8 \
|
||||
libtsan2 \
|
||||
libubsan
|
||||
|
||||
dnf clean -y all
|
||||
rm -rf /var/cache/dnf/*
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "ERROR: unsupported OS '${ID}'. Supported: debian, ubuntu, rhel-family" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Verify that every expected library is now resolvable by the dynamic linker.
|
||||
missing=0
|
||||
for lib in libasan.so.8 libtsan.so.2 libubsan.so.1; do
|
||||
if ldconfig -p | grep -q "${lib}"; then
|
||||
echo "OK: ${lib} found"
|
||||
else
|
||||
echo "ERROR: ${lib} not found after installation" >&2
|
||||
missing=$((missing + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${missing}" -ne 0 ]; then
|
||||
echo "ERROR: ${missing} library/libraries missing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All sanitizer runtime libraries installed successfully."
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64) LOADER=/lib64/ld-linux-x86-64.so.2 ;;
|
||||
aarch64) LOADER=/lib/ld-linux-aarch64.so.1 ;;
|
||||
*)
|
||||
echo "Unsupported arch: $(uname -m)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "${LOADER}"
|
||||
@@ -27,12 +27,10 @@ RUN mkdir /tmp/nix-store-closure && \
|
||||
cp -R $(nix-store -qR result/) /tmp/nix-store-closure
|
||||
|
||||
# Final image
|
||||
FROM ${BASE_IMAGE} AS final
|
||||
|
||||
ARG BASE_IMAGE
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
# bash is not located at /bin/bash in nixos/nix, so we need to create a symlink to it.
|
||||
RUN if echo "${BASE_IMAGE}" | grep -qiE 'nixos'; then \
|
||||
RUN if [ -d /nix ]; then \
|
||||
ln -s /root/.nix-profile/bin/bash /bin/bash; \
|
||||
fi
|
||||
|
||||
@@ -45,64 +43,24 @@ ENTRYPOINT ["/bin/bash"]
|
||||
COPY --from=builder /tmp/nix-store-closure /nix/store
|
||||
COPY --from=builder /tmp/build/result /nix/ci-env
|
||||
|
||||
ENV PATH="/nix/ci-env/bin:${PATH}"
|
||||
|
||||
# Externally-built dynamically-linked ELF binaries hard-code the loader path
|
||||
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Install it
|
||||
# from the Nix store when the base image doesn't already provide one.
|
||||
COPY docker/loader-path.sh /tmp/loader-path.sh
|
||||
ENV PATH="/nix/ci-env/bin:$PATH"
|
||||
|
||||
RUN <<EOF
|
||||
target="$(/tmp/loader-path.sh)"
|
||||
|
||||
if [ ! -e "${target}" ]; then
|
||||
# Use the loader from the same glibc that gcc links libc against, so
|
||||
# ld-linux and libc/libpthread share GLIBC_PRIVATE symbols at runtime.
|
||||
src="$(dirname "$(gcc -print-file-name=libc.so.6)")/$(basename "${target}")"
|
||||
[ -e "${src}" ] || { echo "ld-linux not found at ${src}" >&2; exit 1; }
|
||||
mkdir -p "$(dirname "${target}")"
|
||||
cp "${src}" "${target}"
|
||||
fi
|
||||
ccache --version
|
||||
clang-format --version
|
||||
cmake --version
|
||||
conan --version
|
||||
g++ --version
|
||||
gcc --version
|
||||
gcovr --version
|
||||
git --version
|
||||
make --version
|
||||
mold --version
|
||||
ninja --version
|
||||
perl --version
|
||||
pkg-config --version
|
||||
pre-commit --version
|
||||
python3 --version
|
||||
run-clang-tidy --help
|
||||
vim --version
|
||||
EOF
|
||||
|
||||
COPY docker/check-tool-versions.sh /tmp/check-tool-versions.sh
|
||||
RUN /tmp/check-tool-versions.sh
|
||||
|
||||
# Sanity-check that the g++/clang++ are able to build binaries, including sanitizer-instrumented ones.
|
||||
COPY docker/test_files/cpp_sources/ /tmp/cpp_sources/
|
||||
COPY docker/test_files/compile-cpp-sources.sh /tmp/compile-cpp-sources.sh
|
||||
RUN /tmp/compile-cpp-sources.sh /tmp/cpp_sources /tmp/bins
|
||||
|
||||
# Tester: start from a clean BASE_IMAGE, install sanitizer runtime libraries,
|
||||
# and run the compiled test binaries to verify they execute correctly.
|
||||
FROM ${BASE_IMAGE} AS tester
|
||||
|
||||
ARG BASE_IMAGE
|
||||
|
||||
# bash is not located at /bin/bash in nixos/nix, so we need to create a symlink to it.
|
||||
RUN if echo "${BASE_IMAGE}" | grep -qiE 'nixos'; then \
|
||||
ln -s /root/.nix-profile/bin/bash /bin/bash; \
|
||||
fi
|
||||
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
|
||||
# Sanity-check that the built binaries run correctly in the vanilla base image, with the necessary sanitizer runtime libraries installed.
|
||||
COPY docker/install-sanitizer-libs.sh /tmp/install-sanitizer-libs.sh
|
||||
COPY docker/test_files/run-test-binaries.sh /tmp/run-test-binaries.sh
|
||||
COPY --from=final /tmp/bins /tmp/bins
|
||||
|
||||
RUN <<EOF
|
||||
if echo "${BASE_IMAGE}" | grep -qiE 'nixos'; then
|
||||
echo "Skipping runnning binaries on NixOS."
|
||||
else
|
||||
/tmp/install-sanitizer-libs.sh
|
||||
/tmp/run-test-binaries.sh /tmp/bins
|
||||
fi
|
||||
touch /tmp/tests-passed
|
||||
EOF
|
||||
|
||||
# Output: the final image, gated on a successful test run in the tester stage.
|
||||
# Copying the sentinel from tester creates a hard build dependency: if the test
|
||||
# run above failed, this stage — and the overall build — fails too.
|
||||
FROM final
|
||||
COPY --from=tester /tmp/tests-passed /tmp/tests-passed
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Compile all C++ test binaries during the Docker image build.
|
||||
# Each binary has the target system's ELF PT_INTERP (dynamic-linker path)
|
||||
# baked in so it can run on the (potentially minimal) final BASE_IMAGE.
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
src_dir="${1:?usage: $0 <src_dir> <dst_dir>}"
|
||||
dst_dir="${2:?usage: $0 <src_dir> <dst_dir>}"
|
||||
|
||||
loader="$(/tmp/loader-path.sh)"
|
||||
|
||||
mkdir -p "${dst_dir}"
|
||||
|
||||
function compile() {
|
||||
local compiler="${1}"
|
||||
local name="${2}"
|
||||
local san_flag="${3:-}"
|
||||
|
||||
local src="${src_dir}/${name}.cpp"
|
||||
local binary="${dst_dir}/${name}-${compiler}"
|
||||
|
||||
echo "=== Compiling ${name} with ${compiler} ==="
|
||||
# Always statically link libstdc++ so the test binary does not depend on
|
||||
# the host's libstdc++.so.6 version.
|
||||
local compile_cmd="${compiler} -std=c++23 -O1 -g \
|
||||
-pthread \
|
||||
-static-libstdc++ \
|
||||
${san_flag} \
|
||||
${src} -o ${binary}"
|
||||
echo "Compile cmd: ${compile_cmd}"
|
||||
eval "${compile_cmd}"
|
||||
|
||||
echo "=== Patching ${binary} to use ${loader} as PT_INTERP ==="
|
||||
local patch_cmd="patchelf --set-interpreter ${loader} --remove-rpath ${binary}"
|
||||
echo "Patch cmd: ${patch_cmd}"
|
||||
eval "${patch_cmd}"
|
||||
}
|
||||
|
||||
declare -A sanitize=(
|
||||
[regular]=""
|
||||
|
||||
[asan]="-fsanitize=address"
|
||||
[tsan]="-fsanitize=thread"
|
||||
[ubsan]="-fsanitize=undefined -fno-sanitize-recover=all"
|
||||
)
|
||||
|
||||
for name in regular asan tsan ubsan; do
|
||||
san_flag="${sanitize[${name}]}"
|
||||
for compiler in g++ clang++; do
|
||||
compile "${compiler}" "${name}" "${san_flag}"
|
||||
done
|
||||
done
|
||||
|
||||
echo "=== All binaries compiled ==="
|
||||
|
||||
ls -la "${dst_dir}"
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
__attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
__declspec(noinline)
|
||||
#endif
|
||||
int
|
||||
read_after_free(volatile int* array, std::size_t index)
|
||||
{
|
||||
std::atomic_signal_fence(std::memory_order_seq_cst);
|
||||
int value = array[index];
|
||||
std::atomic_signal_fence(std::memory_order_seq_cst);
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int* array = new int[5]{10, 20, 30, 40, 50};
|
||||
delete[] array;
|
||||
|
||||
std::cout << "Value at index 2: " << read_after_free(array, 2) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
static std::mutex gMutex;
|
||||
|
||||
void
|
||||
worker(int id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(gMutex);
|
||||
std::cout << "Hello from thread " << id << "\n";
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
constexpr int kNumThreads = 10;
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(kNumThreads);
|
||||
for (int i = 0; i < kNumThreads; ++i)
|
||||
threads.emplace_back(worker, i);
|
||||
for (auto& t : threads)
|
||||
t.join();
|
||||
|
||||
std::cout << "Hello from main thread\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
static int kCounter = 0;
|
||||
|
||||
void
|
||||
increment()
|
||||
{
|
||||
for (int i = 0; i < 100'000; ++i)
|
||||
{
|
||||
++kCounter;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
std::thread t1(increment);
|
||||
std::thread t2(increment);
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
std::cout << "Final counter value: " << kCounter << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int maxInt = std::numeric_limits<int>::max();
|
||||
int volatile one = 1;
|
||||
std::cout << "Current max: " << maxInt << std::endl;
|
||||
int overflowed = maxInt + one;
|
||||
std::cout << "Overflowed result: " << overflowed << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Run pre-compiled sanitizer binaries and confirm each emits its expected diagnostic.
|
||||
# Binaries must already exist in <bins_dir> with the layout:
|
||||
# <name>-g++ and <name>-clang++ for name in {regular,asan,tsan,ubsan}
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
bins_dir="${1:?usage: $0 <bins_dir>}"
|
||||
|
||||
failed_binaries=()
|
||||
|
||||
# Run a binary and verify its exit code and output.
|
||||
# Usage: run <binary> <expected_output> <expected_rc>
|
||||
function run() {
|
||||
local binary="${1}"
|
||||
local expected_output="${2}"
|
||||
local expected_rc="${3}"
|
||||
|
||||
local out_file
|
||||
out_file="$(mktemp)"
|
||||
|
||||
echo "=== Run ${binary} ==="
|
||||
set +e
|
||||
"${binary}" >"${out_file}" 2>&1
|
||||
local rc=$?
|
||||
set -e
|
||||
|
||||
cat "${out_file}"
|
||||
|
||||
local failed=0
|
||||
if [ "${expected_rc}" = "nonzero" ]; then
|
||||
if [ "${rc}" -eq 0 ]; then
|
||||
echo "ERROR: expected non-zero exit code from ${binary}, got ${rc}" >&2
|
||||
failed=1
|
||||
fi
|
||||
elif [ "${rc}" -ne "${expected_rc}" ]; then
|
||||
echo "ERROR: expected exit code ${expected_rc} from ${binary}, got ${rc}" >&2
|
||||
failed=1
|
||||
fi
|
||||
|
||||
if ! grep -q "${expected_output}" "${out_file}"; then
|
||||
echo "ERROR: expected '${expected_output}' from ${binary}" >&2
|
||||
failed=1
|
||||
fi
|
||||
|
||||
if [ "${failed}" -eq 0 ]; then
|
||||
echo "OK: '${expected_output}' detected"
|
||||
else
|
||||
failed_binaries+=("${binary}")
|
||||
fi
|
||||
}
|
||||
|
||||
declare -A expect=(
|
||||
[regular]="Hello from main thread"
|
||||
|
||||
[asan]="heap-use-after-free"
|
||||
[tsan]="data race"
|
||||
[ubsan]="signed integer overflow"
|
||||
)
|
||||
|
||||
for compiler in g++ clang++; do
|
||||
for name in regular asan tsan ubsan; do
|
||||
binary="${bins_dir}/${name}-${compiler}"
|
||||
|
||||
if [ "${name}" = "tsan" ] && [ "${compiler}" = "g++" ] &&
|
||||
grep -qi 'debian' /etc/os-release 2>/dev/null &&
|
||||
[ "$(uname -m)" = "aarch64" ]; then
|
||||
echo "=== Skipping ${binary} (tsan-g++ unsupported on Debian ARM64) ==="
|
||||
echo " NOTE: to enable it, add --security-opt seccomp=unconfined to your docker run command"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${name}" = "regular" ]; then
|
||||
expected_rc=0
|
||||
else
|
||||
expected_rc=nonzero
|
||||
fi
|
||||
run "${binary}" "${expect[$name]}" "${expected_rc}"
|
||||
done
|
||||
done
|
||||
|
||||
if [ "${#failed_binaries[@]}" -gt 0 ]; then
|
||||
echo "ERROR: the following binaries failed:" >&2
|
||||
printf ' %s\n' "${failed_binaries[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
4
flake.lock
generated
4
flake.lock
generated
@@ -15,7 +15,7 @@
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-custom-glibc": {
|
||||
"nixpkgs-glibc231": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1593520194,
|
||||
@@ -35,7 +35,7 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc"
|
||||
"nixpkgs-glibc231": "nixpkgs-glibc231"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
# version — matches the system libc on Ubuntu 20.04 LTS. Imported
|
||||
# manually (flake = false) because this revision predates nixpkgs'
|
||||
# own flake.nix.
|
||||
nixpkgs-custom-glibc = {
|
||||
nixpkgs-glibc231 = {
|
||||
url = "github:NixOS/nixpkgs/9cd98386a38891d1074fc18036b842dc4416f562";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ nixpkgs, nixpkgs-custom-glibc, ... }:
|
||||
{ nixpkgs, nixpkgs-glibc231, ... }:
|
||||
let
|
||||
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc; };
|
||||
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-glibc231; };
|
||||
in
|
||||
{
|
||||
devShells = forEachSystem (import ./nix/devshell.nix);
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -42,58 +38,17 @@ isPowerOfTen(T value)
|
||||
return logTen(value).has_value();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Builds a table of the powers of 10
|
||||
*
|
||||
* This function is marked consteval, so it can only be run in
|
||||
* a constexpr context. This assures that it is and can only be run at
|
||||
* compile time. Doing it at runtime would be pretty wasteful and
|
||||
* inefficient.
|
||||
*/
|
||||
constexpr std::size_t kInt64Digits = 20;
|
||||
consteval std::array<std::uint64_t, kInt64Digits>
|
||||
buildPowersOfTen()
|
||||
{
|
||||
std::array<std::uint64_t, kInt64Digits> result{};
|
||||
|
||||
std::uint64_t power = 1;
|
||||
std::size_t exponent = 0;
|
||||
// end the loop early so it doesn't overflow;
|
||||
for (; exponent < result.size() - 1; ++exponent, power *= 10)
|
||||
{
|
||||
result[exponent] = power;
|
||||
if (power > std::numeric_limits<std::uint64_t>::max() / 10)
|
||||
throw std::logic_error("Power of 10 table is too big");
|
||||
}
|
||||
result[exponent] = power;
|
||||
if (power < std::numeric_limits<std::uint64_t>::max() / 10)
|
||||
throw std::logic_error("Power of 10 table is not big enough for the uint64_t type");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
constexpr std::array<std::uint64_t, detail::kInt64Digits> kPowerOfTen = detail::buildPowersOfTen();
|
||||
|
||||
static_assert(kPowerOfTen[0] == 1);
|
||||
static_assert(kPowerOfTen[1] == 10);
|
||||
static_assert(kPowerOfTen[10] == 10'000'000'000);
|
||||
static_assert(
|
||||
isPowerOfTen(kPowerOfTen.back()) && *logTen(kPowerOfTen.back()) == detail::kInt64Digits - 1);
|
||||
|
||||
/** MantissaRange defines a range for the mantissa of a normalized Number.
|
||||
*
|
||||
* The mantissa is in the range [min, max], where
|
||||
* * min is a power of 10, and
|
||||
* * max = min * 10 - 1.
|
||||
*
|
||||
* The MantissaScale enum indicates properties of the range: size, and some behavioral
|
||||
* options. This intentionally restricts the number of unique MantissaRanges that can
|
||||
* be instantiated: one for each scale.
|
||||
* The mantissa_scale enum indicates whether the range is "small" or "large".
|
||||
* This intentionally restricts the number of MantissaRanges that can be
|
||||
* instantiated to two: one for each scale.
|
||||
*
|
||||
* The "Small" scale is based on the behavior of STAmount for IOUs. It has a min
|
||||
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
|
||||
* value of 10^15, and a max value of 10^16-1. This was sufficient for
|
||||
* uses before Lending Protocol was implemented, mostly related to AMM.
|
||||
*
|
||||
@@ -104,100 +59,46 @@ static_assert(
|
||||
* STNumber field type, and for internal calculations. That necessitated the
|
||||
* "large" scale.
|
||||
*
|
||||
* The "Large" scales are intended to represent all values that can be represented
|
||||
* The "large" scale is intended to represent all values that can be represented
|
||||
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
|
||||
* value of 10^19-1. "LargeLegacy" is like "Large", but preserves
|
||||
* a rounding error when a computation results in a mantissa of
|
||||
* Number::kMaxRep that needs to be rounded up, but rounds down
|
||||
* instead. It will maintain consistent behavior until the fixCleanup3_2_0
|
||||
* amendment is enabled.
|
||||
* value of 10^19-1.
|
||||
*
|
||||
* Note that if the mentioned amendments are eventually retired, this class
|
||||
* should be left in place, but the "Small" scale option should be removed. This
|
||||
* should be left in place, but the "small" scale option should be removed. This
|
||||
* will allow for future expansion beyond 64-bits if it is ever needed.
|
||||
*/
|
||||
struct MantissaRange final
|
||||
struct MantissaRange
|
||||
{
|
||||
using rep = std::uint64_t;
|
||||
enum class MantissaScale { Small, Large };
|
||||
|
||||
enum class MantissaScale {
|
||||
Small,
|
||||
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
|
||||
LargeLegacy,
|
||||
Large,
|
||||
};
|
||||
|
||||
// This entire enum can be removed when fixCleanup3_2_0 is retired
|
||||
enum class CuspRoundingFix : bool {
|
||||
Disabled = false,
|
||||
Enabled = true,
|
||||
};
|
||||
|
||||
explicit constexpr MantissaRange(MantissaScale sc) : scale(sc)
|
||||
explicit constexpr MantissaRange(MantissaScale scale)
|
||||
: min(getMin(scale)), log(logTen(min).value_or(-1)), scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
MantissaScale const scale;
|
||||
int const log{getExponent(scale)};
|
||||
rep const min{getMin(scale, log)};
|
||||
rep const max{(min * 10) - 1};
|
||||
CuspRoundingFix const cuspRoundingFixEnabled{isCuspFixEnabled(scale)};
|
||||
|
||||
static MantissaRange const&
|
||||
getMantissaRange(MantissaScale scale);
|
||||
|
||||
static std::set<MantissaScale> const&
|
||||
getAllScales();
|
||||
rep min;
|
||||
rep max{(min * 10) - 1};
|
||||
int log;
|
||||
MantissaScale scale;
|
||||
|
||||
private:
|
||||
static constexpr int
|
||||
getExponent(MantissaScale scale)
|
||||
static constexpr rep
|
||||
getMin(MantissaScale scale)
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case MantissaScale::Small:
|
||||
return 15;
|
||||
case MantissaScale::LargeLegacy:
|
||||
return 1'000'000'000'000'000ULL;
|
||||
case MantissaScale::Large:
|
||||
return 18;
|
||||
// LCOV_EXCL_START
|
||||
return 1'000'000'000'000'000'000ULL;
|
||||
default:
|
||||
// If called in a constexpr context, this throw assures that the build fails if an
|
||||
// Since this can never be called outside a non-constexpr
|
||||
// context, this throw assures that the build fails if an
|
||||
// invalid scale is used.
|
||||
throw std::runtime_error("Unknown mantissa scale");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
// Keep this function for future use with different ways to compute
|
||||
// the ranges.
|
||||
static constexpr rep
|
||||
getMin(MantissaScale scale, int exponent)
|
||||
{
|
||||
if (exponent < 0 || exponent >= kPowerOfTen.size())
|
||||
throw std::runtime_error("Invalid exponent"); // LCOV_EXCL_LINE
|
||||
return kPowerOfTen[exponent];
|
||||
}
|
||||
|
||||
static constexpr CuspRoundingFix
|
||||
isCuspFixEnabled(MantissaScale scale)
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case MantissaScale::Small:
|
||||
case MantissaScale::LargeLegacy:
|
||||
return CuspRoundingFix::Disabled;
|
||||
case MantissaScale::Large:
|
||||
return CuspRoundingFix::Enabled;
|
||||
default:
|
||||
// If called in a constexpr context, this throw assures that the build fails if an
|
||||
// invalid scale is used.
|
||||
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
static std::unordered_map<MantissaScale, MantissaRange> const&
|
||||
getRanges();
|
||||
};
|
||||
|
||||
// Like std::integral, but only 64-bit integral types.
|
||||
@@ -302,7 +203,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
|
||||
* amendments are enabled to determine which result to expect.
|
||||
*
|
||||
*/
|
||||
class Number final
|
||||
class Number
|
||||
{
|
||||
using rep = std::int64_t;
|
||||
using internalrep = MantissaRange::rep;
|
||||
@@ -523,83 +424,49 @@ public:
|
||||
return kRange.get().log;
|
||||
}
|
||||
|
||||
/// oneSmall is needed because the ranges are private
|
||||
static constexpr Number
|
||||
oneSmall();
|
||||
/// oneLarge is needed because the ranges are private
|
||||
static constexpr Number
|
||||
oneLarge();
|
||||
|
||||
// And one is needed because it needs to choose between oneSmall and
|
||||
// oneLarge based on the current range
|
||||
static Number
|
||||
one();
|
||||
|
||||
template <
|
||||
auto MinMantissa,
|
||||
auto MaxMantissa,
|
||||
Integral64 T = std::decay_t<decltype(MinMantissa)>>
|
||||
template <Integral64 T>
|
||||
[[nodiscard]]
|
||||
std::pair<T, int>
|
||||
normalizeToRange() const;
|
||||
|
||||
/** Normalize raw (mantissa, exponent) integers directly to a target range.
|
||||
*
|
||||
* This is the construction-time counterpart of the member overload above.
|
||||
* Callers that hold raw integers (e.g. IOUAmount) and want them in a
|
||||
* narrow range would otherwise build a Number (one normalize pass to the
|
||||
* default kRange) and then call the member normalizeToRange (a second pass
|
||||
* down to the narrow range). This overload does a single pass: it converts
|
||||
* the signed mantissa to its internal magnitude and normalizes straight to
|
||||
* [MinMantissa, MaxMantissa], building no intermediate Number.
|
||||
*
|
||||
* Data flow (single pass), contrasted with the old two-pass path:
|
||||
*
|
||||
* two-pass: (m,e) --build Number--> [kRange/Large] --member--> [Min,Max]
|
||||
* one-pass: (m,e) -------------- normalize --------------> [Min,Max]
|
||||
*
|
||||
* @tparam MinMantissa Lower bound of the target mantissa range; must be a
|
||||
* positive power of ten.
|
||||
* @tparam MaxMantissa Upper bound; must equal MinMantissa * 10 - 1.
|
||||
* @tparam T Result mantissa type, int64_t or uint64_t. Defaults
|
||||
* to the type of MinMantissa.
|
||||
* @param mantissa Raw signed mantissa (sign is extracted internally).
|
||||
* @param exponent Raw exponent.
|
||||
* @return The normalized (mantissa, exponent) pair in the target range.
|
||||
* A zero mantissa is returned unchanged.
|
||||
* @note The result is bit-identical to the two-pass path: an intermediate
|
||||
* pass to a strictly wider range cannot change the final
|
||||
* narrower-range result.
|
||||
* @note Thread-safety: reads the thread-local rounding mode only; holds no
|
||||
* shared state of its own. Safe to call concurrently.
|
||||
*
|
||||
* Example (IOU range, 10^15 .. 10^16-1):
|
||||
* @code
|
||||
* auto [m, e] = Number::normalizeToRange<1'000'000'000'000'000,
|
||||
* 9'999'999'999'999'999>(1, 0);
|
||||
* // m == 1'000'000'000'000'000, e == -15
|
||||
* @endcode
|
||||
*/
|
||||
template <
|
||||
auto MinMantissa,
|
||||
auto MaxMantissa,
|
||||
Integral64 T = std::decay_t<decltype(MinMantissa)>>
|
||||
[[nodiscard]]
|
||||
static std::pair<T, int>
|
||||
normalizeToRange(rep mantissa, int exponent);
|
||||
normalizeToRange(T minMantissa, T maxMantissa) const;
|
||||
|
||||
private:
|
||||
// Shared implementation for both normalizeToRange overloads. Takes the sign
|
||||
// and internal (uint64) magnitude already separated, normalizes in place to
|
||||
// [MinMantissa, MaxMantissa], and returns the signed (mantissa, exponent).
|
||||
template <
|
||||
auto MinMantissa,
|
||||
auto MaxMantissa,
|
||||
Integral64 T = std::decay_t<decltype(MinMantissa)>>
|
||||
static std::pair<T, int>
|
||||
normalizeToRangeImpl(bool negative, internalrep mantissa, int exponent);
|
||||
|
||||
static thread_local RoundingMode mode;
|
||||
// The available ranges for mantissa
|
||||
|
||||
static constexpr MantissaRange kSmallRange{MantissaRange::MantissaScale::Small};
|
||||
static_assert(isPowerOfTen(kSmallRange.min));
|
||||
static_assert(kSmallRange.min == 1'000'000'000'000'000LL);
|
||||
static_assert(kSmallRange.max == 9'999'999'999'999'999LL);
|
||||
static_assert(kSmallRange.log == 15);
|
||||
static_assert(kSmallRange.min < kMaxRep);
|
||||
static_assert(kSmallRange.max < kMaxRep);
|
||||
static constexpr MantissaRange kLargeRange{MantissaRange::MantissaScale::Large};
|
||||
static_assert(isPowerOfTen(kLargeRange.min));
|
||||
static_assert(kLargeRange.min == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(kLargeRange.max == internalrep(9'999'999'999'999'999'999ULL));
|
||||
static_assert(kLargeRange.log == 18);
|
||||
static_assert(kLargeRange.min < kMaxRep);
|
||||
static_assert(kLargeRange.max > kMaxRep);
|
||||
|
||||
// The range for the mantissa when normalized.
|
||||
// Use reference_wrapper to avoid making copies, and prevent accidentally
|
||||
// changing the values inside the range.
|
||||
static thread_local std::reference_wrapper<MantissaRange const> kRange;
|
||||
|
||||
void
|
||||
normalize(MantissaRange const& range);
|
||||
normalize();
|
||||
|
||||
/** Normalize Number components to an arbitrary range.
|
||||
*
|
||||
@@ -614,8 +481,7 @@ private:
|
||||
T& mantissa,
|
||||
int& exponent,
|
||||
internalrep const& minMantissa,
|
||||
internalrep const& maxMantissa,
|
||||
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled);
|
||||
internalrep const& maxMantissa);
|
||||
|
||||
template <class T>
|
||||
friend void
|
||||
@@ -624,9 +490,7 @@ private:
|
||||
T& mantissa,
|
||||
int& exponent,
|
||||
MantissaRange::rep const& minMantissa,
|
||||
MantissaRange::rep const& maxMantissa,
|
||||
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
|
||||
bool dropped);
|
||||
MantissaRange::rep const& maxMantissa);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isnormal() const noexcept;
|
||||
@@ -662,7 +526,7 @@ static constexpr Number kNumZero{};
|
||||
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
|
||||
: Number(negative, mantissa, exponent, Unchecked{})
|
||||
{
|
||||
normalize(kRange);
|
||||
normalize();
|
||||
}
|
||||
|
||||
inline Number::Number(internalrep mantissa, int exponent, Normalized)
|
||||
@@ -832,20 +696,13 @@ Number::isnormal() const noexcept
|
||||
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
|
||||
}
|
||||
|
||||
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
|
||||
template <Integral64 T>
|
||||
std::pair<T, int>
|
||||
Number::normalizeToRangeImpl(bool negative, internalrep mantissa, int exponent)
|
||||
Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
{
|
||||
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::int64_t>);
|
||||
static_assert(std::is_same_v<T, std::decay_t<decltype(MinMantissa)>>);
|
||||
static_assert(std::is_same_v<T, std::decay_t<decltype(MaxMantissa)>>);
|
||||
auto constexpr kMIN = static_cast<T>(MinMantissa);
|
||||
auto constexpr kMAX = static_cast<T>(MaxMantissa);
|
||||
static_assert(kMIN > 0);
|
||||
static_assert(kMIN % 10 == 0);
|
||||
static_assert(isPowerOfTen(kMIN));
|
||||
static_assert(kMAX % 10 == 9);
|
||||
static_assert((kMAX + 1) / 10 == kMIN);
|
||||
bool negative = negative_;
|
||||
internalrep mantissa = mantissa_;
|
||||
int exponent = exponent_;
|
||||
|
||||
if constexpr (std::is_unsigned_v<T>)
|
||||
{
|
||||
@@ -854,35 +711,12 @@ Number::normalizeToRangeImpl(bool negative, internalrep mantissa, int exponent)
|
||||
"xrpl::Number::normalizeToRange",
|
||||
"Number is non-negative for unsigned range.");
|
||||
}
|
||||
// Don't need to worry about the cuspRounding fix because rounding up will never take the
|
||||
// mantissa over maxMantissa with a ones digit value other than 0. 0 can safely be truncated.
|
||||
Number::normalize(
|
||||
negative, mantissa, exponent, kMIN, kMAX, MantissaRange::CuspRoundingFix::Disabled);
|
||||
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
|
||||
auto const sign = negative ? -1 : 1;
|
||||
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
|
||||
}
|
||||
|
||||
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
|
||||
std::pair<T, int>
|
||||
Number::normalizeToRange() const
|
||||
{
|
||||
// Forward this Number's already-separated internal components to the shared
|
||||
// implementation. Passing mantissa_ (which may exceed kMaxRep in the Large
|
||||
// range) through unchanged keeps the result byte-identical to before.
|
||||
return normalizeToRangeImpl<MinMantissa, MaxMantissa, T>(negative_, mantissa_, exponent_);
|
||||
}
|
||||
|
||||
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
|
||||
std::pair<T, int>
|
||||
Number::normalizeToRange(rep mantissa, int exponent)
|
||||
{
|
||||
// Separate sign and magnitude from the raw signed mantissa, then normalize
|
||||
// straight to the target range in a single pass (no intermediate Number).
|
||||
return normalizeToRangeImpl<MinMantissa, MaxMantissa, T>(
|
||||
mantissa < 0, externalToInternal(mantissa), exponent);
|
||||
}
|
||||
|
||||
constexpr Number
|
||||
abs(Number x) noexcept
|
||||
{
|
||||
@@ -929,8 +763,6 @@ to_string(MantissaRange::MantissaScale const& scale)
|
||||
{
|
||||
case MantissaRange::MantissaScale::Small:
|
||||
return "small";
|
||||
case MantissaRange::MantissaScale::LargeLegacy:
|
||||
return "largeLegacy";
|
||||
case MantissaRange::MantissaScale::Large:
|
||||
return "large";
|
||||
default:
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
/** Fetch an item from the cache.
|
||||
If the digest was not found, Handler
|
||||
will be called with this signature:
|
||||
SLE::const_pointer(void)
|
||||
std::shared_ptr<SLE const>(void)
|
||||
*/
|
||||
template <class Handler>
|
||||
SharedPointerType
|
||||
@@ -181,14 +181,14 @@ private:
|
||||
beast::insight::Collector::ptr const& collector)
|
||||
: hook(collector->makeHook(handler))
|
||||
, size(collector->makeGauge(prefix, "size"))
|
||||
, hitRate(collector->makeGauge(prefix, "hit_rate"))
|
||||
, hit_rate(collector->makeGauge(prefix, "hit_rate"))
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
beast::insight::Hook hook;
|
||||
beast::insight::Gauge size;
|
||||
beast::insight::Gauge hitRate;
|
||||
beast::insight::Gauge hit_rate;
|
||||
|
||||
std::size_t hits{0};
|
||||
std::size_t misses{0};
|
||||
@@ -197,16 +197,16 @@ private:
|
||||
class KeyOnlyEntry
|
||||
{
|
||||
public:
|
||||
clock_type::time_point lastAccess;
|
||||
clock_type::time_point last_access;
|
||||
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : lastAccess(lastAccess)
|
||||
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : last_access(lastAccess)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
touch(clock_type::time_point const& now)
|
||||
{
|
||||
lastAccess = now;
|
||||
last_access = now;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,10 +214,10 @@ private:
|
||||
{
|
||||
public:
|
||||
shared_weak_combo_pointer_type ptr;
|
||||
clock_type::time_point lastAccess;
|
||||
clock_type::time_point last_access;
|
||||
|
||||
ValueEntry(clock_type::time_point const& lastAccess, shared_pointer_type const& ptr)
|
||||
: ptr(ptr), lastAccess(lastAccess)
|
||||
: ptr(ptr), last_access(lastAccess)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
void
|
||||
touch(clock_type::time_point const& now)
|
||||
{
|
||||
lastAccess = now;
|
||||
last_access = now;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -286,13 +286,13 @@ private:
|
||||
std::string name_;
|
||||
|
||||
// Desired number of cache entries (0 = ignore)
|
||||
int const targetSize_;
|
||||
int const target_size_;
|
||||
|
||||
// Desired maximum cache age
|
||||
clock_type::duration const targetAge_;
|
||||
clock_type::duration const target_age_;
|
||||
|
||||
// Number of items cached
|
||||
int cacheCount_{0};
|
||||
int cache_count_{0};
|
||||
cache_type cache_; // Hold strong reference to recent objects
|
||||
std::uint64_t hits_{0};
|
||||
std::uint64_t misses_{0};
|
||||
|
||||
@@ -34,8 +34,8 @@ inline TaggedCache<
|
||||
, clock_(clock)
|
||||
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
|
||||
, name_(name)
|
||||
, targetSize_(size)
|
||||
, targetAge_(expiration)
|
||||
, target_size_(size)
|
||||
, target_age_(expiration)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
getCacheSize() const
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
return cacheCount_;
|
||||
return cache_count_;
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -139,7 +139,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
cache_.clear();
|
||||
cacheCount_ = 0;
|
||||
cache_count_ = 0;
|
||||
}
|
||||
|
||||
template <
|
||||
@@ -157,7 +157,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
cache_.clear();
|
||||
cacheCount_ = 0;
|
||||
cache_count_ = 0;
|
||||
hits_ = 0;
|
||||
misses_ = 0;
|
||||
}
|
||||
@@ -213,21 +213,21 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
|
||||
if (targetSize_ == 0 || (static_cast<int>(cache_.size()) <= targetSize_))
|
||||
if (target_size_ == 0 || (static_cast<int>(cache_.size()) <= target_size_))
|
||||
{
|
||||
whenExpire = now - targetAge_;
|
||||
whenExpire = now - target_age_;
|
||||
}
|
||||
else
|
||||
{
|
||||
whenExpire = now - (targetAge_ * targetSize_ / cache_.size());
|
||||
whenExpire = now - (target_age_ * target_size_ / cache_.size());
|
||||
|
||||
clock_type::duration const minimumAge(std::chrono::seconds(1));
|
||||
if (whenExpire > (now - minimumAge))
|
||||
whenExpire = now - minimumAge;
|
||||
|
||||
JLOG(journal_.trace())
|
||||
<< name_ << " is growing fast " << cache_.size() << " of " << targetSize_
|
||||
<< " aging at " << (now - whenExpire).count() << " of " << targetAge_.count();
|
||||
<< name_ << " is growing fast " << cache_.size() << " of " << target_size_
|
||||
<< " aging at " << (now - whenExpire).count() << " of " << target_age_.count();
|
||||
}
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
@@ -242,7 +242,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
for (std::thread& worker : workers)
|
||||
worker.join();
|
||||
|
||||
cacheCount_ -= allRemovals;
|
||||
cache_count_ -= allRemovals;
|
||||
}
|
||||
// At this point allStuffToSweep will go out of scope outside the lock
|
||||
// and decrement the reference count on each strong pointer.
|
||||
@@ -280,7 +280,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
--cacheCount_;
|
||||
--cache_count_;
|
||||
entry.ptr.convertToWeak();
|
||||
ret = true;
|
||||
}
|
||||
@@ -317,7 +317,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(key),
|
||||
std::forward_as_tuple(clock_.now(), data));
|
||||
++cacheCount_;
|
||||
++cache_count_;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -366,12 +366,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
data = cachedData;
|
||||
}
|
||||
|
||||
++cacheCount_;
|
||||
++cache_count_;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = data;
|
||||
++cacheCount_;
|
||||
++cache_count_;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -477,7 +477,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
auto [it, inserted] = cache_.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
|
||||
if (!inserted)
|
||||
it->second.lastAccess = now;
|
||||
it->second.last_access = now;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@@ -626,7 +626,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (entry.isCached())
|
||||
{
|
||||
// independent of cache size, so not counted as a hit
|
||||
++cacheCount_;
|
||||
++cache_count_;
|
||||
entry.touch(clock_.now());
|
||||
return entry.ptr.getStrong();
|
||||
}
|
||||
@@ -658,7 +658,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
if (total != 0)
|
||||
hitRate = (hits_ * 100) / total;
|
||||
}
|
||||
stats_.hitRate.set(hitRate);
|
||||
stats_.hit_rate.set(hitRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
else if (cit->second.lastAccess <= whenExpire)
|
||||
else if (cit->second.last_access <= whenExpire)
|
||||
{
|
||||
// strong, expired
|
||||
++cacheRemovals;
|
||||
@@ -773,12 +773,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
auto cit = partition.begin();
|
||||
while (cit != partition.end())
|
||||
{
|
||||
if (cit->second.lastAccess > now)
|
||||
if (cit->second.last_access > now)
|
||||
{
|
||||
cit->second.lastAccess = now;
|
||||
cit->second.last_access = now;
|
||||
++cit;
|
||||
}
|
||||
else if (cit->second.lastAccess <= whenExpire)
|
||||
else if (cit->second.last_access <= whenExpire)
|
||||
{
|
||||
cit = partition.erase(cit);
|
||||
}
|
||||
|
||||
@@ -24,20 +24,20 @@ namespace xrpl {
|
||||
template <class EF>
|
||||
class ScopeExit
|
||||
{
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
|
||||
public:
|
||||
~ScopeExit()
|
||||
{
|
||||
if (executeOnDestruction_)
|
||||
exitFunction_();
|
||||
if (execute_on_destruction_)
|
||||
exit_function_();
|
||||
}
|
||||
|
||||
ScopeExit(ScopeExit&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
executeOnDestruction_ = false;
|
||||
execute_on_destruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,22 +69,22 @@ ScopeExit(EF) -> ScopeExit<EF>;
|
||||
template <class EF>
|
||||
class ScopeFail
|
||||
{
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
int uncaughtOnCreation_{std::uncaught_exceptions()};
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
int uncaught_on_creation_{std::uncaught_exceptions()};
|
||||
|
||||
public:
|
||||
~ScopeFail()
|
||||
{
|
||||
if (executeOnDestruction_ && std::uncaught_exceptions() > uncaughtOnCreation_)
|
||||
exitFunction_();
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_)
|
||||
exit_function_();
|
||||
}
|
||||
|
||||
ScopeFail(ScopeFail&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
, uncaught_on_creation_{rhs.uncaught_on_creation_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
std::enable_if_t<
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> &&
|
||||
std::is_constructible_v<EF, EFP>>* = 0) noexcept
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
executeOnDestruction_ = false;
|
||||
execute_on_destruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -116,22 +116,22 @@ ScopeFail(EF) -> ScopeFail<EF>;
|
||||
template <class EF>
|
||||
class ScopeSuccess
|
||||
{
|
||||
EF exitFunction_;
|
||||
bool executeOnDestruction_{true};
|
||||
int uncaughtOnCreation_{std::uncaught_exceptions()};
|
||||
EF exit_function_;
|
||||
bool execute_on_destruction_{true};
|
||||
int uncaught_on_creation_{std::uncaught_exceptions()};
|
||||
|
||||
public:
|
||||
~ScopeSuccess() noexcept(noexcept(exitFunction_()))
|
||||
~ScopeSuccess() noexcept(noexcept(exit_function_()))
|
||||
{
|
||||
if (executeOnDestruction_ && std::uncaught_exceptions() <= uncaughtOnCreation_)
|
||||
exitFunction_();
|
||||
if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_)
|
||||
exit_function_();
|
||||
}
|
||||
|
||||
ScopeSuccess(ScopeSuccess&& rhs) noexcept(
|
||||
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
|
||||
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
|
||||
, executeOnDestruction_{rhs.executeOnDestruction_}
|
||||
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
|
||||
: exit_function_{std::forward<EF>(rhs.exit_function_)}
|
||||
, execute_on_destruction_{rhs.execute_on_destruction_}
|
||||
, uncaught_on_creation_{rhs.uncaught_on_creation_}
|
||||
{
|
||||
rhs.release();
|
||||
}
|
||||
@@ -146,14 +146,14 @@ public:
|
||||
!std::is_same_v<std::remove_cv_t<EFP>, ScopeSuccess> &&
|
||||
std::is_constructible_v<EF, EFP>>* =
|
||||
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
|
||||
: exitFunction_{std::forward<EFP>(f)}
|
||||
: exit_function_{std::forward<EFP>(f)}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept
|
||||
{
|
||||
executeOnDestruction_ = false;
|
||||
execute_on_destruction_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -77,8 +77,8 @@ private:
|
||||
|
||||
std::ostream& os_;
|
||||
Results results_;
|
||||
SuiteResults suiteResults_;
|
||||
CaseResults caseResults_;
|
||||
SuiteResults suite_results_;
|
||||
CaseResults case_results_;
|
||||
|
||||
public:
|
||||
Reporter(Reporter const&) = delete;
|
||||
@@ -196,22 +196,22 @@ template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onSuiteBegin(SuiteInfo const& info)
|
||||
{
|
||||
suiteResults_ = SuiteResults{info.fullName()};
|
||||
suite_results_ = SuiteResults{info.fullName()};
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onSuiteEnd()
|
||||
{
|
||||
results_.add(suiteResults_);
|
||||
results_.add(suite_results_);
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onCaseBegin(std::string const& name)
|
||||
{
|
||||
caseResults_ = CaseResults(name);
|
||||
os_ << suiteResults_.name << (caseResults_.name.empty() ? "" : (" " + caseResults_.name))
|
||||
case_results_ = CaseResults(name);
|
||||
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
@@ -219,23 +219,23 @@ template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onCaseEnd()
|
||||
{
|
||||
suiteResults_.add(caseResults_);
|
||||
suite_results_.add(case_results_);
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onPass()
|
||||
{
|
||||
++caseResults_.total;
|
||||
++case_results_.total;
|
||||
}
|
||||
|
||||
template <class Unused>
|
||||
void
|
||||
Reporter<Unused>::onFail(std::string const& reason)
|
||||
{
|
||||
++caseResults_.failed;
|
||||
++caseResults_.total;
|
||||
os_ << "#" << caseResults_.total << " failed" << (reason.empty() ? "" : ": ") << reason
|
||||
++case_results_.failed;
|
||||
++case_results_.total;
|
||||
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ inline bool
|
||||
JobQueue::Coro::post()
|
||||
{
|
||||
{
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
running_ = true;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ JobQueue::Coro::post()
|
||||
}
|
||||
|
||||
// The coroutine will not run. Clean up running_.
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
running_ = false;
|
||||
cv_.notify_all();
|
||||
return false;
|
||||
@@ -68,7 +68,7 @@ inline void
|
||||
JobQueue::Coro::resume()
|
||||
{
|
||||
{
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
running_ = true;
|
||||
}
|
||||
{
|
||||
@@ -92,7 +92,7 @@ JobQueue::Coro::resume()
|
||||
}
|
||||
detail::getLocalValues().release();
|
||||
detail::getLocalValues().reset(saved);
|
||||
std::scoped_lock const lk(mutexRun_);
|
||||
std::scoped_lock const lk(mutex_run_);
|
||||
running_ = false;
|
||||
cv_.notify_all();
|
||||
}
|
||||
@@ -127,7 +127,7 @@ JobQueue::Coro::expectEarlyExit()
|
||||
inline void
|
||||
JobQueue::Coro::join()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(mutexRun_);
|
||||
std::unique_lock<std::mutex> lk(mutex_run_);
|
||||
cv_.wait(lk, [this]() { return !running_; });
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ private:
|
||||
std::function<void()> job_;
|
||||
std::shared_ptr<LoadEvent> loadEvent_;
|
||||
std::string name_;
|
||||
clock_type::time_point queueTime_;
|
||||
clock_type::time_point queue_time_;
|
||||
};
|
||||
|
||||
using JobCounter = ClosureCounter<void>;
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
std::string name_;
|
||||
bool running_{false};
|
||||
std::mutex mutex_;
|
||||
std::mutex mutexRun_;
|
||||
std::mutex mutex_run_;
|
||||
std::condition_variable cv_;
|
||||
boost::coroutines2::coroutine<void>::push_type* yield_{};
|
||||
boost::coroutines2::coroutine<void>::pull_type coro_;
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
// Statistics tracking
|
||||
perf::PerfLog& perfLog_;
|
||||
beast::insight::Collector::ptr collector_;
|
||||
beast::insight::Gauge jobCount_;
|
||||
beast::insight::Gauge job_count_;
|
||||
beast::insight::Hook hook_;
|
||||
|
||||
std::condition_variable cv_;
|
||||
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
* While the JSON spec doesn't explicitly disallow this, you should avoid
|
||||
* calling this method twice with the same tag for the same object.
|
||||
*
|
||||
* If CHECK_JSON_WRITER is defined, this function throws an exception if
|
||||
* If CHECK_JSON_WRITER is defined, this function throws an exception if if
|
||||
* the tag you use has already been used in this object.
|
||||
*/
|
||||
template <typename Type>
|
||||
|
||||
@@ -123,7 +123,7 @@ private:
|
||||
bool preserveOrder,
|
||||
Keylet const& directory,
|
||||
uint256 const& key,
|
||||
std::function<void(SLE::ref)> const& describe);
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
||||
|
||||
public:
|
||||
ApplyView() = default;
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
|
||||
@return `nullptr` if the key is not present
|
||||
*/
|
||||
virtual SLE::pointer
|
||||
virtual std::shared_ptr<SLE>
|
||||
peek(Keylet const& k) = 0;
|
||||
|
||||
/** Remove a peeked SLE.
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
The key is no longer associated with the SLE.
|
||||
*/
|
||||
virtual void
|
||||
erase(SLE::ref sle) = 0;
|
||||
erase(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Insert a new state SLE
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
insert(SLE::ref sle) = 0;
|
||||
insert(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Indicate changes to a peeked SLE
|
||||
|
||||
@@ -208,7 +208,7 @@ public:
|
||||
*/
|
||||
/** @{ */
|
||||
virtual void
|
||||
update(SLE::ref sle) = 0;
|
||||
update(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -301,7 +301,7 @@ public:
|
||||
dirAppend(
|
||||
Keylet const& directory,
|
||||
Keylet const& key,
|
||||
std::function<void(SLE::ref)> const& describe)
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
if (key.type != ltOFFER)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ public:
|
||||
dirInsert(
|
||||
Keylet const& directory,
|
||||
uint256 const& key,
|
||||
std::function<void(SLE::ref)> const& describe)
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
return dirAdd(false, directory, key, describe);
|
||||
}
|
||||
@@ -349,7 +349,7 @@ public:
|
||||
dirInsert(
|
||||
Keylet const& directory,
|
||||
Keylet const& key,
|
||||
std::function<void(SLE::ref)> const& describe)
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
return dirAdd(false, directory, key.key, describe);
|
||||
}
|
||||
@@ -411,7 +411,7 @@ createRoot(
|
||||
ApplyView& view,
|
||||
Keylet const& directory,
|
||||
uint256 const& key,
|
||||
std::function<void(SLE::ref)> const& describe);
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
||||
|
||||
auto
|
||||
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start);
|
||||
@@ -434,7 +434,7 @@ insertPage(
|
||||
SLE::ref next,
|
||||
uint256 const& key,
|
||||
Keylet const& directory,
|
||||
std::function<void(SLE::ref)> const& describe);
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
||||
|
||||
} // namespace directory
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -67,8 +67,8 @@ public:
|
||||
std::function<void(
|
||||
uint256 const& key,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after)> const& func);
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func);
|
||||
|
||||
private:
|
||||
std::optional<STAmount> deliver_;
|
||||
|
||||
@@ -9,15 +9,15 @@ class BookDirs
|
||||
private:
|
||||
ReadView const* view_ = nullptr;
|
||||
uint256 const root_;
|
||||
uint256 const nextQuality_;
|
||||
uint256 const next_quality_;
|
||||
uint256 const key_;
|
||||
SLE::const_pointer sle_ = nullptr;
|
||||
std::shared_ptr<SLE const> sle_ = nullptr;
|
||||
unsigned int entry_ = 0;
|
||||
uint256 index_;
|
||||
|
||||
public:
|
||||
class const_iterator; // NOLINT(readability-identifier-naming)
|
||||
using value_type = SLE::const_pointer;
|
||||
using value_type = std::shared_ptr<SLE const>;
|
||||
|
||||
BookDirs(ReadView const&, Book const&);
|
||||
|
||||
@@ -67,16 +67,16 @@ private:
|
||||
friend class BookDirs;
|
||||
|
||||
const_iterator(ReadView const& view, uint256 const& root, uint256 const& dirKey)
|
||||
: view_(&view), root_(root), key_(dirKey), curKey_(dirKey)
|
||||
: view_(&view), root_(root), key_(dirKey), cur_key_(dirKey)
|
||||
{
|
||||
}
|
||||
|
||||
ReadView const* view_ = nullptr;
|
||||
uint256 root_;
|
||||
uint256 nextQuality_;
|
||||
uint256 next_quality_;
|
||||
uint256 key_;
|
||||
uint256 curKey_;
|
||||
SLE::const_pointer sle_;
|
||||
uint256 cur_key_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
unsigned int entry_ = 0;
|
||||
uint256 index_;
|
||||
std::optional<value_type> mutable cache_;
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
bool
|
||||
exists(Keylet const& k) const override;
|
||||
|
||||
SLE::const_pointer
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
bool
|
||||
|
||||
@@ -22,12 +22,12 @@ class Dir
|
||||
private:
|
||||
ReadView const* view_ = nullptr;
|
||||
Keylet root_;
|
||||
SLE::const_pointer sle_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
STVector256 const* indexes_ = nullptr;
|
||||
|
||||
public:
|
||||
class ConstIterator;
|
||||
using value_type = SLE::const_pointer;
|
||||
using value_type = std::shared_ptr<SLE const>;
|
||||
|
||||
Dir(ReadView const&, Keylet const&);
|
||||
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
Keylet page_;
|
||||
uint256 index_;
|
||||
std::optional<value_type> mutable cache_;
|
||||
SLE::const_pointer sle_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
STVector256 const* indexes_ = nullptr;
|
||||
std::vector<uint256>::const_iterator it_;
|
||||
};
|
||||
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
std::optional<uint256>
|
||||
succ(uint256 const& key, std::optional<uint256> const& last = std::nullopt) const override;
|
||||
|
||||
SLE::const_pointer
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
std::unique_ptr<SlesType::iter_base>
|
||||
@@ -202,16 +202,16 @@ public:
|
||||
//
|
||||
|
||||
void
|
||||
rawErase(SLE::ref sle) override;
|
||||
rawErase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawInsert(SLE::ref sle) override;
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawErase(uint256 const& key);
|
||||
|
||||
void
|
||||
rawReplace(SLE::ref sle) override;
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawDestroyXRP(XRPAmount const& fee) override
|
||||
@@ -361,7 +361,7 @@ public:
|
||||
bool
|
||||
isVotingLedger() const;
|
||||
|
||||
SLE::pointer
|
||||
std::shared_ptr<SLE>
|
||||
peek(Keylet const& k) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
|
||||
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||
// easily moved.
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonicResource_;
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonic_resource_;
|
||||
txs_map txs_;
|
||||
Rules rules_;
|
||||
LedgerHeader header_;
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
std::optional<key_type>
|
||||
succ(key_type const& key, std::optional<key_type> const& last = std::nullopt) const override;
|
||||
|
||||
SLE::const_pointer
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
std::unique_ptr<SlesType::iter_base>
|
||||
@@ -224,13 +224,13 @@ public:
|
||||
// RawView
|
||||
|
||||
void
|
||||
rawErase(SLE::ref sle) override;
|
||||
rawErase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawInsert(SLE::ref sle) override;
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawReplace(SLE::ref sle) override;
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawDestroyXRP(XRPAmount const& fee) override;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
can calculate metadata.
|
||||
*/
|
||||
virtual void
|
||||
rawErase(SLE::ref sle) = 0;
|
||||
rawErase(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Unconditionally insert a state item.
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
rawInsert(SLE::ref sle) = 0;
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Unconditionally replace a state item.
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
rawReplace(SLE::ref sle) = 0;
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Destroy XRP.
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ public:
|
||||
|
||||
using key_type = uint256;
|
||||
|
||||
using mapped_type = SLE::const_pointer;
|
||||
using mapped_type = std::shared_ptr<SLE const>;
|
||||
|
||||
struct SlesType : detail::ReadViewFwdRange<SLE::const_pointer>
|
||||
struct SlesType : detail::ReadViewFwdRange<std::shared_ptr<SLE const>>
|
||||
{
|
||||
explicit SlesType(ReadView const& view);
|
||||
[[nodiscard]] Iterator
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
@return `nullptr` if the key is not present or
|
||||
if the type does not match.
|
||||
*/
|
||||
[[nodiscard]] virtual SLE::const_pointer
|
||||
[[nodiscard]] virtual std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const = 0;
|
||||
|
||||
// Accounts in a payment are not allowed to use assets acquired during that
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
@@ -56,7 +57,7 @@ isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptShare,
|
||||
std::uint8_t depth);
|
||||
int depth);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isLPTokenFrozen(
|
||||
@@ -134,7 +135,7 @@ areCompatible(
|
||||
dirLink(
|
||||
ApplyView& view,
|
||||
AccountID const& owner,
|
||||
SLE::pointer& object,
|
||||
std::shared_ptr<SLE>& object,
|
||||
SF_UINT64 const& node = sfOwnerNode);
|
||||
|
||||
/** Checks that can withdraw funds from an object to itself or a destination.
|
||||
@@ -214,8 +215,8 @@ doWithdraw(
|
||||
* (if should not be skipped) and if the entry should be skipped. The status
|
||||
* is always tesSUCCESS if the entry should be skipped.
|
||||
*/
|
||||
using EntryDeleter =
|
||||
std::function<std::pair<TER, SkipEntry>(LedgerEntryType, uint256 const&, SLE::pointer&)>;
|
||||
using EntryDeleter = std::function<
|
||||
std::pair<TER, SkipEntry>(LedgerEntryType, uint256 const&, std::shared_ptr<SLE>&)>;
|
||||
/** Cleanup owner directory entries on account delete.
|
||||
* Used for a regular and AMM accounts deletion. The caller
|
||||
* has to provide the deleter function, which handles details of
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl::detail {
|
||||
|
||||
// Helper class that buffers modifications
|
||||
@@ -24,7 +26,7 @@ private:
|
||||
Modify,
|
||||
};
|
||||
|
||||
using items_t = std::map<key_type, std::pair<Action, SLE::pointer>>;
|
||||
using items_t = std::map<key_type, std::pair<Action, std::shared_ptr<SLE>>>;
|
||||
|
||||
items_t items_;
|
||||
XRPAmount dropsDestroyed_{0};
|
||||
@@ -58,10 +60,10 @@ public:
|
||||
[[nodiscard]] std::optional<key_type>
|
||||
succ(ReadView const& base, key_type const& key, std::optional<key_type> const& last) const;
|
||||
|
||||
[[nodiscard]] SLE::const_pointer
|
||||
[[nodiscard]] std::shared_ptr<SLE const>
|
||||
read(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
SLE::pointer
|
||||
std::shared_ptr<SLE>
|
||||
peek(ReadView const& base, Keylet const& k);
|
||||
|
||||
[[nodiscard]] std::size_t
|
||||
@@ -73,23 +75,23 @@ public:
|
||||
std::function<void(
|
||||
uint256 const& key,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after)> const& func) const;
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func) const;
|
||||
|
||||
void
|
||||
erase(ReadView const& base, SLE::ref sle);
|
||||
erase(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
rawErase(ReadView const& base, SLE::ref sle);
|
||||
rawErase(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
insert(ReadView const& base, SLE::ref sle);
|
||||
insert(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
update(ReadView const& base, SLE::ref sle);
|
||||
update(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
replace(ReadView const& base, SLE::ref sle);
|
||||
replace(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
destroyXRP(XRPAmount const& fee);
|
||||
@@ -102,12 +104,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
using Mods = hash_map<key_type, SLE::pointer>;
|
||||
using Mods = hash_map<key_type, std::shared_ptr<SLE>>;
|
||||
|
||||
static void
|
||||
threadItem(TxMeta& meta, SLE::ref to);
|
||||
threadItem(TxMeta& meta, std::shared_ptr<SLE> const& to);
|
||||
|
||||
SLE::pointer
|
||||
std::shared_ptr<SLE>
|
||||
getForMod(ReadView const& base, key_type const& key, Mods& mods, beast::Journal j);
|
||||
|
||||
void
|
||||
@@ -117,7 +119,7 @@ private:
|
||||
threadOwners(
|
||||
ReadView const& base,
|
||||
TxMeta& meta,
|
||||
SLE::const_ref sle,
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
Mods& mods,
|
||||
beast::Journal j);
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
[[nodiscard]] std::optional<key_type>
|
||||
succ(key_type const& key, std::optional<key_type> const& last = std::nullopt) const override;
|
||||
|
||||
[[nodiscard]] SLE::const_pointer
|
||||
[[nodiscard]] std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
[[nodiscard]] std::unique_ptr<SlesType::iter_base>
|
||||
@@ -69,28 +69,28 @@ public:
|
||||
[[nodiscard]] ApplyFlags
|
||||
flags() const override;
|
||||
|
||||
SLE::pointer
|
||||
std::shared_ptr<SLE>
|
||||
peek(Keylet const& k) override;
|
||||
|
||||
void
|
||||
erase(SLE::ref sle) override;
|
||||
erase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
insert(SLE::ref sle) override;
|
||||
insert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
update(SLE::ref sle) override;
|
||||
update(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
// RawView
|
||||
|
||||
void
|
||||
rawErase(SLE::ref sle) override;
|
||||
rawErase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawInsert(SLE::ref sle) override;
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawReplace(SLE::ref sle) override;
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawDestroyXRP(XRPAmount const& feeDrops) override;
|
||||
|
||||
@@ -22,14 +22,14 @@ public:
|
||||
static constexpr size_t kInitialBufferSize = kilobytes(256);
|
||||
|
||||
RawStateTable()
|
||||
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
kInitialBufferSize)}
|
||||
, items_{monotonicResource_.get()} {};
|
||||
, items_{monotonic_resource_.get()} {};
|
||||
|
||||
RawStateTable(RawStateTable const& rhs)
|
||||
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
kInitialBufferSize)}
|
||||
, items_{rhs.items_, monotonicResource_.get()}
|
||||
, items_{rhs.items_, monotonic_resource_.get()}
|
||||
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||
|
||||
RawStateTable(RawStateTable&&) = default;
|
||||
@@ -49,15 +49,15 @@ public:
|
||||
succ(ReadView const& base, key_type const& key, std::optional<key_type> const& last) const;
|
||||
|
||||
void
|
||||
erase(SLE::ref sle);
|
||||
erase(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
insert(SLE::ref sle);
|
||||
insert(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
replace(SLE::ref sle);
|
||||
replace(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
[[nodiscard]] SLE::const_pointer
|
||||
[[nodiscard]] std::shared_ptr<SLE const>
|
||||
read(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
void
|
||||
@@ -84,10 +84,10 @@ private:
|
||||
struct SleAction
|
||||
{
|
||||
Action action;
|
||||
SLE::pointer sle;
|
||||
std::shared_ptr<SLE> sle;
|
||||
|
||||
// Constructor needed for emplacement in std::map
|
||||
SleAction(Action action, SLE::pointer sle) : action(action), sle(std::move(sle))
|
||||
SleAction(Action action, std::shared_ptr<SLE> const& sle) : action(action), sle(sle)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -101,7 +101,7 @@ private:
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<key_type const, SleAction>>>;
|
||||
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||
// easily moved.
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonicResource_;
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonic_resource_;
|
||||
items_t items_;
|
||||
|
||||
XRPAmount dropsDestroyed_{0};
|
||||
|
||||
@@ -792,7 +792,7 @@ deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::
|
||||
void
|
||||
initializeFeeAuctionVote(
|
||||
ApplyView& view,
|
||||
SLE::pointer& ammSle,
|
||||
std::shared_ptr<SLE>& ammSle,
|
||||
AccountID const& account,
|
||||
Asset const& lptAsset,
|
||||
std::uint16_t tfee);
|
||||
@@ -812,7 +812,7 @@ Expected<bool, TER>
|
||||
verifyAndAdjustLPTokenBalance(
|
||||
Sandbox& sb,
|
||||
STAmount const& lpTokens,
|
||||
SLE::pointer& ammSle,
|
||||
std::shared_ptr<SLE>& ammSle,
|
||||
AccountID const& account);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
@@ -35,7 +36,11 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
|
||||
|
||||
/** Adjust the owner count up or down. */
|
||||
void
|
||||
adjustOwnerCount(ApplyView& view, SLE::ref sle, std::int32_t amount, beast::Journal j);
|
||||
adjustOwnerCount(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sle,
|
||||
std::int32_t amount,
|
||||
beast::Journal j);
|
||||
|
||||
/** Returns IOU issuer transfer fee as Rate. Rate specifies
|
||||
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
||||
@@ -71,7 +76,9 @@ getPseudoAccountFields();
|
||||
- null pointer
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isPseudoAccount(SLE::const_pointer sleAcct, std::set<SField const*> const& pseudoFieldFilter = {});
|
||||
isPseudoAccount(
|
||||
std::shared_ptr<SLE const> sleAcct,
|
||||
std::set<SField const*> const& pseudoFieldFilter = {});
|
||||
|
||||
/** Convenience overload that reads the account from the view. */
|
||||
[[nodiscard]] inline bool
|
||||
@@ -91,7 +98,7 @@ isPseudoAccount(
|
||||
* before using a field. The amendment check is **not** performed in
|
||||
* createPseudoAccount.
|
||||
*/
|
||||
[[nodiscard]] Expected<SLE::pointer, TER>
|
||||
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
|
||||
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
|
||||
|
||||
/** Checks the destination and tag.
|
||||
|
||||
@@ -23,7 +23,7 @@ checkExpired(SLE const& sleCredential, NetClock::time_point const& closed);
|
||||
|
||||
// Actually remove a credentials object from the ledger
|
||||
[[nodiscard]] TER
|
||||
deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j);
|
||||
deleteSLE(ApplyView& view, std::shared_ptr<SLE> const& sleCredential, beast::Journal j);
|
||||
|
||||
// Amendment and parameters checks for sfCredentialIDs field
|
||||
NotTEC
|
||||
@@ -70,7 +70,7 @@ verifyDepositPreauth(
|
||||
ApplyView& view,
|
||||
AccountID const& src,
|
||||
AccountID const& dst,
|
||||
SLE::const_ref sleDst,
|
||||
std::shared_ptr<SLE const> const& sleDst,
|
||||
beast::Journal j);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace xrpl {
|
||||
* if not.
|
||||
*/
|
||||
NotTEC
|
||||
checkTxPermission(SLE::const_ref delegate, STTx const& tx);
|
||||
checkTxPermission(std::shared_ptr<SLE const> const& delegate, STTx const& tx);
|
||||
|
||||
/**
|
||||
* Load the granular permissions granted to the delegate account for the
|
||||
@@ -28,7 +28,7 @@ checkTxPermission(SLE::const_ref delegate, STTx const& tx);
|
||||
*/
|
||||
void
|
||||
loadGranularPermission(
|
||||
SLE::const_ref delegate,
|
||||
std::shared_ptr<SLE const> const& delegate,
|
||||
TxType const& type,
|
||||
std::unordered_set<GranularPermissionType>& granularPermissions);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ bool
|
||||
cdirFirst(
|
||||
ReadView const& view,
|
||||
uint256 const& root,
|
||||
SLE::const_pointer& page,
|
||||
std::shared_ptr<SLE const>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
|
||||
@@ -123,7 +123,7 @@ bool
|
||||
dirFirst(
|
||||
ApplyView& view,
|
||||
uint256 const& root,
|
||||
SLE::pointer& page,
|
||||
std::shared_ptr<SLE>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
/** @} */
|
||||
@@ -147,7 +147,7 @@ bool
|
||||
cdirNext(
|
||||
ReadView const& view,
|
||||
uint256 const& root,
|
||||
SLE::const_pointer& page,
|
||||
std::shared_ptr<SLE const>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
|
||||
@@ -155,14 +155,17 @@ bool
|
||||
dirNext(
|
||||
ApplyView& view,
|
||||
uint256 const& root,
|
||||
SLE::pointer& page,
|
||||
std::shared_ptr<SLE>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
/** @} */
|
||||
|
||||
/** Iterate all items in the given directory. */
|
||||
void
|
||||
forEachItem(ReadView const& view, Keylet const& root, std::function<void(SLE::const_ref)> const& f);
|
||||
forEachItem(
|
||||
ReadView const& view,
|
||||
Keylet const& root,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f);
|
||||
|
||||
/** Iterate all items after an item in the given directory.
|
||||
@param after The key of the item to start after
|
||||
@@ -177,11 +180,14 @@ forEachItemAfter(
|
||||
uint256 const& after,
|
||||
std::uint64_t const hint,
|
||||
unsigned int limit,
|
||||
std::function<bool(SLE::const_ref)> const& f);
|
||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f);
|
||||
|
||||
/** Iterate all items in an account's owner directory. */
|
||||
inline void
|
||||
forEachItem(ReadView const& view, AccountID const& id, std::function<void(SLE::const_ref)> const& f)
|
||||
forEachItem(
|
||||
ReadView const& view,
|
||||
AccountID const& id,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
forEachItem(view, keylet::ownerDir(id), f);
|
||||
}
|
||||
@@ -199,7 +205,7 @@ forEachItemAfter(
|
||||
uint256 const& after,
|
||||
std::uint64_t const hint,
|
||||
unsigned int limit,
|
||||
std::function<bool(SLE::const_ref)> const& f)
|
||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
return forEachItemAfter(view, keylet::ownerDir(id), after, hint, limit, f);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ TER
|
||||
escrowUnlockApplyHelper(
|
||||
ApplyView& view,
|
||||
Rate lockedRate,
|
||||
SLE::ref sleDest,
|
||||
std::shared_ptr<SLE> const& sleDest,
|
||||
STAmount const& xrpBalance,
|
||||
STAmount const& amount,
|
||||
AccountID const& issuer,
|
||||
@@ -32,7 +32,7 @@ inline TER
|
||||
escrowUnlockApplyHelper<Issue>(
|
||||
ApplyView& view,
|
||||
Rate lockedRate,
|
||||
SLE::ref sleDest,
|
||||
std::shared_ptr<SLE> const& sleDest,
|
||||
STAmount const& xrpBalance,
|
||||
STAmount const& amount,
|
||||
AccountID const& issuer,
|
||||
@@ -162,7 +162,7 @@ inline TER
|
||||
escrowUnlockApplyHelper<MPTIssue>(
|
||||
ApplyView& view,
|
||||
Rate lockedRate,
|
||||
SLE::ref sleDest,
|
||||
std::shared_ptr<SLE> const& sleDest,
|
||||
STAmount const& xrpBalance,
|
||||
STAmount const& amount,
|
||||
AccountID const& issuer,
|
||||
|
||||
@@ -4,38 +4,8 @@
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/st.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* Broker cover preclaim precision guard (fixCleanup3_2_0).
|
||||
*
|
||||
* Prevents a "silent sub-ULP no-op" where a deposit, withdrawal, or clawback
|
||||
* amount is so small that it rounds to zero at `sfCoverAvailable`'s scale.
|
||||
* Without this guard, both the pseudo trust-line and `sfCoverAvailable` would
|
||||
* identically absorb the rounded zero, resulting in a successful transaction
|
||||
* (tesSUCCESS) where no funds actually moved.
|
||||
*
|
||||
* @param view Read view (rules used for amendment gating).
|
||||
* @param sleBroker The loan broker SLE (read-only).
|
||||
* @param vaultAsset The underlying vault asset (the broker's cover asset).
|
||||
* @param amount The effective subtraction/addition amount.
|
||||
* @param j Journal for logging.
|
||||
* @param logPrefix Transactor name for log diagnostics.
|
||||
*
|
||||
* @return `tecPRECISION_LOSS` if the request rounds to zero at cover scale.
|
||||
* `tesSUCCESS` if the amendment is disabled or the request is safely supra-ULP.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canApplyToBrokerCover(
|
||||
ReadView const& view,
|
||||
SLE::const_ref sleBroker,
|
||||
Asset const& vaultAsset,
|
||||
STAmount const& amount,
|
||||
beast::Journal j,
|
||||
std::string_view logPrefix);
|
||||
|
||||
// Lending protocol has dependencies, so capture them here.
|
||||
bool
|
||||
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
|
||||
@@ -203,21 +173,6 @@ getAssetsTotalScale(SLE::const_ref vaultSle)
|
||||
return scale(vaultSle->at(sfAssetsTotal), vaultSle->at(sfAsset));
|
||||
}
|
||||
|
||||
// Compute the minimum required broker cover, rounded consistently.
|
||||
// DebtTotal is a broker-level aggregate maintained at vault scale, so the
|
||||
// rounding must also use vault scale — never an individual loan's scale.
|
||||
inline Number
|
||||
minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::const_ref vaultSle)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
vaultSle && vaultSle->getType() == ltVAULT, "xrpl::minimumBrokerCover : valid Vault sle");
|
||||
NumberRoundModeGuard const mg(Number::RoundingMode::Upward);
|
||||
return roundToAsset(
|
||||
vaultSle->at(sfAsset),
|
||||
tenthBipsOfValue(debtTotal, coverRateMinimum),
|
||||
getAssetsTotalScale(vaultSle));
|
||||
}
|
||||
|
||||
TER
|
||||
checkLoanGuards(
|
||||
Asset const& vaultAsset,
|
||||
@@ -461,7 +416,6 @@ loanAccruedInterest(
|
||||
|
||||
ExtendedPaymentComponents
|
||||
computeOverpaymentComponents(
|
||||
Rules const& rules,
|
||||
Asset const& asset,
|
||||
int32_t const loanScale,
|
||||
Number const& overpayment,
|
||||
|
||||
@@ -27,18 +27,14 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue,
|
||||
std::uint8_t depth = 0);
|
||||
isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
MPTIssue const& mptIssue,
|
||||
std::uint8_t depth = 0);
|
||||
int depth = 0);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
@@ -92,7 +88,7 @@ requireAuth(
|
||||
MPTIssue const& mptIssue,
|
||||
AccountID const& account,
|
||||
AuthType authType = AuthType::Legacy,
|
||||
std::uint8_t depth = 0);
|
||||
int depth = 0);
|
||||
|
||||
/** Enforce account has MPToken to match its authorization.
|
||||
*
|
||||
@@ -108,78 +104,23 @@ enforceMPTokenAuthorization(
|
||||
XRPAmount const& priorBalance,
|
||||
beast::Journal j);
|
||||
|
||||
/** Resolve the underlying asset of a vault share.
|
||||
*
|
||||
* Reads sfReferenceHolding from @p sleShareIssuance to determine which
|
||||
* asset the vault wraps. @p sleHolding must be the SLE that
|
||||
* sfReferenceHolding points to — either an ltMPTOKEN (returns its
|
||||
* MPTIssue) or an ltRIPPLE_STATE (returns its low/high Issue).
|
||||
*
|
||||
* @pre Both SLEs must exist and @p sleHolding must be of type ltMPTOKEN
|
||||
* or ltRIPPLE_STATE. Passing any other type is undefined behaviour.
|
||||
* @param sleShareIssuance MPTokenIssuance SLE for the vault share token.
|
||||
* @param sleHolding SLE referenced by sfReferenceHolding.
|
||||
* @return The underlying Asset (MPTIssue or Issue).
|
||||
*/
|
||||
[[nodiscard]] Asset
|
||||
assetOfHolding(SLE const& sleShareIssuance, SLE const& sleHolding);
|
||||
|
||||
/** Check whether @p to may receive the given MPT from @p from.
|
||||
*
|
||||
* The check passes when any of the following is true:
|
||||
* - @p waive is WaiveMPTCanTransfer::Yes (recovery-path exemption), or
|
||||
* - @p from or @p to is the issuer, or
|
||||
* - lsfMPTCanTransfer is set on the MPTokenIssuance.
|
||||
*
|
||||
* For vault shares (MPTokenIssuances that carry sfReferenceHolding) the
|
||||
* check recurses into the underlying asset's transferability. This
|
||||
* recursion is defensive; vault-of-vault-shares is rejected at vault
|
||||
* creation, so in practice depth never exceeds 1.
|
||||
*
|
||||
* @param view Ledger state to read from.
|
||||
* @param mptIssue The MPT issuance being transferred.
|
||||
* @param from Sending account.
|
||||
* @param to Receiving account.
|
||||
* @param waive WaiveMPTCanTransfer::Yes skips the lsfMPTCanTransfer
|
||||
* check. Use for recovery paths (e.g. unwinding SAV or
|
||||
* Lending Protocol positions after an issuer revokes
|
||||
* transferability).
|
||||
* @param depth Recursion depth; bounded at kMaxAssetCheckDepth.
|
||||
* @return tesSUCCESS if the transfer is allowed, tecNO_AUTH otherwise.
|
||||
/** Check if the destination account is allowed
|
||||
* to receive MPT. Return tecNO_AUTH if it doesn't
|
||||
* and tesSUCCESS otherwise.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canTransfer(
|
||||
ReadView const& view,
|
||||
MPTIssue const& mptIssue,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
WaiveMPTCanTransfer waive = WaiveMPTCanTransfer::No,
|
||||
std::uint8_t depth = 0);
|
||||
|
||||
/** Check whether @p asset may be traded on the DEX.
|
||||
*
|
||||
* For IOU assets the check delegates to the existing offer/AMM freeze
|
||||
* logic. For MPT assets it checks lsfMPTCanTrade on the MPTokenIssuance.
|
||||
* Vault shares recurse into the underlying asset's tradability via
|
||||
* sfReferenceHolding; depth is bounded at kMaxAssetCheckDepth.
|
||||
*
|
||||
* @param view Ledger state to read from.
|
||||
* @param asset The asset to check.
|
||||
* @param depth Recursion depth; bounded at kMaxAssetCheckDepth.
|
||||
* @return tesSUCCESS if trading is allowed, tecNO_PERMISSION otherwise.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canTrade(ReadView const& view, Asset const& asset, std::uint8_t depth = 0);
|
||||
|
||||
/** Convenience to combine canTrade/Transfer. Returns tesSUCCESS if Asset is Issue.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canMPTTradeAndTransfer(
|
||||
ReadView const& v,
|
||||
Asset const& asset,
|
||||
AccountID const& from,
|
||||
AccountID const& to);
|
||||
|
||||
/** Check if Asset can be traded on DEX. return tecNO_PERMISSION
|
||||
* if it doesn't and tesSUCCESS otherwise.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canTrade(ReadView const& view, Asset const& asset);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Empty holding operations (MPT-specific)
|
||||
@@ -286,4 +227,17 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue);
|
||||
void
|
||||
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// MPT DEX
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* Return true if a transaction is allowed for the specified MPT/account. The
|
||||
* function checks MPTokenIssuance and MPToken objects flags to determine if the
|
||||
* transaction is allowed.
|
||||
*/
|
||||
TER
|
||||
checkMPTTxAllowed(ReadView const& v, TxType tx, Asset const& asset, AccountID const& accountID);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -28,9 +28,10 @@ findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID
|
||||
struct TokenAndPage
|
||||
{
|
||||
STObject token;
|
||||
SLE::pointer page;
|
||||
std::shared_ptr<SLE> page;
|
||||
|
||||
TokenAndPage(STObject token, SLE::pointer page) : token(std::move(token)), page(std::move(page))
|
||||
TokenAndPage(STObject token, std::shared_ptr<SLE> page)
|
||||
: token(std::move(token)), page(std::move(page))
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -46,7 +47,11 @@ TER
|
||||
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID);
|
||||
|
||||
TER
|
||||
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, SLE::ref page);
|
||||
removeToken(
|
||||
ApplyView& view,
|
||||
AccountID const& owner,
|
||||
uint256 const& nftokenID,
|
||||
std::shared_ptr<SLE> const& page);
|
||||
|
||||
/** Deletes the given token offer.
|
||||
|
||||
@@ -58,7 +63,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
|
||||
The offer also consumes one incremental reserve.
|
||||
*/
|
||||
bool
|
||||
deleteTokenOffer(ApplyView& view, SLE::ref offer);
|
||||
deleteTokenOffer(ApplyView& view, std::shared_ptr<SLE> const& offer);
|
||||
|
||||
/** Repairs the links in an NFTokenPage directory.
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** Delete an offer.
|
||||
@@ -21,6 +23,6 @@ namespace xrpl {
|
||||
*/
|
||||
// [[nodiscard]] // nodiscard commented out so Flow, BookTip and others compile.
|
||||
TER
|
||||
offerDelete(ApplyView& view, SLE::ref sle, beast::Journal j);
|
||||
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
namespace xrpl {
|
||||
|
||||
TER
|
||||
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j);
|
||||
closeChannel(
|
||||
std::shared_ptr<SLE> const& slep,
|
||||
ApplyView& view,
|
||||
uint256 const& key,
|
||||
beast::Journal j);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -93,7 +93,7 @@ isFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||
// Overload with depth parameter for uniformity with MPTIssue version.
|
||||
// The depth parameter is ignored for IOUs since they don't have vault recursion.
|
||||
[[nodiscard]] inline bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, std::uint8_t /*depth*/)
|
||||
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int /*depth*/)
|
||||
{
|
||||
return isFrozen(view, account, issue);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ isDeepFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& issue,
|
||||
std::uint8_t = 0 /*ignored*/)
|
||||
int = 0 /*ignored*/)
|
||||
{
|
||||
return isDeepFrozen(view, account, issue.currency, issue.account);
|
||||
}
|
||||
@@ -154,7 +154,7 @@ trustCreate(
|
||||
[[nodiscard]] TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
SLE::ref sleRippleState,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
@@ -248,7 +248,7 @@ removeEmptyHolding(
|
||||
[[nodiscard]] TER
|
||||
deleteAMMTrustLine(
|
||||
ApplyView& view,
|
||||
SLE::pointer sleState,
|
||||
std::shared_ptr<SLE> sleState,
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
@@ -258,7 +258,7 @@ deleteAMMTrustLine(
|
||||
[[nodiscard]] TER
|
||||
deleteAMMMPToken(
|
||||
ApplyView& view,
|
||||
SLE::pointer sleMPT,
|
||||
std::shared_ptr<SLE> sleMPT,
|
||||
AccountID const& ammAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
|
||||
@@ -34,15 +34,6 @@ enum class WaiveTransferFee : bool { No = false, Yes };
|
||||
/** Controls whether accountSend is allowed to overflow OutstandingAmount **/
|
||||
enum class AllowMPTOverflow : bool { No = false, Yes };
|
||||
|
||||
/** Controls whether canTransfer enforces lsfMPTCanTransfer on MPTs.
|
||||
*
|
||||
* Default is No (enforce). Use Yes at call sites that must remain available
|
||||
* even when an MPT issuer has cleared lsfMPTCanTransfer - for example,
|
||||
* unwinding existing positions in SAV or the Lending Protocol. Has no
|
||||
* effect on the IOU branch of canTransfer.
|
||||
*/
|
||||
enum class WaiveMPTCanTransfer : bool { No = false, Yes };
|
||||
|
||||
/* Check if MPToken (for MPT) or trust line (for IOU) exists:
|
||||
* - StrongAuth - before checking if authorization is required
|
||||
* - WeakAuth
|
||||
@@ -63,26 +54,16 @@ enum class AuthType { StrongAuth, WeakAuth, Legacy };
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(ReadView const& view, Asset const& asset);
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkGlobalFrozen(ReadView const& view, Asset const& asset);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
|
||||
|
||||
/**
|
||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||
* purely defensive, as we currently do not allow such vaults to be created.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Asset const& asset,
|
||||
std::uint8_t depth = 0);
|
||||
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue);
|
||||
@@ -104,14 +85,14 @@ isAnyFrozen(
|
||||
ReadView const& view,
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
Asset const& asset,
|
||||
std::uint8_t depth = 0);
|
||||
int depth = 0);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue,
|
||||
std::uint8_t depth = 0);
|
||||
int depth = 0);
|
||||
|
||||
/**
|
||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
||||
@@ -119,11 +100,7 @@ isDeepFrozen(
|
||||
* purely defensive, as we currently do not allow such vaults to be created.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Asset const& asset,
|
||||
std::uint8_t depth = 0);
|
||||
isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||
@@ -257,13 +234,7 @@ requireAuth(
|
||||
AuthType authType = AuthType::Legacy);
|
||||
|
||||
[[nodiscard]] TER
|
||||
canTransfer(
|
||||
ReadView const& view,
|
||||
Asset const& asset,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
WaiveMPTCanTransfer waive = WaiveMPTCanTransfer::No,
|
||||
std::uint8_t depth = 0);
|
||||
canTransfer(ReadView const& view, Asset const& asset, AccountID const& from, AccountID const& to);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -20,7 +19,10 @@ namespace xrpl {
|
||||
@return The number of shares, or nullopt on error.
|
||||
*/
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets);
|
||||
assetsToSharesDeposit(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& assets);
|
||||
|
||||
/** From the perspective of a vault, return the number of assets to take from
|
||||
depositor when they receive a fixed amount of shares. Note, since shares are
|
||||
@@ -33,19 +35,14 @@ assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
|
||||
@return The number of assets, or nullopt on error.
|
||||
*/
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares);
|
||||
sharesToAssetsDeposit(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares);
|
||||
|
||||
/** Controls whether to truncate shares instead of rounding. */
|
||||
enum class TruncateShares : bool { No = false, Yes = true };
|
||||
|
||||
/** Controls whether the withdraw conversion helpers
|
||||
(assetsToSharesWithdraw and sharesToAssetsWithdraw) subtract
|
||||
sfLossUnrealized from sfAssetsTotal before computing the exchange rate.
|
||||
The default (No) applies the standard discounted rate; Yes is used when
|
||||
the redeemer is the sole remaining shareholder.
|
||||
*/
|
||||
enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
|
||||
|
||||
/** From the perspective of a vault, return the number of shares to demand from
|
||||
the depositor when they ask to withdraw a fixed amount of assets. Since
|
||||
shares are MPT this number is integral, and it will be rounded to nearest
|
||||
@@ -55,18 +52,15 @@ enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
|
||||
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||
@param assets The amount of assets to convert.
|
||||
@param truncate Whether to truncate instead of rounding.
|
||||
@param waive Whether to waive the unrealized-loss discount when computing
|
||||
the exchange rate.
|
||||
|
||||
@return The number of shares, or nullopt on error.
|
||||
*/
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
assetsToSharesWithdraw(
|
||||
SLE::const_ref vault,
|
||||
SLE::const_ref issuance,
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& assets,
|
||||
TruncateShares truncate = TruncateShares::No,
|
||||
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
|
||||
TruncateShares truncate = TruncateShares::No);
|
||||
|
||||
/** From the perspective of a vault, return the number of assets to give the
|
||||
depositor when they redeem a fixed amount of shares. Note, since shares are
|
||||
@@ -75,28 +69,13 @@ assetsToSharesWithdraw(
|
||||
@param vault The vault SLE.
|
||||
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||
@param shares The amount of shares to convert.
|
||||
@param waive Whether to waive (i.e. not subtract) the vault's unrealized
|
||||
loss when computing the exchange rate.
|
||||
|
||||
@return The number of assets, or nullopt on error.
|
||||
*/
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
sharesToAssetsWithdraw(
|
||||
SLE::const_ref vault,
|
||||
SLE::const_ref issuance,
|
||||
STAmount const& shares,
|
||||
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
|
||||
|
||||
/** Returns true iff `account` holds all of the vault's outstanding shares —
|
||||
i.e. is the sole remaining shareholder. Returns false if the account
|
||||
holds no shares or fewer than the total outstanding.
|
||||
|
||||
@param view The ledger view.
|
||||
@param account The candidate sole shareholder.
|
||||
@param issuance The MPTokenIssuance SLE for the vault's shares; provides
|
||||
both the share MPTID and the outstanding-amount total.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance);
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -21,13 +21,13 @@ public:
|
||||
bool sslVerify,
|
||||
beast::Journal j,
|
||||
boost::asio::ssl::context_base::method method = boost::asio::ssl::context::sslv23)
|
||||
: sslContext_{method}, j_(j), verify_{sslVerify}
|
||||
: ssl_context_{method}, j_(j), verify_{sslVerify}
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
if (sslVerifyFile.empty())
|
||||
{
|
||||
registerSSLCerts(sslContext_, ec, j_);
|
||||
registerSSLCerts(ssl_context_, ec, j_);
|
||||
|
||||
if (ec && sslVerifyDir.empty())
|
||||
{
|
||||
@@ -37,12 +37,12 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
sslContext_.load_verify_file(sslVerifyFile);
|
||||
ssl_context_.load_verify_file(sslVerifyFile);
|
||||
}
|
||||
|
||||
if (!sslVerifyDir.empty())
|
||||
{
|
||||
sslContext_.add_verify_path(sslVerifyDir, ec);
|
||||
ssl_context_.add_verify_path(sslVerifyDir, ec);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
boost::asio::ssl::context&
|
||||
context()
|
||||
{
|
||||
return sslContext_;
|
||||
return ssl_context_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::ssl::context sslContext_;
|
||||
boost::asio::ssl::context ssl_context_;
|
||||
beast::Journal const j_;
|
||||
bool const verify_;
|
||||
};
|
||||
|
||||
@@ -83,6 +83,10 @@ public:
|
||||
virtual Status
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) = 0;
|
||||
|
||||
/** Fetch a batch synchronously. */
|
||||
virtual std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256> const& hashes) = 0;
|
||||
|
||||
/** Store a single object.
|
||||
Depending on the implementation this may happen immediately
|
||||
or deferred using a scheduled task.
|
||||
|
||||
@@ -131,10 +131,6 @@ public:
|
||||
std::uint32_t ledgerSeq,
|
||||
std::function<void(std::shared_ptr<NodeObject> const&)>&& callback);
|
||||
|
||||
/** Remove expired entries from the positive and negative caches. */
|
||||
virtual void
|
||||
sweep() = 0;
|
||||
|
||||
/** Gather statistics pertaining to read and write activities.
|
||||
*
|
||||
* @param obj Json object reference into which to place counters.
|
||||
|
||||
@@ -22,32 +22,6 @@ public:
|
||||
beast::Journal j)
|
||||
: Database(scheduler, readThreads, config, j), backend_(std::move(backend))
|
||||
{
|
||||
std::optional<int> cacheSize, cacheAge;
|
||||
|
||||
if (config.exists("cache_size"))
|
||||
{
|
||||
cacheSize = get<int>(config, "cache_size");
|
||||
if (cacheSize.value() < 0)
|
||||
Throw<std::runtime_error>("Specified negative value for cache_size");
|
||||
}
|
||||
|
||||
if (config.exists("cache_age"))
|
||||
{
|
||||
cacheAge = get<int>(config, "cache_age");
|
||||
if (cacheAge.value() < 0)
|
||||
Throw<std::runtime_error>("Specified negative value for cache_age");
|
||||
}
|
||||
|
||||
if (cacheSize.has_value() || cacheAge.has_value())
|
||||
{
|
||||
cache_ = std::make_shared<TaggedCache<uint256, NodeObject>>(
|
||||
"DatabaseNodeImp",
|
||||
cacheSize.value_or(0),
|
||||
std::chrono::minutes(cacheAge.value_or(0)),
|
||||
stopwatch(),
|
||||
j);
|
||||
}
|
||||
|
||||
XRPL_ASSERT(
|
||||
backend_,
|
||||
"xrpl::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null "
|
||||
@@ -93,19 +67,16 @@ public:
|
||||
backend_->sync();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<NodeObject>>
|
||||
fetchBatch(std::vector<uint256> const& hashes);
|
||||
|
||||
void
|
||||
asyncFetch(
|
||||
uint256 const& hash,
|
||||
std::uint32_t ledgerSeq,
|
||||
std::function<void(std::shared_ptr<NodeObject> const&)>&& callback) override;
|
||||
|
||||
void
|
||||
sweep() override;
|
||||
|
||||
private:
|
||||
// Cache for database objects. This cache is not always initialized. Check
|
||||
// for null before using.
|
||||
std::shared_ptr<TaggedCache<uint256, NodeObject>> cache_;
|
||||
// Persistent key/value storage
|
||||
std::shared_ptr<Backend> backend_;
|
||||
|
||||
|
||||
@@ -55,9 +55,6 @@ public:
|
||||
void
|
||||
sync() override;
|
||||
|
||||
void
|
||||
sweep() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Backend> writableBackend_;
|
||||
std::shared_ptr<Backend> archiveBackend_;
|
||||
|
||||
@@ -140,8 +140,8 @@ private:
|
||||
using issue_hasher = std::hash<xrpl::Issue>;
|
||||
using mptissue_hasher = std::hash<xrpl::MPTIssue>;
|
||||
|
||||
issue_hasher mIssueHasher_;
|
||||
mptissue_hasher mMptissueHasher_;
|
||||
issue_hasher m_issue_hasher_;
|
||||
mptissue_hasher m_mptissue_hasher_;
|
||||
|
||||
public:
|
||||
explicit hash() = default;
|
||||
@@ -151,11 +151,11 @@ public:
|
||||
{
|
||||
return asset.visit(
|
||||
[&](xrpl::Issue const& issue) {
|
||||
value_type const result(mIssueHasher_(issue));
|
||||
value_type const result(m_issue_hasher_(issue));
|
||||
return result;
|
||||
},
|
||||
[&](xrpl::MPTIssue const& issue) {
|
||||
value_type const result(mMptissueHasher_(issue));
|
||||
value_type const result(m_mptissue_hasher_(issue));
|
||||
return result;
|
||||
});
|
||||
}
|
||||
@@ -170,8 +170,8 @@ private:
|
||||
using asset_hasher = std::hash<xrpl::Asset>;
|
||||
using uint256_hasher = xrpl::uint256::hasher;
|
||||
|
||||
asset_hasher issueHasher_;
|
||||
uint256_hasher uint256Hasher_;
|
||||
asset_hasher issue_hasher_;
|
||||
uint256_hasher uint256_hasher_;
|
||||
|
||||
public:
|
||||
hash() = default;
|
||||
@@ -182,11 +182,11 @@ public:
|
||||
value_type
|
||||
operator()(argument_type const& value) const
|
||||
{
|
||||
value_type result(issueHasher_(value.in));
|
||||
boost::hash_combine(result, issueHasher_(value.out));
|
||||
value_type result(issue_hasher_(value.in));
|
||||
boost::hash_combine(result, issue_hasher_(value.out));
|
||||
|
||||
if (value.domain)
|
||||
boost::hash_combine(result, uint256Hasher_(*value.domain));
|
||||
boost::hash_combine(result, uint256_hasher_(*value.domain));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -172,24 +172,24 @@ struct ErrorInfo
|
||||
{
|
||||
// Default ctor needed to produce an empty std::array during constexpr eval.
|
||||
constexpr ErrorInfo()
|
||||
: code(RpcUnknown), token("unknown"), message("An unknown error code."), httpStatus(200)
|
||||
: code(RpcUnknown), token("unknown"), message("An unknown error code."), http_status(200)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message)
|
||||
: code(code), token(token), message(message), httpStatus(200)
|
||||
: code(code), token(token), message(message), http_status(200)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message, int httpStatus)
|
||||
: code(code), token(token), message(message), httpStatus(httpStatus)
|
||||
: code(code), token(token), message(message), http_status(httpStatus)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorCodeI code;
|
||||
json::StaticString token;
|
||||
json::StaticString message;
|
||||
int httpStatus;
|
||||
int http_status;
|
||||
};
|
||||
|
||||
/** Returns an ErrorInfo that reflects the error code. */
|
||||
|
||||
@@ -251,6 +251,9 @@ constexpr std::uint8_t kVaultMaximumIouScale = 18;
|
||||
* another vault; counted from 0 */
|
||||
constexpr std::uint8_t kMaxAssetCheckDepth = 5;
|
||||
|
||||
/** Maximum length of a Data field in Escrow object that can be updated by WASM code. */
|
||||
constexpr std::size_t kMaxWasmDataLength = 1 * 1024; // 1KB
|
||||
|
||||
/** A ledger index. */
|
||||
using LedgerIndex = std::uint32_t;
|
||||
|
||||
|
||||
@@ -122,17 +122,4 @@ private:
|
||||
std::optional<Rules> saved_;
|
||||
};
|
||||
|
||||
class NumberSO;
|
||||
class NumberMantissaScaleGuard;
|
||||
|
||||
bool
|
||||
useRulesGuards(Rules const& rules);
|
||||
|
||||
void
|
||||
createGuards(
|
||||
Rules const& rules,
|
||||
std::optional<NumberSO>& stNumberSO,
|
||||
std::optional<CurrentTransactionRulesGuard>& rulesGuard,
|
||||
std::optional<NumberMantissaScaleGuard>& mantissaScaleGuard);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -365,8 +365,8 @@ using SF_XCHAIN_BRIDGE = TypedField<STXChainBridge>;
|
||||
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SField const sfName;
|
||||
#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SF_##stiSuffix const sfName;
|
||||
|
||||
extern SField const sfInvalid; // NOLINT(readability-identifier-naming)
|
||||
extern SField const sfGeneric; // NOLINT(readability-identifier-naming)
|
||||
extern SField const kSfInvalid;
|
||||
extern SField const kSfGeneric;
|
||||
|
||||
#include <xrpl/protocol/detail/sfields.macro>
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/basics/LocalValue.h>
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
@@ -186,23 +184,6 @@ public:
|
||||
[[nodiscard]] STAmount const&
|
||||
value() const noexcept;
|
||||
|
||||
/**
|
||||
* Checks if this amount evaluates to zero when constrained to a specific
|
||||
* accounting scale.
|
||||
* For XRP and MPT `roundToScale` is a no-op, returns true only when the amount itself is zero.
|
||||
* The `scale` argument is ignored in that case.
|
||||
* For IOU, the amount is rounded to the given scale using Number::RoundingMode::ToNearest mode
|
||||
* and the result is checked for zero; if `scale <= exponent()`, `roundToScale` short-circuits
|
||||
* and returns the value unchanged, so this returns false for any non-zero amount.
|
||||
*
|
||||
* @param scale The target accounting scale to evaluate against.
|
||||
* @return `true` if this amount rounds to zero at the given scale, `false` otherwise.
|
||||
*
|
||||
* @see roundToScale
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isZeroAtScale(int scale) const;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Operators
|
||||
@@ -559,7 +540,7 @@ STAmount::fromNumber(A const& a, Number const& number)
|
||||
return STAmount{asset, intValue, 0, negative};
|
||||
}
|
||||
|
||||
auto const [mantissa, exponent] = working.normalizeToRange<kMinValue, kMaxValue>();
|
||||
auto const [mantissa, exponent] = working.normalizeToRange(kMinValue, kMaxValue);
|
||||
|
||||
return STAmount{asset, mantissa, exponent, negative};
|
||||
}
|
||||
@@ -594,25 +575,12 @@ STAmount::value() const noexcept
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
inline bool
|
||||
isLegalNet(STAmount const& value)
|
||||
{
|
||||
return !value.native() || (value.mantissa() <= STAmount::kMaxNativeN);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isLegalMPT(STAmount const& value)
|
||||
{
|
||||
return !value.holds<MPTIssue>() ||
|
||||
(!value.negative() && value.exponent() == 0 && value.mantissa() <= kMaxMpTokenAmount);
|
||||
}
|
||||
|
||||
/* Check recursively if an object has invalid MPTAmount or XRPAmount in STAmount field.
|
||||
* Calls isLegalNet() and isLegalMPT().
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
hasInvalidAmount(STBase const& field, beast::Journal j);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Operators
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
STBlob(SField const& f, void const* data, std::size_t size);
|
||||
STBlob(SField const& f, Buffer&& b);
|
||||
STBlob(SField const& n);
|
||||
STBlob(SerialIter&, SField const& name = sfGeneric);
|
||||
STBlob(SerialIter&, SField const& name = kSfGeneric);
|
||||
|
||||
[[nodiscard]] std::size_t
|
||||
size() const;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user