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
7 changes: 6 additions & 1 deletion src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@
#include <consensus/params.h>
#include <flatfile.h>
#include <primitives/block.h>
#include <serialize.h>
#include <sync.h>
#include <uint256.h>

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>

/**
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
* current time before the block will be accepted.
*/
static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;

Expand Down
2 changes: 1 addition & 1 deletion src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <util/check.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/time.h>
#include <util/trace.h>
#include <util/underlying.h>
#include <validation.h>
Expand Down Expand Up @@ -70,7 +71,6 @@

#include <algorithm>
#include <atomic>
#include <chrono>
#include <future>
#include <list>
#include <memory>
Expand Down
2 changes: 1 addition & 1 deletion src/node/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
#include <policy/policy.h>
#include <pow.h>
#include <primitives/transaction.h>
#include <timedata.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/time.h>
Copy link

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

python - <<'PY'
from pathlib import Path
import re

repo = Path('.')
miner = repo / 'src/node/miner.cpp'
inc_re = re.compile(r'#include <([^>]+)>')

includes = []
for line in miner.read_text().splitlines():
    m = inc_re.match(line.strip())
    if m:
        includes.append(m.group(1))
    if line.strip() == 'namespace node {':
        break

print("Direct includes in src/node/miner.cpp:")
for inc in includes:
    print(f"  {inc}")

print("\nDeclaration/definition sites for GetAdjustedTime():")
for path in sorted(repo.glob('src/**/*')):
    if path.suffix not in {'.h', '.hpp', '.hh', '.c', '.cc', '.cpp'}:
        continue
    text = path.read_text(errors='ignore')
    for lineno, line in enumerate(text.splitlines(), 1):
        if 'GetAdjustedTime(' in line:
            print(f"  {path}:{lineno}: {line.strip()}")

print("\nDirectly included headers that reference GetAdjustedTime() or timedata.h:")
for inc in includes:
    for path in sorted(repo.glob(f'**/{Path(inc).name}')):
        if not path.is_file():
            continue
        text = path.read_text(errors='ignore')
        hits = [
            (lineno, line.strip())
            for lineno, line in enumerate(text.splitlines(), 1)
            if 'GetAdjustedTime(' in line or 'timedata.h' in line
        ]
        if hits:
            print(f"  {path}")
            for lineno, line in hits:
                print(f"    {lineno}: {line}")
PY

Repository: dashpay/dash

Length of output: 4490


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check which directly included headers transitively include timedata.h
direct_includes=(
  "node/miner.h"
  "chain.h"
  "chainparams.h"
  "consensus/amount.h"
  "consensus/consensus.h"
  "consensus/merkle.h"
  "consensus/tx_verify.h"
  "consensus/validation.h"
  "deploymentstatus.h"
  "node/context.h"
  "policy/feerate.h"
  "policy/policy.h"
  "pow.h"
  "primitives/transaction.h"
  "util/moneystr.h"
  "util/system.h"
  "util/time.h"
  "validation.h"
  "chainlock/chainlock.h"
  "chainlock/handler.h"
  "evo/specialtx.h"
  "evo/cbtx.h"
  "evo/chainhelper.h"
  "evo/creditpool.h"
  "evo/mnhftx.h"
  "evo/deterministicmns.h"
  "evo/simplifiedmns.h"
  "evo/specialtxman.h"
  "governance/governance.h"
  "instantsend/instantsend.h"
  "llmq/blockprocessor.h"
  "llmq/context.h"
  "llmq/options.h"
  "llmq/snapshot.h"
  "masternode/payments.h"
)

echo "Checking which direct includes transitively include timedata.h:"
for inc in "${direct_includes[@]}"; do
  # Find the file
  file_path=$(find src -name "$(basename "$inc")" -path "*${inc}" 2>/dev/null | head -1)
  if [ -f "$file_path" ]; then
    if grep -q "timedata\.h" "$file_path"; then
      echo "$inc includes timedata.h"
      grep -n "timedata\.h" "$file_path"
    fi
  fi
done

echo ""
echo "Checking src/node/miner.h specifically:"
if [ -f "src/node/miner.h" ]; then
  cat -n src/node/miner.h | head -50
fi

Repository: dashpay/dash

Length of output: 1660


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check full miner.h
echo "=== Full src/node/miner.h ==="
cat src/node/miner.h

