Code Review Report
This review covers Bitcoin Knots v29.2.knots20251110. The current release, v29.3.knots20260508 (May 2026), additionally ships the BIP-110 (RDTS) consensus rules — enforced by the standard build on its activation schedule, with a non-enforcing build also published. Those rules are outside the scope of this review; see BIP-110 / RDTS Integration.
Subject: Bitcoin Knots v29.2.knots20251110 consensus-adjacent code Compared against: Bitcoin Core v29.0 Review date: January 2026 Reviewer: AI-assisted analysis (Claude, Anthropic)
This review was conducted using AI-assisted static code analysis. It is not a formal security audit. All findings should be independently verified using the commands provided. This review focuses on identifying consensus-related changes, not comprehensive security analysis.
Executive Summary
| Category | Files Changed | Lines Added | Consensus Changes Found |
|---|---|---|---|
script/interpreter.cpp | 1 | +90 | None |
validation.cpp | 1 | +591 | None |
consensus/ | 3 | +94 | None |
script/bitcoinconsensus.* | 2 | +252 | None (restored Core code) |
Conclusion: No consensus rule changes were identified in v29.2.knots20251110, the release under review. (v29.3's deliberate RDTS soft-fork deployment is outside this review's scope.) All modifications are either:
- Policy options (configurable relay behavior)
- Performance optimizations
- Restored Bitcoin Core code
- Build system/infrastructure
Methodology
Scope
Files reviewed (consensus-adjacent):
src/script/interpreter.cpp— Script executionsrc/validation.cpp— Block/transaction validationsrc/consensus/— Consensus parameterssrc/script/bitcoinconsensus.*— Consensus library
Process
# Repository setup
git clone https://github.com/bitcoinknots/bitcoin.git
cd bitcoin
git checkout v29.2.knots20251110
git remote add core https://github.com/bitcoin/bitcoin.git
git fetch core v29.0
# Generate diffs
git diff FETCH_HEAD..HEAD -- src/script/interpreter.cpp
git diff FETCH_HEAD..HEAD -- src/validation.cpp
git diff FETCH_HEAD..HEAD -- src/consensus/
Criteria
For each change, we asked:
- Does it modify consensus validation logic?
- Does it change consensus parameters (block size, etc.)?
- Could it cause a network fork?
- Is it policy (relay) or consensus (validation)?
Detailed Findings
1. script/interpreter.cpp
Lines changed: +90 insertions, -28 deletions
Finding 1.1: SigHashCache Performance Optimization
// NEW: Caching mechanism for signature hash computation
int SigHashCache::CacheIndex(int32_t hash_type) const noexcept
bool SigHashCache::Load(int32_t hash_type, ...) const noexcept
void SigHashCache::Store(int32_t hash_type, ...) noexcept
Assessment: ✅ Safe — Performance only
This adds caching for signature hash midstates. The actual hash computation is unchanged — same inputs produce identical outputs. This is a performance optimization that speeds up signature verification for transactions with multiple inputs.
Verification:
# The SignatureHash function produces identical results
# Only the caching layer is new
git diff FETCH_HEAD..HEAD -- src/script/interpreter.cpp | grep -A5 "SignatureHash"
Finding 1.2: Optional SIGHASH_ALL Requirement
// NEW: Optional policy check
if (m_require_sighash_all && nHashType != SIGHASH_ALL) {
return false;
}
Assessment: ✅ Safe — Policy option only
This adds an optional requirement that signatures use SIGHASH_ALL. Key points:
- It's a more restrictive check, not a relaxation
- Consensus does NOT require SIGHASH_ALL
- Disabled by default
- Only affects what the node relays, not what blocks it accepts
Finding 1.3: Critical Functions Unchanged
The following consensus-critical functions have no logic changes:
| Function | Status | Notes |
|---|---|---|
EvalScript() | ✅ Unchanged | Core script execution |
VerifyScript() | ✅ Unchanged | Script verification |
OP_* implementations | ✅ Unchanged | All opcodes |
SignatureHashSchnorr() | ✅ Unchanged | Taproot signatures |
Verification:
git diff FETCH_HEAD..HEAD -- src/script/interpreter.cpp | grep -E "EvalScript|VerifyScript|case OP_"
# Should return no changes to these functions
2. validation.cpp
Lines changed: +591 insertions, -210 deletions
This is the largest diff, but examination reveals all changes are policy options.
Finding 2.1: Database Write Randomization
// BEFORE (Core):
static constexpr std::chrono::hours DATABASE_WRITE_INTERVAL{1};
// AFTER (Knots):
static constexpr auto DATABASE_WRITE_INTERVAL_MIN{50min};
static constexpr auto DATABASE_WRITE_INTERVAL_MAX{70min};
Assessment: ✅ Safe — Performance/privacy improvement
Randomizes database write timing to prevent network-wide synchronization. Does not affect validation.
Finding 2.2: Configurable Policy Rejections
// NEW: ignore_rejects allows bypassing specific policy checks
const ignore_rejects_type& ignore_rejects = args.m_ignore_rejects;
// Example usage:
MaybeReject(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
Assessment: ✅ Safe — Policy flexibility only
The ignore_rejects mechanism allows node operators to bypass specific policy rejections. Critical observation:
- These are relay/mempool policies, NOT consensus rules
- Transactions rejected by policy are still consensus-valid
- Your node accepts blocks containing these transactions regardless
Finding 2.3: New Policy Options
| Option | Purpose | Consensus Impact |
|---|---|---|
SpkReuseMode | Address reuse detection | None — privacy feature |
minrelaymaturity | Coin age requirement | None — relay policy |
datacarrier_fullcount | OP_RETURN counting | None — relay policy |
RBFPolicy | Replace-by-fee modes | None — relay policy |
TRUCPolicy | Transaction version handling | None — relay policy |
Verification:
# All policy options are in AcceptToMemoryPool path, NOT ConnectBlock
git diff FETCH_HEAD..HEAD -- src/validation.cpp | grep -B5 "ignore_rejects"
Finding 2.4: Script Verification Flags Safety
// Critical safety measure at line 758:
flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; // for safety
Assessment: ✅ Safe — Explicit safety guarantee
Even when policy flags are relaxed, mandatory (consensus) flags are always preserved. This is an explicit safety measure ensuring consensus validation is never weakened.
Finding 2.5: Consensus Functions Unchanged
| Function | Status | Notes |
|---|---|---|
CheckBlock() | ✅ Unchanged | Block structure validation |
ContextualCheckBlock() | ✅ Unchanged | Block context validation |
ConnectBlock() | ✅ Unchanged | UTXO set updates |
CheckTxInputs() | ✅ Unchanged | Input validation |
Consensus::CheckTransaction() | ✅ Unchanged | Transaction validation |
Verification:
git diff FETCH_HEAD..HEAD -- src/validation.cpp | grep -E "CheckBlock|ConnectBlock|CheckTxInputs"
# Verify no changes to these function implementations
3. consensus/ Directory
Lines changed: +94 insertions, -5 deletions
Finding 3.1: CMakeLists.txt (NEW FILE)
# Build configuration for libbitcoinconsensus
add_library(bitcoinconsensus
../script/bitcoinconsensus.cpp
...
)
Assessment: ✅ Safe — Build infrastructure only
This is build system configuration for the restored libbitcoinconsensus library. Contains no consensus logic.
Finding 3.2: merkle.cpp Optimization
// BEFORE:
if (hashes[pos] == hashes[pos + 1]) mutation = true;
// AFTER:
if (hashes[pos] == hashes[pos + 1]) {
mutation = true;
break; // <-- NEW: Early exit optimization
}
Assessment: ✅ Safe — Performance optimization
Adds early exit when mutation is detected. The function returns identical results — once mutation is found, there's no need to continue checking.
Finding 3.3: validation.h Refactoring
// Refactored to accept CTransaction directly
inline int GetWitnessCommitmentIndex(const CTransaction& gentx)
// Original block version now wraps the transaction version
inline int GetWitnessCommitmentIndex(const CBlock& block)
Assessment: ✅ Safe — Code refactoring only
The logic is identical, just factored to be more flexible. The block version is now a wrapper that calls the transaction version.
4. script/bitcoinconsensus.* (Restored Library)
Lines changed: +252 insertions (two new files)
Finding 4.1: Copyright Headers
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2022 The Bitcoin Core developers
Assessment: ✅ Safe — Original Bitcoin Core code
This is restored Bitcoin Core code, not new Knots code. Key facts:
- Written by Bitcoin Core developers
- Reviewed when originally merged to Core
- Used in production for years
- Removed from Core v28, restored in Knots for compatibility
- Provides
bitcoinconsensus_verify_script()for external validators
Verification:
# Compare against historical Core version
git log --oneline core/v27.0 -- src/script/bitcoinconsensus.cpp | head -5
# Shows original Core commits
Risk Matrix
| Change Category | Risk Level | Reasoning |
|---|---|---|
| Performance optimizations | None | Same outputs, faster computation |
| Policy options | None | Relay only, consensus unchanged |
| Build system | None | Infrastructure, no runtime effect |
| Restored Core code | None | Already reviewed, battle-tested |
| Consensus logic | N/A | No changes found |
Verification Commands
Run these commands to verify the findings yourself:
#!/bin/bash
# verify-consensus-changes.sh
git clone https://github.com/bitcoinknots/bitcoin.git
cd bitcoin
git checkout v29.2.knots20251110
git remote add core https://github.com/bitcoin/bitcoin.git
git fetch core v29.0
echo "=== 1. Check interpreter.cpp for EvalScript changes ==="
git diff FETCH_HEAD..HEAD -- src/script/interpreter.cpp | \
grep -E "^[+-].*EvalScript|^[+-].*VerifyScript" | head -20
echo -e "\n=== 2. Check validation.cpp for ConnectBlock changes ==="
git diff FETCH_HEAD..HEAD -- src/validation.cpp | \
grep -E "^[+-].*ConnectBlock|^[+-].*CheckBlock\(" | head -20
echo -e "\n=== 3. Verify MANDATORY_SCRIPT_VERIFY_FLAGS safety ==="
git diff FETCH_HEAD..HEAD -- src/validation.cpp | \
grep "MANDATORY_SCRIPT_VERIFY_FLAGS"
echo -e "\n=== 4. Check consensus parameters ==="
git diff FETCH_HEAD..HEAD -- src/consensus/consensus.h
echo -e "\n=== 5. Verify bitcoinconsensus is Core code ==="
head -10 src/script/bitcoinconsensus.cpp
Limitations
This review:
- ✅ Examined consensus-adjacent code changes
- ✅ Verified no consensus rule modifications
- ✅ Confirmed policy vs consensus distinction
- ❌ Did not audit all 36,000+ lines of Knots changes
- ❌ Did not perform fuzzing or dynamic analysis
- ❌ Did not mathematically prove correctness
For high-stakes deployments, consider commissioning a formal security audit from a firm specializing in Bitcoin.
Conclusion
After systematic review of all consensus-adjacent code in Bitcoin Knots v29.2, no consensus rule changes were identified in that release. The changes fall into well-defined categories:
- Policy options — Configurable relay behavior that doesn't affect block validation
- Performance optimizations — Same results, faster computation
- Restored Core code — Previously reviewed code brought back for compatibility
The claim that Knots contains "dangerous consensus changes" is not supported by examination of the v29.2 code. Knots v29.2 validates blocks identically to Bitcoin Core. The RDTS soft-fork deployment added in v29.3 is a deliberate, documented consensus feature — not a hidden change — and would need a separate review; see BIP-110 / RDTS Integration.
See Also
- Consensus-Adjacent Code Deep Dive — Conceptual explanation
- Code Analysis — High-level statistics
- Differences from Core — Feature comparison