backport: Merge bitcoin/bitcoin#28857 , 29458, 29236, 29633, 29459, 29479, 29615, 29433#7292
backport: Merge bitcoin/bitcoin#28857 , 29458, 29236, 29633, 29459, 29479, 29615, 29433#7292vijaydasmp wants to merge 8 commits intodashpay:developfrom
Conversation
|
1e5b861 test: Add test for array serialization (TheCharlatan) d49d198 refactor: Initialize magic bytes in constructor initializer (TheCharlatan) Pull request description: This is a followup-PR for bitcoin#28423 * Initialize magic bytes in constructor * Add a small unit test for serializing arrays. ACKs for top commit: sipa: utACK 1e5b861 maflcko: lgtm ACK 1e5b861 Tree-SHA512: 0f58d2332dc501ca9fd419f40ed4f977c83dce0169e9a0eee1ffc9f8daa2d2ef7e7df18205ba076f55d90ae6c4a20d2b51ab303150d38470a962bcc58a66f6e7
…void resizing a19235c Preallocate result in `TryParseHex` to avoid resizing (Lőrinc) b7489ec Add benchmark for TryParseHex (Lőrinc) Pull request description: This pull request introduces optimizations to the `TryParseHex` function, focusing primarily on the ideal case (valid hexadecimal input without spaces). A new benchmark, `HexParse` was introduced in a separate commit. The main optimization preallocates the result vector based on the input string's length. This aims to completely avoid costly dynamic reallocations when no spaces are present. ------------ Before: ``` | ns/base16 | base16/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 1.60 | 623,238,893.11 | 0.3% | 0.01 | `HexParse` | 1.65 | 606,747,566.34 | 0.6% | 0.01 | `HexParse` | 1.60 | 626,149,544.07 | 0.3% | 0.01 | `HexParse` ``` After: ``` | ns/base16 | base16/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 0.68 | 1,465,555,976.27 | 0.8% | 0.01 | `HexParse` | 0.68 | 1,472,962,920.18 | 0.3% | 0.01 | `HexParse` | 0.68 | 1,476,159,423.00 | 0.3% | 0.01 | `HexParse` ``` ACKs for top commit: achow101: ACK a19235c hebasto: ACK a19235c. andrewtoth: Re-ACK a19235c Empact: Re-ACK bitcoin@a19235c Tree-SHA512: e09a59791104be3fd1026862ce98de9efafa1f949626fa01e3b7d58e6a2ef02a11f0de55ddba5c43230a53effd24e6d368c1e12848b17e8ce91d7908a59333f0
fa39151 refactor: Remove unused error() (MarcoFalke) fad0335 scripted-diff: Replace error() with LogError() (MarcoFalke) fa808fb refactor: Make error() return type void (MarcoFalke) fa1d624 scripted-diff: return error(...); ==> error(...); return false; (MarcoFalke) fa9a5e8 refactor: Add missing {} around error() calls (MarcoFalke) Pull request description: `error(...)` has many issues: * It is often used in the context of `return error(...)`, implying that it has a "fancy" type, creating confusion with `util::Result/Error` * `-logsourcelocations` does not work with it, because it will pretend the error happened inside of `logging.h` * The log line contains `ERROR: `, as opposed to `[error]`, like for other errors logged with `LogError`. Fix all issues by removing it. ACKs for top commit: fjahr: re-utACK fa39151 stickies-v: re-ACK fa39151, no changes since 4a90374 ryanofsky: Code review ACK fa39151. Just rebase since last review Tree-SHA512: ec5bb502ab0d3733fdb14a8a00762638fce0417afd8dd6294ae0d485ce2b7ca5b1efeb50fc2cd7467f6c652e4ed3e99b0f283b08aeca04bbfb7ea4f2c95d283a Rebase and fixing blockstorage.cpp file src/validation.cpp - Fixing linting error
d0e6564 log: Remove error() reference (Fabian Jahr) Pull request description: Mini-followup to bitcoin#29236 that was just merged. Removes a reference to `error()` that was missed in a comment. ACKs for top commit: ryanofsky: Code review ACK d0e6564. Just dropped LogPrintf reference since last review stickies-v: ACK d0e6564 Empact: ACK bitcoin@d0e6564 Tree-SHA512: 8abe4895951013c2ceca9a57743aacabaf8af831d07eee9ae8372c121c16e88b7226f0e537200c3464792e19ac7e03b57ba0be31f43add8802753972b0aefc48
bf264e0 test: check_mempool_result negative feerate (kevkevin) Pull request description: Adds test coverage in `mempool_accept.py` to check if a negative `maxfeerate` is input into `check_mempool_result` Asserts "Amount out of range" error message and `-3` error code Motivated by this [comment](https://github.com/bitcoin/bitcoin/pull/29434/files#r1491112250) ACKs for top commit: maflcko: lgtm ACK bf264e0 brunoerg: nice, utACK bf264e0 davidgumberg: Looks great, ACK bitcoin@bf264e0 Tree-SHA512: 58931b774cc887c616f2fd91af3ee65cc5db55acd8e2875c76de448c80bd4e020b057c5f4f85556431377f0d0e7553771fb285d1ec20cf64f64ec92a47776b78
80fa7da test: Refactor subtree exclusion in lint tests (Brandon Odiwuor) Pull request description: Fixes bitcoin#17413 Refactor subtree exclusion in lint tests to one place Second attempt after PR: bitcoin#24435 ACKs for top commit: fjahr: re-ACK 80fa7da maflcko: lgtm ACK 80fa7da davidgumberg: ACK bitcoin@80fa7da Tree-SHA512: deff7457dd19ca5ea440d3d53feae047e8863b9ddeb6494a3c94605a5d16edc91db8f99a435b4fab2ef89aedee42439562be006da647fb85bbf3def903a3ce50
… add unit test 3e9c736 test: fix accurate multisig sigop count (BIP16), add unit test (Sebastian Falbesoner) Pull request description: In the course of reviewing bitcoin#29589 I noticed the following buggy call-site of `CScriptOp.decode_op_n` in the CScript's `GetSigOpCount` method: https://github.com/bitcoin/bitcoin/blob/4cc99df44aec4d104590aee46cf18318e22a8568/test/functional/test_framework/script.py#L591-L593 This should be `lastOpcode` rather than `opcode`. The latter is either OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY at this point, so `decode_op_n` would result in an error. Also, in `CScript.raw_iter`, we have to return the op as `CScriptOp` type instead of a bare integer, otherwise we can't call the decode method on it. To prevent this in the future, add some simple unit tests for `GetSigOpCount`. Note that this was unnoticed, as the code part was never hit so far in the test framework. ACKs for top commit: achow101: ACK 3e9c736 Christewart: ACK 3e9c736 rkrux: tACK [3e9c736](bitcoin@3e9c736) hernanmarino: tACK 3e9c736 Tree-SHA512: 51647bb6d462fbd101effd851afdbd6ad198c0567888cd4fdcac389a9fb4bd3d7e648095c6944fd8875d36272107ebaabdc62d0e2423289055588c12294d05a7
…output text in json format 9adf949 contrib: rpcauth.py - Add new option (-j/--json) to output text in json format (bstin) Pull request description: This is a simple change to rpcauth.py utility in order to output as json instead raw text. This is beneficial because integrating json output is simpler with multiple different forms of automation and tooling ACKs for top commit: maflcko: ACK 9adf949 achow101: ACK 9adf949 willcl-ark: tACK 9adf949 tdb3: ACK for 9adf949 Tree-SHA512: 2cdc3b2071fbe4fb32a84ce42ee8ad216cff96ed82aaef58daeb3991953ac137ae42d6898a7fdb6cbd1800e1f61ff8d292f0b150eaebdd2a3fd9d37ed7450787
|
🕓 Ready for review — 7 ahead in queue (commit 11dde62) |
WalkthroughThis pull request introduces a new Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
test/lint/lint-includes.py (1)
20-26: ⚡ Quick winDeduplicate
EXCLUDED_DIRSnow that shared exclusions are imported.Line 20-23 duplicates paths already provided by
SHARED_EXCLUDED_SUBTREES, leaving two sources of truth.Proposed refactor
-EXCLUDED_DIRS = ["src/leveldb/", - "src/crc32c/", - "src/secp256k1/", - "src/minisketch/", - "src/dashbls/", - "src/immer/", - "src/crypto/x11/"] + SHARED_EXCLUDED_SUBTREES +EXCLUDED_DIRS = [ + "src/dashbls/", + "src/immer/", + "src/crypto/x11/", +] + SHARED_EXCLUDED_SUBTREES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/lint/lint-includes.py` around lines 20 - 26, The EXCLUDED_DIRS list duplicates paths that are already present in SHARED_EXCLUDED_SUBTREES; update the definition of EXCLUDED_DIRS to avoid redundant entries by removing the hardcoded directory strings and simply compose EXCLUDED_DIRS from any unique local exclusions (if any) plus SHARED_EXCLUDED_SUBTREES, ensuring EXCLUDED_DIRS references SHARED_EXCLUDED_SUBTREES (symbol names: EXCLUDED_DIRS, SHARED_EXCLUDED_SUBTREES) so there is a single source of truth for shared exclusions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/node/blockstorage.cpp`:
- Around line 807-810: In ReadBlockFromDisk (the branch that currently does
`return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match
index for %s at %s", pindex->ToString(), block_pos.ToString()); return false;`)
remove the unreachable `return false;` and instead replace the `return
error(...)` call with a logging call (e.g., LogError or the project's LogPrint
equivalent) that emits the same message using pindex->ToString() and
block_pos.ToString(), then follow it with `return false;` so the branch matches
the LogError(...); return false; pattern used elsewhere.
In `@src/validation.cpp`:
- Around line 2484-2488: The LogError call after Consensus::CheckTxInputs is
logging state.ToString() which is incorrect because the CheckTxInputs failure
details are in tx_state; update the LogError invocation in the ConnectBlock
error branch to include tx_state.ToString() (and/or
tx_state.GetRejectReason()/GetDebugMessage() if you prefer more detail) so the
actual transaction rejection reason from CheckTxInputs is recorded before
returning state.Invalid; keep the existing return that uses tx_state for the
reject reason/debug message.
In `@test/lint/lint-spelling.py`:
- Line 18: The list comprehension uses the loop variable named dir which shadows
the built-in dir() and triggers Ruff A001; update the variable name in the
expression that builds FILES_ARGS (the comprehension referencing
SHARED_EXCLUDED_SUBTREES) to a non-built-in name like subtree or subdir so it no
longer shadows the built-in (e.g., replace occurrences of dir inside the
comprehension with subtree).
---
Nitpick comments:
In `@test/lint/lint-includes.py`:
- Around line 20-26: The EXCLUDED_DIRS list duplicates paths that are already
present in SHARED_EXCLUDED_SUBTREES; update the definition of EXCLUDED_DIRS to
avoid redundant entries by removing the hardcoded directory strings and simply
compose EXCLUDED_DIRS from any unique local exclusions (if any) plus
SHARED_EXCLUDED_SUBTREES, ensuring EXCLUDED_DIRS references
SHARED_EXCLUDED_SUBTREES (symbol names: EXCLUDED_DIRS, SHARED_EXCLUDED_SUBTREES)
so there is a single source of truth for shared exclusions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 4c0b72be-d976-4838-b731-76d2d55c7508
📒 Files selected for processing (26)
share/rpcauth/README.mdshare/rpcauth/rpcauth.pysrc/Makefile.bench.includesrc/addrdb.cppsrc/bench/parse_hex.cppsrc/flatfile.cppsrc/index/base.cppsrc/index/blockfilterindex.cppsrc/index/coinstatsindex.cppsrc/index/txindex.cppsrc/kernel/coinstats.cppsrc/logging.hsrc/net.cppsrc/netbase.cppsrc/node/blockstorage.cppsrc/script/signingprovider.cppsrc/test/serialize_tests.cppsrc/util/strencodings.cppsrc/validation.cpptest/functional/mempool_accept.pytest/functional/test_framework/script.pytest/lint/README.mdtest/lint/lint-include-guards.pytest/lint/lint-includes.pytest/lint/lint-spelling.pytest/lint/lint_ignore_dirs.py
| return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", | ||
| pindex->ToString(), block_pos.ToString()); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Remove unreachable return and complete the error() cleanup in this branch.
At Line 807, return error(...); makes Line 809 unreachable. Convert this branch to the same LogError(...); return false; pattern used in this PR.
Suggested fix
- if (*hash != pindex->GetBlockHash()) {
- return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
- pindex->ToString(), block_pos.ToString());
- return false;
- }
+ if (*hash != pindex->GetBlockHash()) {
+ LogError("%s: GetHash() doesn't match index for %s at %s\n",
+ __func__, pindex->ToString(), block_pos.ToString());
+ return false;
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/node/blockstorage.cpp` around lines 807 - 810, In ReadBlockFromDisk (the
branch that currently does `return error("ReadBlockFromDisk(CBlock&,
CBlockIndex*): GetHash() doesn't match index for %s at %s", pindex->ToString(),
block_pos.ToString()); return false;`) remove the unreachable `return false;`
and instead replace the `return error(...)` call with a logging call (e.g.,
LogError or the project's LogPrint equivalent) that emits the same message using
pindex->ToString() and block_pos.ToString(), then follow it with `return false;`
so the branch matches the LogError(...); return false; pattern used elsewhere.
| if (!Consensus::CheckTxInputs(tx, tx_state, view, pindex->nHeight, txfee)) { | ||
| // Any transaction validation failure in ConnectBlock is a block consensus failure | ||
| LogPrintf("ERROR: %s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), state.ToString()); | ||
| LogError("%s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), state.ToString()); | ||
| return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | ||
| tx_state.GetRejectReason(), tx_state.GetDebugMessage()); |
There was a problem hiding this comment.
Log the failing tx_state instead of state.
Line 2486 logs state.ToString(), but this branch hasn't copied the CheckTxInputs() failure into state yet. That can hide the actual rejection reason in debug.log and make consensus failures harder to diagnose.
Suggested fix
if (!Consensus::CheckTxInputs(tx, tx_state, view, pindex->nHeight, txfee)) {
// Any transaction validation failure in ConnectBlock is a block consensus failure
- LogError("%s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), state.ToString());
+ LogError("%s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), tx_state.ToString());
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
}📝 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.
| if (!Consensus::CheckTxInputs(tx, tx_state, view, pindex->nHeight, txfee)) { | |
| // Any transaction validation failure in ConnectBlock is a block consensus failure | |
| LogPrintf("ERROR: %s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), state.ToString()); | |
| LogError("%s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), state.ToString()); | |
| return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | |
| tx_state.GetRejectReason(), tx_state.GetDebugMessage()); | |
| if (!Consensus::CheckTxInputs(tx, tx_state, view, pindex->nHeight, txfee)) { | |
| // Any transaction validation failure in ConnectBlock is a block consensus failure | |
| LogError("%s: Consensus::CheckTxInputs: %s, %s\n", __func__, tx.GetHash().ToString(), tx_state.ToString()); | |
| return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | |
| tx_state.GetRejectReason(), tx_state.GetDebugMessage()); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/validation.cpp` around lines 2484 - 2488, The LogError call after
Consensus::CheckTxInputs is logging state.ToString() which is incorrect because
the CheckTxInputs failure details are in tx_state; update the LogError
invocation in the ConnectBlock error branch to include tx_state.ToString()
(and/or tx_state.GetRejectReason()/GetDebugMessage() if you prefer more detail)
so the actual transaction rejection reason from CheckTxInputs is recorded before
returning state.Invalid; keep the existing return that uses tx_state for the
reject reason/debug message.
| IGNORE_WORDS_FILE = 'test/lint/spelling.ignore-words.txt' | ||
| FILES_ARGS = ['git', 'ls-files', '--', ":(exclude)build-aux/m4/", ":(exclude)contrib/seeds/*.txt", ":(exclude)depends/", ":(exclude)doc/release-notes/", ":(exclude)src/dashbls/", ":(exclude)src/crc32c/", ":(exclude)src/crypto/", ":(exclude)src/ctpl_stl.h", ":(exclude)src/cxxtimer.hpp", ":(exclude)src/immer/", ":(exclude)src/leveldb/", ":(exclude)src/qt/locale/", ":(exclude)src/qt/*.qrc", ":(exclude)src/secp256k1/", ":(exclude)src/minisketch/", ":(exclude)contrib/builder-keys/", ":(exclude)contrib/guix/patches", ":(exclude)src/util/subprocess.hpp", ":(exclude)src/wallet/bip39_english.h"] | ||
| FILES_ARGS = ['git', 'ls-files', '--', ":(exclude)build-aux/m4/", ":(exclude)contrib/seeds/*.txt", ":(exclude)depends/", ":(exclude)doc/release-notes/", ":(exclude)src/dashbls/", ":(exclude)src/crypto/", ":(exclude)src/ctpl_stl.h", ":(exclude)src/cxxtimer.hpp", ":(exclude)src/immer/", ":(exclude)src/qt/locale/", ":(exclude)src/qt/*.qrc", ":(exclude)contrib/builder-keys/", ":(exclude)contrib/guix/patches", ":(exclude)src/util/subprocess.hpp", ":(exclude)src/wallet/bip39_english.h"] | ||
| FILES_ARGS += [f":(exclude){dir}" for dir in SHARED_EXCLUDED_SUBTREES] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n test/lint/lint-spelling.py | head -25Repository: dashpay/dash
Length of output: 1481
🏁 Script executed:
find . -maxdepth 2 -type f \( -name "ruff.toml" -o -name "pyproject.toml" -o -name ".ruff.toml" -o -name "setup.cfg" \) | head -10Repository: dashpay/dash
Length of output: 68
🏁 Script executed:
cat ./ruff.tomlRepository: dashpay/dash
Length of output: 1171
Rename loop variable dir to avoid shadowing Python built-in.
Line 18 uses dir as a loop variable, which shadows the built-in dir() function and triggers Ruff A001. This will fail lint CI since the project's ruff.toml enables the A rule (flake8-builtins) without suppressing this check.
Proposed fix
-FILES_ARGS += [f":(exclude){dir}" for dir in SHARED_EXCLUDED_SUBTREES]
+FILES_ARGS += [f":(exclude){excluded_dir}" for excluded_dir in SHARED_EXCLUDED_SUBTREES]📝 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.
| FILES_ARGS += [f":(exclude){dir}" for dir in SHARED_EXCLUDED_SUBTREES] | |
| FILES_ARGS += [f":(exclude){excluded_dir}" for excluded_dir in SHARED_EXCLUDED_SUBTREES] |
🧰 Tools
🪛 Ruff (0.15.12)
[error] 18-18: Variable dir is shadowing a Python builtin
(A001)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@test/lint/lint-spelling.py` at line 18, The list comprehension uses the loop
variable named dir which shadows the built-in dir() and triggers Ruff A001;
update the variable name in the expression that builds FILES_ARGS (the
comprehension referencing SHARED_EXCLUDED_SUBTREES) to a non-built-in name like
subtree or subdir so it no longer shadows the built-in (e.g., replace
occurrences of dir inside the comprehension with subtree).
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Validated all findings against source. One blocking merge-resolution defect in blockstorage.cpp (stale return error(...) plus unreachable return false) and five LogError calls in validation.cpp that lost their trailing \n during the bitcoin#29236 conversion. Two informational backport-prerequisite notes (partial adaptations of bitcoin#28857 and bitcoin#29236) confirmed against current Dash code.
Reviewed commit: 11dde62
🔴 1 blocking | 🟡 5 suggestion(s) | 💬 2 nitpick(s)
1 additional finding
💬 nitpick: bitcoin#29236 only partially adopted: Dash retains its own error() template
src/util/system.h (lines 52-57)
Verified: bitcoin#29236 upstream removed the error(...) template entirely. Dash applied the scripted-diff converting many error(...) callers to LogError(...) + return false, but kept the error() template at src/util/system.h:53. Several Dash-specific call sites still rely on it (e.g., src/node/blockstorage.cpp:776,784,791,807; src/util/system.cpp:120; src/validation.cpp:2039; src/evo/specialtxman.cpp:593). The retained template wraps LogPrintf rather than LogError, so log severity for those sites is Info rather than Error. Additionally, bitcoin#29633 updated logging.h's leading comment to drop the explicit error reference; this leaves the comment slightly out of sync with Dash's actual state where error() still exists. Cosmetic / informational only — flag for tracking the eventual full removal.
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/node/blockstorage.cpp`:
- [BLOCKING] lines 806-810: Stale return error(...) with unreachable return false; bitcoin#29236 conversion missed this site
Confirmed at src/node/blockstorage.cpp:806-810:
```cpp
if (*hash != pindex->GetBlockHash()) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
pindex->ToString(), block_pos.ToString());
return false;
}
Two problems: (1) error(...) already returns false, so the trailing return false; is unreachable — this can trip the configured -Wunreachable-code diagnostics when warnings are promoted to errors. (2) The point of the bitcoin#29236 backport in this PR is precisely to nuke error() from these call sites; every other hunk in the diff converts to LogError(...\n); return false;. This single site was missed during merge resolution.
Functionally the function still returns false on hash mismatch, so consensus is unaffected, but the merge resolution is inconsistent and risks breaking warning-as-error builds.
In src/validation.cpp:
- [SUGGESTION] line 4781: LogError missing trailing \n in RollforwardBlock
Confirmed: line ends with...ToString());and no\nin the format string.LogErrorexpands toLogPrintLevel_→LogPrintf_→tfm::format(fmt, args...)and writes the result verbatim viaLogPrintStr. The Logger uses the trailing\nto drivem_started_new_line(logging.cpp:481), which controls whether the next entry gets its timestamp/source-location/threadname prefix. Without a trailing\nthe next log line gets concatenated onto the same line and loses its prefix. Every other LogError introduced by this PR (e.g., lines 4690, 4755, 4897, 4909, 4916) ends in\n; this one was missed. - [SUGGESTION] line 4924: LogError missing trailing \n on Dash-specific EvoDB inconsistency message
Same root cause as the line 4781 finding: this Dash-specific call (note the(DASH):tag) was converted fromerror(...)but lost the newline. The very next LogError call at line 4936 (also Dash-specific) has the same defect, as do 4942 and 5126. - [SUGGESTION] line 4936: LogError missing trailing \n in ReplayBlocks ReadBlockFromDisk failure
Same missing-newline issue as 4781/4924. Format string ends with...ToString())without\n. - [SUGGESTION] line 4942: LogError missing trailing \n in ReplayBlocks DisconnectBlock failure
Same missing-newline issue. - [SUGGESTION] line 5126: LogError missing trailing \n in LoadGenesisBlock catch handler
Same missing-newline issue in theLoadGenesisBlockexception handler.
</details>
| if (*hash != pindex->GetBlockHash()) { | ||
| return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", | ||
| pindex->ToString(), block_pos.ToString()); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
🔴 Blocking: Stale return error(...) with unreachable return false; bitcoin#29236 conversion missed this site
Confirmed at src/node/blockstorage.cpp:806-810:
if (*hash != pindex->GetBlockHash()) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
pindex->ToString(), block_pos.ToString());
return false;
}Two problems: (1) error(...) already returns false, so the trailing return false; is unreachable — this can trip the configured -Wunreachable-code diagnostics when warnings are promoted to errors. (2) The point of the bitcoin#29236 backport in this PR is precisely to nuke error() from these call sites; every other hunk in the diff converts to LogError(...\n); return false;. This single site was missed during merge resolution.
Functionally the function still returns false on hash mismatch, so consensus is unaffected, but the merge resolution is inconsistent and risks breaking warning-as-error builds.
💡 Suggested change
| if (*hash != pindex->GetBlockHash()) { | |
| return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", | |
| pindex->ToString(), block_pos.ToString()); | |
| return false; | |
| } | |
| if (*hash != pindex->GetBlockHash()) { | |
| LogError("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s\n", | |
| pindex->ToString(), block_pos.ToString()); | |
| return false; | |
| } |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/node/blockstorage.cpp`:
- [BLOCKING] lines 806-810: Stale return error(...) with unreachable return false; bitcoin#29236 conversion missed this site
Confirmed at src/node/blockstorage.cpp:806-810:
```cpp
if (*hash != pindex->GetBlockHash()) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
pindex->ToString(), block_pos.ToString());
return false;
}
Two problems: (1) error(...) already returns false, so the trailing return false; is unreachable — this can trip the configured -Wunreachable-code diagnostics when warnings are promoted to errors. (2) The point of the bitcoin#29236 backport in this PR is precisely to nuke error() from these call sites; every other hunk in the diff converts to LogError(...\n); return false;. This single site was missed during merge resolution.
Functionally the function still returns false on hash mismatch, so consensus is unaffected, but the merge resolution is inconsistent and risks breaking warning-as-error builds.
</details>
| CBlock block; | ||
| if (!ReadBlockFromDisk(block, pindex, m_params.GetConsensus())) { | ||
| return error("RollforwardBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); | ||
| LogError("RollforwardBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
There was a problem hiding this comment.
🟡 Suggestion: LogError missing trailing \n in RollforwardBlock
Confirmed: line ends with ...ToString()); and no \n in the format string. LogError expands to LogPrintLevel_ → LogPrintf_ → tfm::format(fmt, args...) and writes the result verbatim via LogPrintStr. The Logger uses the trailing \n to drive m_started_new_line (logging.cpp:481), which controls whether the next entry gets its timestamp/source-location/threadname prefix. Without a trailing \n the next log line gets concatenated onto the same line and loses its prefix. Every other LogError introduced by this PR (e.g., lines 4690, 4755, 4897, 4909, 4916) ends in \n; this one was missed.
💡 Suggested change
| LogError("RollforwardBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); | |
| LogError("RollforwardBlock(): ReadBlockFromDisk failed at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/validation.cpp`:
- [SUGGESTION] line 4781: LogError missing trailing \n in RollforwardBlock
Confirmed: line ends with `...ToString());` and no `\n` in the format string. `LogError` expands to `LogPrintLevel_` → `LogPrintf_` → `tfm::format(fmt, args...)` and writes the result verbatim via `LogPrintStr`. The Logger uses the trailing `\n` to drive `m_started_new_line` (logging.cpp:481), which controls whether the next entry gets its timestamp/source-location/threadname prefix. Without a trailing `\n` the next log line gets concatenated onto the same line and loses its prefix. Every other LogError introduced by this PR (e.g., lines 4690, 4755, 4897, 4909, 4916) ends in `\n`; this one was missed.
| const bool fDIP0003Active = DeploymentActiveAt(*pindexOld, m_params.GetConsensus(), Consensus::DEPLOYMENT_DIP0003); | ||
| if (fDIP0003Active && !m_evoDb.VerifyBestBlock(pindexOld->GetBlockHash())) { | ||
| return error("ReplayBlocks(DASH): Found EvoDB inconsistency"); | ||
| LogError("ReplayBlocks(DASH): Found EvoDB inconsistency"); |
There was a problem hiding this comment.
🟡 Suggestion: LogError missing trailing \n on Dash-specific EvoDB inconsistency message
Same root cause as the line 4781 finding: this Dash-specific call (note the (DASH): tag) was converted from error(...) but lost the newline. The very next LogError call at line 4936 (also Dash-specific) has the same defect, as do 4942 and 5126.
💡 Suggested change
| LogError("ReplayBlocks(DASH): Found EvoDB inconsistency"); | |
| LogError("ReplayBlocks(DASH): Found EvoDB inconsistency\n"); |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/validation.cpp`:
- [SUGGESTION] line 4924: LogError missing trailing \n on Dash-specific EvoDB inconsistency message
Same root cause as the line 4781 finding: this Dash-specific call (note the `(DASH):` tag) was converted from `error(...)` but lost the newline. The very next LogError call at line 4936 (also Dash-specific) has the same defect, as do 4942 and 5126.
| CBlock block; | ||
| if (!ReadBlockFromDisk(block, pindexOld, m_params.GetConsensus())) { | ||
| return error("ReplayBlocks(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | ||
| LogError("ReplayBlocks(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); |
There was a problem hiding this comment.
🟡 Suggestion: LogError missing trailing \n in ReplayBlocks ReadBlockFromDisk failure
Same missing-newline issue as 4781/4924. Format string ends with ...ToString()) without \n.
💡 Suggested change
| LogError("ReplayBlocks(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | |
| LogError("ReplayBlocks(): ReadBlockFromDisk() failed at %d, hash=%s\n", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/validation.cpp`:
- [SUGGESTION] line 4936: LogError missing trailing \n in ReplayBlocks ReadBlockFromDisk failure
Same missing-newline issue as 4781/4924. Format string ends with `...ToString())` without `\n`.
| DisconnectResult res = DisconnectBlock(block, pindexOld, cache); | ||
| if (res == DISCONNECT_FAILED) { | ||
| return error("ReplayBlocks(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | ||
| LogError("ReplayBlocks(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); |
There was a problem hiding this comment.
🟡 Suggestion: LogError missing trailing \n in ReplayBlocks DisconnectBlock failure
Same missing-newline issue.
💡 Suggested change
| LogError("ReplayBlocks(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); | |
| LogError("ReplayBlocks(): DisconnectBlock failed at %d, hash=%s\n", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/validation.cpp`:
- [SUGGESTION] line 4942: LogError missing trailing \n in ReplayBlocks DisconnectBlock failure
Same missing-newline issue.
| } | ||
| } catch (const std::runtime_error &e) { | ||
| return error("%s: failed to initialize block database: %s", __func__, e.what()); | ||
| LogError("%s: failed to initialize block database: %s", __func__, e.what()); |
There was a problem hiding this comment.
🟡 Suggestion: LogError missing trailing \n in LoadGenesisBlock catch handler
Same missing-newline issue in the LoadGenesisBlock exception handler.
💡 Suggested change
| LogError("%s: failed to initialize block database: %s", __func__, e.what()); | |
| LogError("%s: failed to initialize block database: %s\n", __func__, e.what()); |
source: ['claude']
🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/validation.cpp`:
- [SUGGESTION] line 5126: LogError missing trailing \n in LoadGenesisBlock catch handler
Same missing-newline issue in the `LoadGenesisBlock` exception handler.
| @@ -178,6 +180,16 @@ BOOST_AUTO_TEST_CASE(vector_bool) | |||
| BOOST_CHECK(SerializeHash(vec1) == SerializeHash(vec2)); | |||
| } | |||
|
|
|||
| BOOST_AUTO_TEST_CASE(array) | |||
| { | |||
| std::array<uint8_t, 32> array1{1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1}; | |||
| DataStream ds; | |||
| ds << array1; | |||
| std::array<uint8_t, 32> array2; | |||
| ds >> array2; | |||
| BOOST_CHECK(array1 == array2); | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
💬 Nitpick: bitcoin#28857 cherry-pick is the test commit only; refactor commit deferred until MessageStartChars→std::array conversion is backported
Verified: bitcoin#28857 upstream had a refactor commit (d49d198) initializing m_magic_bytes via the constructor initializer list using std::array<uint8_t, 4>, and a test commit (1e5b861) adding std::array serialization tests. The Dash cherry-pick (1040ad0) only includes the test piece. src/protocol.h:36 still defines typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; (a C array), so the upstream constructor-initializer form would not compile here. This is non-blocking — the cherry-pick does not introduce broken code — but the refactor portion of bitcoin#28857 is still pending and will need a follow-up after the upstream MessageStartChars→std::array conversion is backported into Dash.
source: ['claude']
bitcoin backports