echo ""
echo "=== Checking validation.h for timedata.h inclusion ==="
grep -n "timedata.h" src/validation.h || echo "Not found in validation.h"

echo ""
echo "=== Checking node/context.h for timedata.h inclusion ==="
grep -n "timedata.h" src/node/context.h || echo "Not found in node/context.h"

echo ""
echo "=== Checking all .h files in src/node/ for timedata.h ==="
grep -r "timedata.h" src/node/ || echo "Not found in src/node/"

echo ""
echo "=== Checking governance/governance.h (uses GetAdjustedTime) ==="
grep -n "timedata.h" src/governance/governance.h || echo "Not found in governance.h"
grep -n "#include" src/governance/governance.h | head -20

Repository: dashpay/dash

Length of output: 8763


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Let's trace the include chain more carefully
echo "=== Searching for timedata.h in all header includes ==="
python3 << 'PYSCRIPT'
import os
import re
from pathlib import Path

def find_transitive_includes(start_file, max_depth=5):
    """Recursively find all includes from a file."""
    visited = set()
    includes = {}
    
    def traverse(filepath, depth=0):
        if depth > max_depth or filepath in visited:
            return
        visited.add(filepath)
        
        if not filepath.exists():
            return
        
        try:
            content = filepath.read_text(errors='ignore')
        except:
            return
            
        includes[str(filepath)] = []
        
        for line in content.split('\n'):
            match = re.match(r'#include\s*[<"]([^>"]+)[>"]', line.strip())
            if match:
                inc = match.group(1)
                includes[str(filepath)].append(inc)
                
                # Try to resolve the include
                inc_path = filepath.parent / inc
                if inc_path.exists():
                    traverse(inc_path, depth + 1)
    
    traverse(start_file)
    return includes

# Check validation.h (one of the major includes)
validation_h = Path('src/validation.h')
print("Checking validation.h includes for timedata.h...")
includes = find_transitive_includes(validation_h)
found_timedata = False
for file, incs in includes.items():
    if 'timedata.h' in incs:
        print(f"  Found in {file}: {[i for i in incs if 'timedata' in i]}")
        found_timedata = True

if not found_timedata:
    print("  timedata.h not found in validation.h include chain")

# Check governance/governance.h (uses GetAdjustedTime)
print("\nChecking governance/governance.h includes...")
gov_h = Path('src/governance/governance.h')
if gov_h.exists():
    includes = find_transitive_includes(gov_h)
    found_timedata = False
    for file, incs in includes.items():
        if 'timedata.h' in incs:
            print(f"  Found in {file}: {[i for i in incs if 'timedata' in i]}")
            found_timedata = True
    if not found_timedata:
        print("  timedata.h not found in governance/governance.h include chain")

PYSCRIPT

echo ""
echo "=== Direct search for which header includes timedata.h ==="
grep -r "^\s*#include.*timedata\.h" src/ | head -20

Repository: dashpay/dash

Length of output: 1238


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Let's check if this can actually compile by looking at what governance.h includes
echo "=== Full governance/governance.h include chain ==="
head -30 src/governance/governance.h

echo ""
echo "=== Check if any major included header has timedata in its transitive chain ==="
# Let's check a few key headers
for header in "src/util/system.h" "src/validation.h" "src/governance/governance.h" "src/coinjoin/coinjoin.h"; do
  if [ -f "$header" ]; then
    echo "=== $header (first 50 lines) ==="
    head -50 "$header"
    echo ""
  fi
done

echo ""
echo "=== Check if governance/governance.h is included in miner.cpp ==="
grep -n "governance/governance.h" src/node/miner.cpp

Repository: dashpay/dash

Length of output: 5938


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking governance/signing.h for timedata.h ==="
head -40 src/governance/signing.h | grep -E "^#include"

echo ""
echo "=== Full governance/signing.h includes ==="
grep "^#include" src/governance/signing.h

echo ""
echo "=== Checking governance/governance.cpp (impl) for timedata ==="
grep -n "timedata" src/governance/governance.cpp | head -5

echo ""
echo "=== Now let's check if protocol.h or sync.h include timedata ==="
grep "timedata.h" src/protocol.h src/sync.h 2>/dev/null || echo "Not found in protocol.h or sync.h"

