Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ $(COV_TOOL_WRAPPER):
@chmod +x $(COV_TOOL_WRAPPER)

baseline.info: $(COV_TOOL_WRAPPER)
$(LCOV) -c -i -d $(abs_builddir)/src -o $@
$(LCOV) $(LCOV_OPTS) -c -i -d $(abs_builddir)/src -o $@

baseline_filtered.info: baseline.info
$(abs_builddir)/contrib/filter-lcov.py $(LCOV_FILTER_PATTERN) $< $@
Expand Down Expand Up @@ -221,13 +221,13 @@ functional_test_filtered.info: functional_test.info
$(LCOV) -a $@ $(LCOV_OPTS) -o $@

fuzz_coverage.info: fuzz_filtered.info
$(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a fuzz_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
$(LCOV) $(LCOV_OPTS) -a baseline_filtered.info -a fuzz_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt

test_dash_coverage.info: baseline_filtered.info test_dash_filtered.info
$(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a test_dash_filtered.info -o $@
$(LCOV) $(LCOV_OPTS) -a baseline_filtered.info -a test_dash_filtered.info -o $@

total_coverage.info: test_dash_filtered.info functional_test_filtered.info
$(LCOV) -a $(LCOV_OPTS) baseline_filtered.info -a test_dash_filtered.info -a functional_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
$(LCOV) $(LCOV_OPTS) -a baseline_filtered.info -a test_dash_filtered.info -a functional_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt

fuzz.coverage/.dirstamp: fuzz_coverage.info
$(GENHTML) -s $(LCOV_OPTS) $< -o $(@D)
Expand Down
11 changes: 11 additions & 0 deletions ci/lint/04_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ if [ -z "${SKIP_PYTHON_INSTALL}" ]; then
python3 --version
fi

export LINT_RUNNER_PATH="/lint_test_runner"
if [ ! -d "${LINT_RUNNER_PATH}" ]; then
${CI_RETRY_EXE} apt-get install -y cargo
(
cd ./test/lint/test_runner || exit 1
cargo build
mkdir -p "${LINT_RUNNER_PATH}"
mv target/debug/test_runner "${LINT_RUNNER_PATH}"
)
Comment on lines +37 to +44
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Check for the executable, not just the directory.

Line 37 only checks -d "${LINT_RUNNER_PATH}". If the directory exists but test_runner is missing (e.g., prior partial run), the build is skipped and downstream execution fails. Guard on the binary path (-x) instead.

Suggested fix
 export LINT_RUNNER_PATH="/lint_test_runner"
-if [ ! -d "${LINT_RUNNER_PATH}" ]; then
+if [ ! -x "${LINT_RUNNER_PATH}/test_runner" ]; then
   ${CI_RETRY_EXE} apt-get install -y cargo
   (
     cd ./test/lint/test_runner || exit 1
     cargo build
     mkdir -p "${LINT_RUNNER_PATH}"
-    mv target/debug/test_runner "${LINT_RUNNER_PATH}"
+    mv target/debug/test_runner "${LINT_RUNNER_PATH}/test_runner"
   )
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ci/lint/04_install.sh` around lines 37 - 44, The script currently tests only
if the LINT_RUNNER_PATH directory exists, which misses the case where the
test_runner binary is absent; update the guard to check the executable itself
(use -x on the binary path, e.g. "${LINT_RUNNER_PATH}/test_runner" or ensure
LINT_RUNNER_PATH points to the binary) so the cargo build and mv steps run when
the binary is missing; adjust surrounding logic that creates the directory
(mkdir -p) and the subsequent mv target/debug/test_runner to work with the new
executable-path check and keep using CI_RETRY_EXE for apt-get as before.

fi

# NOTE: BUMP ALSO contrib/containers/ci/ci-slim.Dockerfile
${CI_RETRY_EXE} pip3 install codespell==2.2.1
${CI_RETRY_EXE} pip3 install flake8==5.0.4
Expand Down
1 change: 1 addition & 0 deletions ci/lint/06_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ test/lint/git-subtree-check.sh src/crypto/ctaes
test/lint/git-subtree-check.sh src/secp256k1
test/lint/git-subtree-check.sh src/minisketch
test/lint/git-subtree-check.sh src/leveldb
RUST_BACKTRACE=1 "${LINT_RUNNER_PATH}/test_runner"
test/lint/check-doc.py
test/lint/all-lint.py

Expand Down
2 changes: 2 additions & 0 deletions ci/lint/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export LC_ALL=C
# of the mounted bitcoin src dir.
git config --global --add safe.directory /bitcoin

export LINT_RUNNER_PATH="/lint_test_runner"

if [ -z "$1" ]; then
LOCAL_BRANCH=1 bash -ic "./ci/lint/06_script.sh"
else
Expand Down
1 change: 1 addition & 0 deletions ci/test/00_setup_env_native_fuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=true
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --enable-fuzz --with-sanitizers=fuzzer,address,undefined,integer CC='clang-19 -ftrivial-auto-var-init=pattern' CXX='clang++-19 -ftrivial-auto-var-init=pattern'"
export LLVM_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-17"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect compiler and symbolizer pins in the changed CI setup script.
rg -n 'BITCOIN_CONFIG|LLVM_SYMBOLIZER_PATH|clang-[0-9]+|llvm-symbolizer-[0-9]+' ci/test/00_setup_env_native_fuzz.sh -C1

# Extract and compare major versions (read-only check).
python - <<'PY'
import re
from pathlib import Path

p = Path("ci/test/00_setup_env_native_fuzz.sh").read_text()
clang = re.search(r"clang-(\d+)", p)
symbolizer = re.search(r"llvm-symbolizer-(\d+)", p)

print("clang_major =", clang.group(1) if clang else "not found")
print("symbolizer_major =", symbolizer.group(1) if symbolizer else "not found")

if clang and symbolizer and clang.group(1) != symbolizer.group(1):
    print("RESULT: version mismatch detected (needs explicit justification).")
else:
    print("RESULT: no major-version mismatch detected in this file.")
PY

Repository: dashpay/dash

Length of output: 446


Address LLVM version mismatch and verify CI-scope approval.

Line 19 pins llvm-symbolizer-17 while line 18 compiles with clang-19. This major-version mismatch between the compiler and symbolizer can degrade stack trace quality during fuzzing and sanitizer reporting. Additionally, this change modifies the ci/** directory, which per coding guidelines should not be changed unless explicitly prompted. Confirm that this CI modification is in scope and that the symbolizer version mismatch is intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ci/test/00_setup_env_native_fuzz.sh` at line 19, The export of
LLVM_SYMBOLIZER_PATH points to llvm-symbolizer-17 while the build uses clang-19
(mismatched major versions), and changes to ci/** require explicit scope
approval; update the symbolizer to match the compiler (e.g., set
LLVM_SYMBOLIZER_PATH to llvm-symbolizer-19) or make the clang invocation use
clang-17 so versions align, and add a brief CI note or PR description confirming
that modifying files under ci/** is authorized by the team/CI owners; locate the
assignment to LLVM_SYMBOLIZER_PATH and the clang-19 invocation in the script and
adjust one of them (or add an approval comment) to resolve the mismatch and
policy concern.

5 changes: 2 additions & 3 deletions contrib/devtools/circular-dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import sys
import re
from multiprocess import Pool # type: ignore[import]
from typing import Dict, List, Set

MAPPING = {
'core_read.cpp': 'core_io.cpp',
Expand Down Expand Up @@ -35,7 +34,7 @@ def module_name(path):

if __name__=="__main__":
files = dict()
deps: Dict[str, Set[str]] = dict()
deps: dict[str, set[str]] = dict()

RE = re.compile("^#include <(.*)>")

Expand All @@ -49,7 +48,7 @@ def handle_module(arg):

def handle_module2(module):
# Build the transitive closure of dependencies of module
closure: Dict[str, List[str]] = dict()
closure: dict[str, list[str]] = dict()
for dep in deps[module]:
closure[dep] = []
while True:
Expand Down
3 changes: 1 addition & 2 deletions contrib/devtools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
import shutil
import sys
import os
from typing import List


def determine_wellknown_cmd(envvar, progname) -> List[str]:
def determine_wellknown_cmd(envvar, progname) -> list[str]:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Contrib-path modification needs explicit scope approval.

Line 13 changes contrib/devtools/utils.py, but this PR context does not explicitly document an exception for contrib/** edits. Please confirm and document that this directory is intentionally in-scope for this backport.

As per coding guidelines, "Do not make changes to build system files (guix-build*), release artifacts, or avoid changes to .github, depends, ci, contrib, and doc directories unless specifically prompted".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contrib/devtools/utils.py` at line 13, This change touches
contrib/devtools/utils.py (function determine_wellknown_cmd) which per
guidelines requires explicit scope approval; update the PR description or
backport metadata to state that modifications under contrib/ are intentional and
approved, and include a short justification and the approver's identifier (e.g.,
maintainer or release manager) so reviewers can verify the exception, and
optionally add a one-line comment above determine_wellknown_cmd noting the
accepted contrib-path change for future readers.

maybe_env = os.getenv(envvar)
maybe_which = shutil.which(progname)
if maybe_env:
Expand Down
3 changes: 1 addition & 2 deletions contrib/guix/security-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
'''
import re
import sys
from typing import List

import lief

Expand Down Expand Up @@ -277,7 +276,7 @@ def check_MACHO_BRANCH_PROTECTION(binary) -> bool:
arch = binary.abstract.header.architecture
binary.concrete

failed: List[str] = []
failed: list[str] = []
for (name, func) in CHECKS[etype][arch]:
if not func(binary):
failed.append(name)
Expand Down
7 changes: 3 additions & 4 deletions contrib/guix/symbol-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
find ../path/to/guix/binaries -type f -executable | xargs python3 contrib/guix/symbol-check.py
'''
import sys
from typing import Dict, List

import lief

Expand Down Expand Up @@ -50,7 +49,7 @@

# Expected linker-loader names can be found here:
# https://sourceware.org/glibc/wiki/ABIList?action=recall&rev=16
ELF_INTERPRETER_NAMES: Dict[lief.ELF.ARCH, Dict[lief.ENDIANNESS, str]] = {
ELF_INTERPRETER_NAMES: dict[lief.ELF.ARCH, dict[lief.ENDIANNESS, str]] = {
lief.ELF.ARCH.x86_64: {
lief.ENDIANNESS.LITTLE: "/lib64/ld-linux-x86-64.so.2",
},
Expand All @@ -69,7 +68,7 @@
},
}

ELF_ABIS: Dict[lief.ELF.ARCH, Dict[lief.ENDIANNESS, List[int]]] = {
ELF_ABIS: dict[lief.ELF.ARCH, dict[lief.ENDIANNESS, list[int]]] = {
lief.ELF.ARCH.x86_64: {
lief.ENDIANNESS.LITTLE: [3,2,0],
},
Expand Down Expand Up @@ -303,7 +302,7 @@ def check_ELF_ABI(binary) -> bool:
binary = lief.parse(filename)
etype = binary.format

failed: List[str] = []
failed: list[str] = []
for (name, func) in CHECKS[etype]:
if not func(binary):
failed.append(name)
Expand Down
6 changes: 3 additions & 3 deletions contrib/macdeploy/macdeployqtplus
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import sys, re, os, platform, shutil, stat, subprocess, os.path
from argparse import ArgumentParser
from pathlib import Path
from subprocess import PIPE, run
from typing import List, Optional
from typing import Optional

# This is ported from the original macdeployqt with modifications

Expand Down Expand Up @@ -181,7 +181,7 @@ class DeploymentInfo(object):
return True
return False

def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
def getFrameworks(binaryPath: str, verbose: int) -> list[FrameworkInfo]:
objdump = os.getenv("OBJDUMP", "objdump")
if verbose:
print(f"Inspecting with {objdump}: {binaryPath}")
Expand Down Expand Up @@ -285,7 +285,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional

return toPath

def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPath: str, strip: bool, verbose: int, deploymentInfo: Optional[DeploymentInfo] = None) -> DeploymentInfo:
def deployFrameworks(frameworks: list[FrameworkInfo], bundlePath: str, binaryPath: str, strip: bool, verbose: int, deploymentInfo: Optional[DeploymentInfo] = None) -> DeploymentInfo:
if deploymentInfo is None:
deploymentInfo = DeploymentInfo()

Expand Down
6 changes: 3 additions & 3 deletions contrib/message-capture/message-capture-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from io import BytesIO
import json
from pathlib import Path
from typing import Any, List, Optional
from typing import Any, Optional
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check Python version requirements across the project

# Check for python_requires in setup files
fd -e py -e cfg -e toml -e txt 'setup|pyproject|requirements|README' --exec rg -n 'python_requires|Python [0-9]|python.*3\.[0-9]+' {}

# Check shebang lines for version hints
rg -n '^#!/usr/bin/env python3\.[0-9]+' --type py

# Check for other uses of built-in generics (list[], dict[])
rg -n 'def.*:\s*(list|dict)\[' --type py | head -20

Repository: dashpay/dash

Length of output: 814


🌐 Web query:

Python 3.9 PEP 585 built-in generic types support

💡 Result:

PEP 585 introduces support for using built-in collection types like list, dict, tuple, set, frozenset, and type as generics directly in type hints in Python 3.9, without needing to import equivalents from the typing module (e.g., list[str] instead of typing.List[str]). This uses class_getitem for parameterization, available at runtime. Importing the typing versions is deprecated for Python 3.9+, with removal planned after Python 3.9's end-of-life in October 2025. Other collections like collections.deque and collections.defaultdict also gain generic support. Type checkers must recognize these, and with from future import annotations (since 3.7), this works in annotations earlier. Example: def greet_all(names: list[str]) -> None: ...

Citations:


Remove built-in generic syntax or add future annotations import to maintain Python 3.7+ compatibility.

The changes use PEP 585 syntax (list[Any]) which requires Python 3.9+, but the project minimum version is Python 3.7+ per setup.py. This breaks compatibility with Python 3.7 and 3.8. Either revert to typing.List, or add from __future__ import annotations at the top of the file to enable this syntax on earlier versions.

Additionally, changes to contrib/ directory should be avoided unless specifically prompted per coding guidelines.

Also applies to: 95-95, 192-192

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contrib/message-capture/message-capture-parser.py` at line 14, The file uses
PEP 585 generics (e.g., list[Any]) which breaks Python 3.7/3.8 compatibility and
touches the contrib directory; either add "from __future__ import annotations"
as the first import in the module to allow built-in generics on older Pythons,
or revert to typing generics by importing List/Dict/etc. from typing and replace
occurrences of list[Any] at the locations referenced (around the existing "from
typing import Any, Optional" import and usages near lines 95 and 192) with
typing.List/typing.Dict forms; also undo any unnecessary edits to the contrib/
directory unless this change was explicitly requested.


sys.path.append(os.path.join(os.path.dirname(__file__), '../../test/functional'))

Expand Down Expand Up @@ -92,7 +92,7 @@ def to_jsonable(obj: Any) -> Any:
return obj


def process_file(path: str, messages: List[Any], recv: bool, progress_bar: Optional[ProgressBar]) -> None:
def process_file(path: str, messages: list[Any], recv: bool, progress_bar: Optional[ProgressBar]) -> None:
with open(path, 'rb') as f_in:
if progress_bar:
bytes_read = 0
Expand Down Expand Up @@ -189,7 +189,7 @@ def main():
output = Path.cwd() / Path(args.output) if args.output else False
use_progress_bar = (not args.no_progress_bar) and sys.stdout.isatty()

messages = [] # type: List[Any]
messages = [] # type: list[Any]
if use_progress_bar:
total_size = sum(capture.stat().st_size for capture in capturepaths)
progress_bar = ProgressBar(total_size)
Expand Down
20 changes: 10 additions & 10 deletions contrib/seeds/makeseeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import collections
import json
import multiprocessing
from typing import List, Dict, Union
from typing import Union

NSEEDS=512

Expand Down Expand Up @@ -76,28 +76,28 @@ def parseip(ip_in: str) -> Union[dict, None]:
"sortkey": sortkey
}

def filtermulticollateralhash(mns : List[Dict]) -> List[Dict]:
def filtermulticollateralhash(mns : list[dict]) -> list[dict]:
'''Filter out MNs sharing the same collateral hash'''
hist = collections.defaultdict(list)
for mn in mns:
hist[mn['collateralHash']].append(mn)
return [mn for mn in mns if len(hist[mn['collateralHash']]) == 1]

def filtermulticollateraladdress(mns : List[Dict]) -> List[Dict]:
def filtermulticollateraladdress(mns : list[dict]) -> list[dict]:
'''Filter out MNs sharing the same collateral address'''
hist = collections.defaultdict(list)
for mn in mns:
hist[mn['collateralAddress']].append(mn)
return [mn for mn in mns if len(hist[mn['collateralAddress']]) == 1]

def filtermultipayoutaddress(mns : List[Dict]) -> List[Dict]:
def filtermultipayoutaddress(mns : list[dict]) -> list[dict]:
'''Filter out MNs sharing the same payout address'''
hist = collections.defaultdict(list)
for mn in mns:
hist[mn['state']['payoutAddress']].append(mn)
return [mn for mn in mns if len(hist[mn['state']['payoutAddress']]) == 1]

def resolveasn(resolver, ip : Dict) -> Union[int, None]:
def resolveasn(resolver, ip : dict) -> Union[int, None]:
""" Look up the asn for an `ip` address by querying cymru.com
on network `net` (e.g. ipv4 or ipv6).

Expand All @@ -124,7 +124,7 @@ def resolveasn(resolver, ip : Dict) -> Union[int, None]:
return None

# Based on Greg Maxwell's seed_filter.py
def filterbyasn(ips: List[Dict], max_per_asn: Dict, max_per_net: int) -> List[Dict]:
def filterbyasn(ips: list[dict], max_per_asn: dict, max_per_net: int) -> list[dict]:
""" Prunes `ips` by
(a) trimming ips to have at most `max_per_net` ips from each net (e.g. ipv4, ipv6); and
(b) trimming ips to have at most `max_per_asn` ips from each asn in each net.
Expand All @@ -144,8 +144,8 @@ def filterbyasn(ips: List[Dict], max_per_asn: Dict, max_per_net: int) -> List[Di

# Filter IPv46 by ASN, and limit to max_per_net per network
result = []
net_count: Dict[str, int] = collections.defaultdict(int)
asn_count: Dict[int, int] = collections.defaultdict(int)
net_count: dict[str, int] = collections.defaultdict(int)
asn_count: dict[int, int] = collections.defaultdict(int)

for i, ip in enumerate(ips_ipv46):
if i % 10 == 0:
Expand All @@ -169,9 +169,9 @@ def filterbyasn(ips: List[Dict], max_per_asn: Dict, max_per_net: int) -> List[Di
result.extend(ips_onion[0:max_per_net])
return result

def ip_stats(ips: List[Dict]) -> str:
def ip_stats(ips: list[dict]) -> str:
""" Format and return pretty string from `ips`. """
hist: Dict[str, int] = collections.defaultdict(int)
hist: dict[str, int] = collections.defaultdict(int)
for ip in ips:
if ip is not None:
hist[ip['net']] += 1
Expand Down
1 change: 1 addition & 0 deletions src/.clang-tidy
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Checks: '
-*,
bugprone-argument-comment,
bugprone-string-constructor,
bugprone-use-after-move,
misc-unused-using-decls,
modernize-use-default-member-init,
Expand Down
7 changes: 5 additions & 2 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -489,11 +489,14 @@ SECONDARY: $(QT_QM)

$(srcdir)/qt/dashstrings.cpp: FORCE
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
$(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
$(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py \
$(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) \
$(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) \
$(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)

# The resulted dash_en.xlf source file should follow Transifex requirements.
# See: https://docs.transifex.com/formats/xliff#how-to-distinguish-between-a-source-file-and-a-translation-file
translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Duplicate $(QT_FORMS_UI) in prerequisites.

$(QT_FORMS_UI) appears twice in the prerequisites list. While Make handles duplicates gracefully, this appears to be an oversight and should be cleaned up.

🔧 Proposed fix
-translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
+translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Makefile.qt.include` at line 499, Remove the duplicate prerequisite by
editing the translate target to list $(QT_FORMS_UI) only once; locate the
translate target definition (the line starting with "translate:") and remove the
extra $(QT_FORMS_UI) token so the prerequisite list contains a single reference
to $(QT_FORMS_UI), leaving other prerequisites (e.g.,
$(srcdir)/qt/dashstrings.cpp, $(BITCOIN_QT_BASE_CPP), $(BITCOIN_QT_WINDOWS_CPP),
$(BITCOIN_QT_WALLET_CPP), $(BITCOIN_QT_H), $(BITCOIN_MM)) unchanged.

@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) -no-obsolete -I $(srcdir) -locations relative $^ -ts $(srcdir)/qt/locale/dash_en.ts
@test -n $(LCONVERT) || echo "lconvert is required for updating translations"
Expand Down
1 change: 1 addition & 0 deletions src/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ static inline path PathFromString(const std::string& string)
* already exists or is a symlink to an existing directory.
* This is a temporary workaround for an issue in libstdc++ that has been fixed
* upstream [PR101510].
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101510
*/
static inline bool create_directories(const std::filesystem::path& p)
{
Expand Down
12 changes: 12 additions & 0 deletions src/test/util/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ static const CScript P2SH_OP_TRUE{
<< ToByteVector(CScriptID{CScript{} << OP_TRUE})
<< OP_EQUAL};

static const std::vector<uint8_t> EMPTY{};
static const CScript P2WSH_EMPTY{
CScript{}
<< OP_0
<< ToByteVector([] {
uint256 hash;
CSHA256().Write(EMPTY.data(), EMPTY.size()).Finalize(hash.begin());
return hash;
}())};
static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TRUE_STACK{{static_cast<uint8_t>(OP_TRUE)}, {}};
static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TWO_STACK{{static_cast<uint8_t>(OP_2)}, {}};

/** Flags that are not forbidden by an assert in script validation */
bool IsValidFlagCombination(unsigned flags);

Expand Down
4 changes: 2 additions & 2 deletions src/wallet/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ bool IsSQLiteFile(const fs::path& path)

file.close();

// Check the magic, see https://sqlite.org/fileformat2.html
// Check the magic, see https://sqlite.org/fileformat.html
std::string magic_str(magic, 16);
if (magic_str != std::string("SQLite format 3", 16)) {
if (magic_str != std::string{"SQLite format 3\000", 16}) {
return false;
}

Expand Down
25 changes: 25 additions & 0 deletions src/wallet/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#include <wallet/transaction.h>

#include <interfaces/chain.h>

using interfaces::FoundBlock;

namespace wallet {
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
{
Expand All @@ -24,4 +28,25 @@ int64_t CWalletTx::GetTxTime() const
int64_t n = nTimeSmart;
return n ? n : nTimeReceived;
}

void CWalletTx::updateState(interfaces::Chain& chain)
{
bool active;
auto lookup_block = [&](const uint256& hash, int& height, TxState& state) {
// If tx block (or conflicting block) was reorged out of chain
// while the wallet was shutdown, change tx status to UNCONFIRMED
// and reset block height, hash, and index. ABANDONED tx don't have
// associated blocks and don't need to be updated. The case where a
// transaction was reorged out while online and then reconfirmed
// while offline is covered by the rescan logic.
if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) {
state = TxStateInactive{};
}
};
if (auto* conf = state<TxStateConfirmed>()) {
lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state);
} else if (auto* conf = state<TxStateConflicted>()) {
lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state);
}
}
} // namespace wallet
Loading
Loading