echo ""
echo "=== Check all files directly included by miner.cpp for timedata chain ==="
python3 << 'PY'
import re
from pathlib import Path

miner_cpp = Path('src/node/miner.cpp')
includes = []

# Extract direct includes from miner.cpp
for line in miner_cpp.read_text().split('\n'):
    m = re.match(r'#include <([^>]+)>', line.strip())
    if m:
        includes.append(m.group(1))
    if 'namespace node {' in line:
        break

# For each include, check if it (or its transitive includes) reference timedata
print("Checking which direct includes transitively lead to timedata.h definition/declaration:\n")

def check_include(inc, visited=None, depth=0):
    if visited is None:
        visited = set()
    if depth > 3 or inc in visited:
        return False
    visited.add(inc)
    
    # Try to find the file
    candidates = list(Path('src').glob(f'**/{Path(inc).name}'))
    for cand in candidates:
        if str(cand).endswith(inc) or cand.name == Path(inc).name:
            try:
                content = cand.read_text(errors='ignore')
                # Check if this file declares or includes timedata
                if 'GetAdjustedTime' in content:
                    return True
                # Check includes in this file
                for line in content.split('\n'):
                    m = re.match(r'#include <([^>]+)>', line.strip())
                    if m:
                        if check_include(m.group(1), visited, depth + 1):
                            return True
            except:
                pass
    return False

for inc in includes[:10]:  # Check first 10
    if check_include(inc):
        print(f"  ✓ {inc} -> leads to GetAdjustedTime definition")

PY

Repository: dashpay/dash

Length of output: 784


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check governance/object.h for timedata inclusion ==="
grep "timedata\|GetAdjustedTime" src/governance/object.h

echo ""
echo "=== Check governance/classes.h for timedata inclusion ==="
grep "timedata\|GetAdjustedTime" src/governance/classes.h

echo ""
echo "=== Let's trace what includes governance/classes.h ==="
head -30 src/governance/classes.h | grep "#include"

echo ""
echo "=== Now check if miner.cpp would actually compile as-is ==="
echo "Looking at actual usage in miner.cpp..."
grep -B2 -A2 "GetAdjustedTime" src/node/miner.cpp

echo ""
echo "=== Final check: Verify coinjoin.h is in miner.cpp includes ==="
grep "coinjoin" src/node/miner.cpp

Repository: dashpay/dash

Length of output: 112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check what files exist in governance/ ==="
ls -la src/governance/ | grep -E "\.(h|cpp)$"

echo ""
echo "=== Check if governance/object.h exists ==="
if [ -f src/governance/object.h ]; then
  echo "Found - checking includes..."
  head -30 src/governance/object.h | grep "#include"
else
  echo "Not found, checking governance/ directory..."
  find src/governance -name "*.h" | head -10
fi

echo ""
echo "=== Direct check: does miner.cpp compile without timedata.h? ==="
echo "Looking at miner.cpp lines 50-55 (around first GetAdjustedTime call):"
sed -n '50,55p' src/node/miner.cpp

echo ""
echo "=== Looking at miner.cpp lines 218-225 (around second GetAdjustedTime call): ==="
sed -n '218,225p' src/node/miner.cpp

echo ""
echo "=== Trace evo/chainhelper.h since it's included in miner.cpp ==="
head -40 src/evo/chainhelper.h | grep "#include"

Repository: dashpay/dash

Length of output: 2565


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check governance/vote.h ==="
head -30 src/governance/vote.h | grep "#include"

echo ""
echo "=== Check governance/votedb.h ==="
head -30 src/governance/votedb.h | grep "#include"

echo ""
echo "=== Comprehensive trace: which header in the chain includes timedata.h ==="
python3 << 'PY'
import re
from pathlib import Path

def get_direct_includes(filepath):
    """Get direct includes from a file."""
    try:
        content = Path(filepath).read_text(errors='ignore')
        includes = []
        for line in content.split('\n'):
            m = re.match(r'#include <([^>]+)>', line.strip())
            if m:
                includes.append(m.group(1))
        return includes
    except:
        return []

# Start from governance.h and trace through
chain = ['governance/governance.h']
visited = set()
depth = 0

print("Tracing include chain from governance/governance.h:")
print(f"0: governance/governance.h")

while chain and depth < 5:
    current = chain.pop(0)
    if current in visited:
        continue
    visited.add(current)
    
    incs = get_direct_includes(f'src/{current}')
    
    for inc in incs:
        print(f"  → {inc}")
        
        if 'timedata.h' in inc:
            print(f"\n✓ FOUND: {current} includes timedata.h!")
        
        # Follow governance/* includes
        if 'governance/' in inc or 'vote' in inc:
            chain.append(inc)
            depth += 1

PY

echo ""
echo "=== Now verify: check if governance/vote.h includes timedata ==="
grep "timedata" src/governance/vote.h || echo "No timedata in vote.h"

Repository: dashpay/dash

Length of output: 1150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check util/time.h fully ==="
cat src/util/time.h

echo ""
echo "=== Check util/system.h for timedata ==="
grep "timedata" src/util/system.h

echo ""
echo "=== Final check: Does coinjoin/coinjoin.h (which includes timedata.h) get included transitively? ==="
python3 << 'PY'
import re
from pathlib import Path

def find_include_path(start_file, target_include, visited=None, path=None):
    """Find if target_include is reachable from start_file."""
    if visited is None:
        visited = set()
    if path is None:
        path = []
    
    if start_file in visited:
        return None
    visited.add(start_file)
    path = path + [start_file]
    
    try:
        content = Path(f'src/{start_file}').read_text(errors='ignore')
    except:
        return None
    
    for line in content.split('\n'):
        m = re.match(r'#include <([^>]+)>', line.strip())
        if m:
            inc = m.group(1)
            if inc == target_include:
                return path + [inc]
            # Try to follow the include
            result = find_include_path(inc, target_include, visited, path)
            if result:
                return result
    
    return None

# Check if timedata.h is reachable from any of miner.cpp's direct includes
miner_includes = [
    'node/miner.h',
    'chain.h',
    'validation.h',
    'governance/governance.h',
    'evo/chainhelper.h'
]

print("Checking if timedata.h is reachable from miner.cpp's includes:\n")

for inc in miner_includes:
    path = find_include_path(inc, 'timedata.h')
    if path:
        print(f"✓ {' → '.join(path)}")

PY

Repository: dashpay/dash

Length of output: 5448


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== One final definitive check: Search for any other GetAdjustedTime declaration ==="
grep -r "GetAdjustedTime" src/ --include="*.h" | grep -E "declare|inline|extern"

echo ""
echo "=== Check if timedata.h is the ONLY place GetAdjustedTime is declared ==="
grep -r "int64_t GetAdjustedTime" src/ --include="*.h"

echo ""
echo "=== Verify the actual include structure being built in miner.cpp ==="
# Let's read the actual miner.cpp to see the full include section
head -45 src/node/miner.cpp

Repository: dashpay/dash

Length of output: 140


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Let's be very explicit and simple
echo "=== Is GetAdjustedTime declared in timedata.h? ==="
grep -n "GetAdjustedTime" src/timedata.h

echo ""
echo "=== Is timedata.h included in miner.cpp? ==="
grep -n "timedata.h" src/node/miner.cpp || echo "(not found)"

echo ""
echo "=== Full include block of miner.cpp ==="
sed -n '1,45p' src/node/miner.cpp

echo ""
echo "=== Summary: Which headers declare GetAdjustedTime() ==="
grep -l "GetAdjustedTime" src/*.h

Repository: dashpay/dash

Length of output: 1708


🏁 Script executed:

#!/bin/bash
set -euoripefail

echo "=== Check governance/classes.h includes ==="
grep "#include" src/governance/classes.h

echo ""
echo "=== Check if any Dash subsystem header (evo, llmq, etc) includes timedata transitively ==="
for header in src/evo/*.h src/llmq/*.h; do
  if grep -q "timedata" "$header" 2>/dev/null; then
    echo "Found timedata ref in: $header"
    grep -n "timedata" "$header"
  fi
done

echo ""
echo "=== Most important: Check if coinjoin/coinjoin.h is included transitively ==="
python3 << 'PY'
import re
from pathlib import Path

# Check if coinjoin.h is included transitively from miner.cpp's direct includes
def find_all_includes(filepath, visited=None, depth=0):
    """Recursively find ALL includes."""
    if visited is None:
        visited = set()
    if depth > 4:
        return set()
    
    if filepath in visited:
        return set()
    visited.add(filepath)
    
    try:
        content = Path(filepath).read_text(errors='ignore')
    except:
        return set()
    
    all_incs = set()
    for line in content.split('\n'):
        m = re.match(r'#include <([^>]+)>', line.strip())
        if m:
            inc = m.group(1)
            all_incs.add(inc)
            # Recursively find includes from this include
            for candidate in Path('src').glob(f'**/{Path(inc).name}'):
                if candidate.is_file():
                    all_incs.update(find_all_includes(str(candidate), visited, depth+1))
    
    return all_incs

# Check a few key direct includes from miner.cpp
miner_direct = [
    'governance/governance.h',
    'chain.h',
    'validation.h',
    'evo/chainhelper.h'
]

print("Checking if coinjoin/coinjoin.h is transitively included:")
for inc in miner_direct:
    filepath = f'src/{inc}'
    if Path(filepath).exists():
        all_incs = find_all_includes(filepath)
        if 'coinjoin/coinjoin.h' in all_incs or 'coinjoin.h' in all_incs:
            print(f"  ✓ {inc} -> includes coinjoin/coinjoin.h")
        if 'timedata.h' in all_incs:
            print(f"  ✓ {inc} -> includes timedata.h")

PY

Repository: dashpay/dash

Length of output: 730


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check governance/classes.h includes ==="
grep "#include" src/governance/classes.h

echo ""
echo "=== Check if any Dash subsystem header (evo, llmq, etc) includes timedata transitively ==="
for header in src/evo/*.h src/llmq/*.h; do
  if grep -q "timedata" "$header" 2>/dev/null; then
    echo "Found timedata ref in: $header"
    grep -n "timedata" "$header"
  fi
done

echo ""
echo "=== Most important: Check if coinjoin/coinjoin.h is included transitively ==="
python3 << 'PY'
import re
from pathlib import Path

# Check if coinjoin.h is included transitively from miner.cpp's direct includes
def find_all_includes(filepath, visited=None, depth=0):
    """Recursively find ALL includes."""
    if visited is None:
        visited = set()
    if depth > 4:
        return set()
    
    if filepath in visited:
        return set()
    visited.add(filepath)
    
    try:
        content = Path(filepath).read_text(errors='ignore')
    except:
        return set()
    
    all_incs = set()
    for line in content.split('\n'):
        m = re.match(r'#include <([^>]+)>', line.strip())
        if m:
            inc = m.group(1)
            all_incs.add(inc)
            # Recursively find includes from this include
            for candidate in Path('src').glob(f'**/{Path(inc).name}'):
                if candidate.is_file():
                    all_incs.update(find_all_includes(str(candidate), visited, depth+1))
    
    return all_incs

# Check a few key direct includes from miner.cpp
miner_direct = [
    'governance/governance.h',
    'chain.h',
    'validation.h',
    'evo/chainhelper.h'
]

print("Checking if coinjoin/coinjoin.h is transitively included:")
for inc in miner_direct:
    filepath = f'src/{inc}'
    if Path(filepath).exists():
        all_incs = find_all_includes(filepath)
        if 'coinjoin/coinjoin.h' in all_incs or 'coinjoin.h' in all_incs:
            print(f"  ✓ {inc} -> includes coinjoin/coinjoin.h")
        if 'timedata.h' in all_incs:
            print(f"  ✓ {inc} -> includes timedata.h")

PY

Repository: dashpay/dash

Length of output: 580


Add explicit #include <timedata.h> to avoid relying on transitive includes.

GetAdjustedTime() is declared only in timedata.h and used at lines 52 and 221, but this TU currently depends on a transitive include chain (governance/governance.hcoinjoin/coinjoin.htimedata.h). While this compiles, it's fragile: any changes to coinjoin/coinjoin.h's includes would silently break this compilation unit.

Suggested fix
`#include` <node/miner.h>

`#include` <chain.h>
+#include <timedata.h>
`#include` <chainparams.h>
🧰 Tools
🪛 Cppcheck (2.19.0)

[error] 24-24: #error No known always_inline attribute for this platform.

(preprocessorErrorDirective)

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

In `@src/node/miner.cpp` at line 24, Add an explicit include for timedata.h in
miner.cpp to stop relying on transitive includes: include <timedata.h> near the
top of the file so that GetAdjustedTime() (used in miner.cpp at the calls around
GetAdjustedTime() lines) is declared directly rather than via
governance/governance.h → coinjoin/coinjoin.h; update the include block in
miner.cpp to add <timedata.h> alongside the existing <util/time.h>.

#include <validation.h>

#include <chainlock/chainlock.h>
Expand Down
1 change: 1 addition & 0 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>
Expand Down
3 changes: 0 additions & 3 deletions src/timedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
#ifndef BITCOIN_TIMEDATA_H
#define BITCOIN_TIMEDATA_H

#include <util/time.h>

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdint>
#include <vector>

Expand Down
4 changes: 4 additions & 0 deletions test/functional/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ don't have test cases for.
`set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of
the subclass, then locally-defined helper methods, then the `run_test()` method.
- Use `f'{x}'` for string formatting in preference to `'{}'.format(x)` or `'%s' % x`.
- Use `platform.system()` for detecting the running operating system and `os.name` to
check whether it's a POSIX system (see also the `skip_if_platform_not_{linux,posix}`
methods in the `BitcoinTestFramework` class, which can be used to skip a whole test
depending on the platform).

#### Naming guidelines

Expand Down
10 changes: 3 additions & 7 deletions test/functional/feature_bind_extra.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@
that bind happens on the expected ports.
"""

import sys

from test_framework.netutil import (
addr_to_hex,
get_bind_addrs,
)
from test_framework.test_framework import (
BitcoinTestFramework,
SkipTest,
)
from test_framework.util import (
assert_equal,
Expand All @@ -32,12 +29,11 @@ def set_test_params(self):
self.bind_to_localhost_only = False
self.num_nodes = 2

def setup_network(self):
def skip_test_if_missing_module(self):
# Due to OS-specific network stats queries, we only run on Linux.
self.log.info("Checking for Linux")
if not sys.platform.startswith('linux'):
raise SkipTest("This test can only be run on Linux.")
self.skip_if_platform_not_linux()

def setup_network(self):
loopback_ipv4 = addr_to_hex("127.0.0.1")

# Start custom ports by reusing unused p2p ports
Expand Down
4 changes: 2 additions & 2 deletions test/functional/feature_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Stress tests related to node initialization."""
import os
from pathlib import Path
from random import randint
import platform
import shutil

from test_framework.test_framework import BitcoinTestFramework, SkipTest
Expand Down Expand Up @@ -37,7 +37,7 @@ def run_test(self):
# and other approaches (like below) don't work:
#
# os.kill(node.process.pid, signal.CTRL_C_EVENT)
if os.name == 'nt':
if platform.system() == 'Windows':
raise SkipTest("can't SIGTERM on Windows")

self.stop_node(0)
Expand Down
9 changes: 5 additions & 4 deletions test/functional/feature_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the -alertnotify, -blocknotify, -chainlocknotify, -instantsendnotify and -walletnotify options."""
import os
import platform

from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE

Expand All @@ -16,13 +17,13 @@

# Linux allow all characters other than \x00
# Windows disallow control characters (0-31) and /\?%:|"<>
FILE_CHAR_START = 32 if os.name == 'nt' else 1
FILE_CHAR_START = 32 if platform.system() == 'Windows' else 1
FILE_CHAR_END = 128
FILE_CHARS_DISALLOWED = '/\\?%*:|"<>' if os.name == 'nt' else '/'
FILE_CHARS_DISALLOWED = '/\\?%*:|"<>' if platform.system() == 'Windows' else '/'
UNCONFIRMED_HASH_STRING = 'unconfirmed'

def notify_outputname(walletname, txid):
return txid if os.name == 'nt' else f'{walletname}_{txid}'
return txid if platform.system() == 'Windows' else f'{walletname}_{txid}'


class NotificationsTest(DashTestFramework):
Expand Down Expand Up @@ -170,7 +171,7 @@ def expect_wallet_notify(self, tx_details):
# Universal newline ensures '\n' on 'nt'
assert_equal(text[-1], '\n')
text = text[:-1]
if os.name == 'nt':
if platform.system() == 'Windows':
# On Windows, echo as above will append a whitespace
assert_equal(text[-1], ' ')
text = text[:-1]
Expand Down
11 changes: 4 additions & 7 deletions test/functional/rpc_bind.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test running dashd with the -rpcbind and -rpcallowip options."""

import sys

from test_framework.netutil import all_interfaces, addr_to_hex, get_bind_addrs, test_ipv6_local
from test_framework.test_framework import BitcoinTestFramework, SkipTest
from test_framework.util import assert_equal, assert_raises_rpc_error, get_rpc_proxy, rpc_port, rpc_url
Expand All @@ -17,6 +15,10 @@ def set_test_params(self):
self.num_nodes = 1
self.supports_cli = False

def skip_test_if_missing_module(self):
# due to OS-specific network stats queries, this test works only on Linux
self.skip_if_platform_not_linux()

def setup_network(self):
self.add_nodes(self.num_nodes, None)

Expand Down Expand Up @@ -61,14 +63,9 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport):
self.stop_nodes()

def run_test(self):
# due to OS-specific network stats queries, this test works only on Linux
if sum([self.options.run_ipv4, self.options.run_ipv6, self.options.run_nonloopback]) > 1:
raise AssertionError("Only one of --ipv4, --ipv6 and --nonloopback can be set")

self.log.info("Check for linux")
if not sys.platform.startswith('linux'):
raise SkipTest("This test can only be run on linux.")

self.log.info("Check for ipv6")
have_ipv6 = test_ipv6_local()
if not have_ipv6 and not (self.options.run_ipv4 or self.options.run_nonloopback):
Expand Down
2 changes: 1 addition & 1 deletion test/functional/rpc_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def test_getpeerinfo(self):
self.log.info("Check getpeerinfo output before a version message was sent")
no_version_peer_id = 3
no_version_peer_conntime = self.mocktime
with self.nodes[0].assert_debug_log([f"Added connection peer={no_version_peer_id}"]):
with self.nodes[0].wait_for_new_peer():
no_version_peer = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
if self.options.v2transport:
self.wait_until(lambda: self.nodes[0].getpeerinfo()[no_version_peer_id]["transport_protocol_type"] == "v2")
Expand Down
3 changes: 2 additions & 1 deletion test/functional/test_framework/p2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from collections import defaultdict
from io import BytesIO
import logging
import platform
import struct
import sys
import threading
Expand Down Expand Up @@ -788,7 +789,7 @@ def __init__(self):

NetworkThread.listeners = {}
NetworkThread.protos = {}
if sys.platform == 'win32':
if platform.system() == 'Windows':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
NetworkThread.network_event_loop = asyncio.new_event_loop()

Expand Down
4 changes: 2 additions & 2 deletions test/functional/test_framework/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
import json
import logging
import os.path
import platform
import re
import subprocess
import tempfile
import time
import urllib.parse
import shlex
import sys
import collections
from pathlib import Path

Expand Down Expand Up @@ -573,7 +573,7 @@ def test_success(cmd):
cmd, shell=True,
stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) == 0

if not sys.platform.startswith('linux'):
if platform.system() != 'Linux':
self.log.warning("Can't profile with perf; only available on Linux platforms")
return None

Expand Down
3 changes: 2 additions & 1 deletion test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import configparser
import datetime
import os
import platform
import time
import shutil
import signal
Expand All @@ -42,7 +43,7 @@
CROSS = "x "
CIRCLE = "o "

if os.name == 'nt': #type:ignore
if platform.system() == 'Windows': #type:ignore
import ctypes
kernel32 = ctypes.windll.kernel32 # type: ignore
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
Expand Down
4 changes: 2 additions & 2 deletions test/functional/wallet_multiwallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from threading import Thread
from decimal import Decimal
import os
import platform
import shutil
import stat
import sys
import time

from test_framework.authproxy import JSONRPCException
Expand Down Expand Up @@ -143,7 +143,7 @@ def wallet_file(name):

# should raise rpc error if wallet path can't be created
err_code = -4 if self.options.descriptors else -1
assert_raises_rpc_error(err_code, "filesystem error:" if sys.platform != 'win32' else "create_directories:", self.nodes[0].createwallet, "w8/bad")
assert_raises_rpc_error(err_code, "filesystem error:" if platform.system() != 'Windows' else "create_directories:", self.nodes[0].createwallet, "w8/bad")

# check that all requested wallets were created
self.stop_node(0)
Expand Down
Loading