mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-22 16:14:50 +01:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf03c458e9 | ||
|
|
dd1bf8bc4e | ||
|
|
f42fcf6ad7 | ||
|
|
6c09325757 | ||
|
|
c838ce514f | ||
|
|
882e0d730d | ||
|
|
0cdfb7e45c | ||
|
|
693403bed6 | ||
|
|
c338e43c6f | ||
|
|
84df30927a | ||
|
|
b06c4c6550 | ||
|
|
57de0f5e77 | ||
|
|
ccff378a28 | ||
|
|
500bba0561 | ||
|
|
0cbdc6b380 | ||
|
|
4f23c86364 | ||
|
|
54bb9b0541 | ||
|
|
f22b9ca70c | ||
|
|
05192ba84c | ||
|
|
ab42206652 | ||
|
|
064f214673 | ||
|
|
0933cf53b4 | ||
|
|
fa90989503 | ||
|
|
b6440f20f2 | ||
|
|
b3093eb755 | ||
|
|
6338f92260 | ||
|
|
f34e44616d | ||
|
|
0d524b1484 | ||
|
|
43c40dd808 |
14
.cirrus.yml
14
.cirrus.yml
@@ -43,7 +43,6 @@ env: # Global defaults
|
||||
# The following specific types should exist, with the following requirements:
|
||||
# - small: For an x86_64 machine, recommended to have 2 CPUs and 8 GB of memory.
|
||||
# - medium: For an x86_64 machine, recommended to have 4 CPUs and 16 GB of memory.
|
||||
# - noble: For a machine running the Linux kernel shipped with exaclty Ubuntu Noble 24.04. The machine is recommended to have 4 CPUs and 16 GB of memory.
|
||||
# - arm64: For an aarch64 machine, recommended to have 2 CPUs and 8 GB of memory.
|
||||
|
||||
# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
|
||||
@@ -159,19 +158,6 @@ task:
|
||||
env:
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_msan.sh"
|
||||
|
||||
task:
|
||||
name: 'ASan + LSan + UBSan + integer, no depends, USDT'
|
||||
enable_bpfcc_script:
|
||||
# In the image build step, no external environment variables are available,
|
||||
# so any settings will need to be written to the settings env file:
|
||||
- sed -i "s|\${CIRRUS_CI}|true|g" ./ci/test/00_setup_env_native_asan.sh
|
||||
<< : *GLOBAL_TASK_TEMPLATE
|
||||
persistent_worker:
|
||||
labels:
|
||||
type: noble # Must use this specific worker (needed for USDT functional tests)
|
||||
env:
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
|
||||
|
||||
task:
|
||||
name: 'fuzzer,address,undefined,integer, no depends'
|
||||
<< : *GLOBAL_TASK_TEMPLATE
|
||||
|
||||
41
.github/workflows/ci.yml
vendored
41
.github/workflows/ci.yml
vendored
@@ -18,7 +18,6 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
DANGER_RUN_CI_ON_HOST: 1
|
||||
CI_FAILFAST_TEST_LEAVE_DANGLING: 1 # GHA does not care about dangling processes and setting this variable avoids killing the CI script itself on error
|
||||
MAKEJOBS: '-j10'
|
||||
|
||||
@@ -81,6 +80,7 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
|
||||
env:
|
||||
DANGER_RUN_CI_ON_HOST: 1
|
||||
FILE_ENV: './ci/test/00_setup_env_mac_native.sh'
|
||||
BASE_ROOT_DIR: ${{ github.workspace }}
|
||||
|
||||
@@ -294,3 +294,42 @@ jobs:
|
||||
TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }}
|
||||
shell: cmd
|
||||
run: py -3 test\functional\test_runner.py --jobs %NUMBER_OF_PROCESSORS% --ci --quiet --tmpdirprefix=%RUNNER_TEMP% --combinedlogslen=99999999 --timeout-factor=%TEST_RUNNER_TIMEOUT_FACTOR% %TEST_RUNNER_EXTRA%
|
||||
|
||||
asan-lsan-ubsan-integer-no-depends-usdt:
|
||||
name: 'ASan + LSan + UBSan + integer, no depends, USDT'
|
||||
runs-on: ubuntu-24.04 # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools
|
||||
# No need to run on the read-only mirror, unless it is a PR.
|
||||
if: github.repository != 'bitcoin-core/gui' || github.event_name == 'pull_request'
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Ccache directory
|
||||
run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Restore Ccache cache
|
||||
id: ccache-cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ github.job }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ github.job }}-ccache-
|
||||
|
||||
- name: Enable bpfcc script
|
||||
# In the image build step, no external environment variables are available,
|
||||
# so any settings will need to be written to the settings env file:
|
||||
run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh
|
||||
|
||||
- name: CI script
|
||||
run: ./ci/test_run_all.sh
|
||||
|
||||
- name: Save Ccache cache
|
||||
uses: actions/cache/save@v4
|
||||
if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
key: ${{ github.job }}-ccache-${{ github.run_id }}
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04"
|
||||
# Only install BCC tracing packages in Cirrus CI.
|
||||
if [[ "${CIRRUS_CI}" == "true" ]]; then
|
||||
|
||||
# Only install BCC tracing packages in CI. Container has to match the host for BCC to work.
|
||||
if [[ "${INSTALL_BCC_TRACING_TOOLS}" == "true" ]]; then
|
||||
# Required for USDT functional tests to run
|
||||
BPFCC_PACKAGE="bpfcc-tools linux-headers-$(uname --kernel-release)"
|
||||
export CI_CONTAINER_CAP="--privileged -v /sys/kernel:/sys/kernel:rw"
|
||||
else
|
||||
|
||||
@@ -16,6 +16,7 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
|
||||
# System-dependent env vars must be kept as is. So read them from the container.
|
||||
docker run --rm "${CI_IMAGE_NAME_TAG}" bash -c "env | grep --extended-regexp '^(HOME|PATH|USER)='" | tee --append "/tmp/env-$USER-$CONTAINER_NAME"
|
||||
echo "Creating $CI_IMAGE_NAME_TAG container to run in"
|
||||
|
||||
DOCKER_BUILDKIT=1 docker build \
|
||||
--file "${BASE_READ_ONLY_DIR}/ci/test_imagefile" \
|
||||
--build-arg "CI_IMAGE_NAME_TAG=${CI_IMAGE_NAME_TAG}" \
|
||||
@@ -23,12 +24,15 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
|
||||
--label="${CI_IMAGE_LABEL}" \
|
||||
--tag="${CONTAINER_NAME}" \
|
||||
"${BASE_READ_ONLY_DIR}"
|
||||
|
||||
docker volume create "${CONTAINER_NAME}_ccache" || true
|
||||
docker volume create "${CONTAINER_NAME}_depends" || true
|
||||
docker volume create "${CONTAINER_NAME}_depends_sources" || true
|
||||
docker volume create "${CONTAINER_NAME}_depends_SDKs_android" || true
|
||||
docker volume create "${CONTAINER_NAME}_previous_releases" || true
|
||||
|
||||
docker network create --ipv6 --subnet 1111:1111::/112 ci-ip6net || true
|
||||
|
||||
if [ -n "${RESTART_CI_DOCKER_BEFORE_RUN}" ] ; then
|
||||
echo "Restart docker before run to stop and clear all containers started with --rm"
|
||||
podman container rm --force --all # Similar to "systemctl restart docker"
|
||||
@@ -56,6 +60,7 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
|
||||
--mount "type=volume,src=${CONTAINER_NAME}_previous_releases,dst=$PREVIOUS_RELEASES_DIR" \
|
||||
--env-file /tmp/env-$USER-$CONTAINER_NAME \
|
||||
--name "$CONTAINER_NAME" \
|
||||
--network ci-ip6net \
|
||||
"$CONTAINER_NAME")
|
||||
export CI_CONTAINER_ID
|
||||
export CI_EXEC_CMD_PREFIX="docker exec ${CI_CONTAINER_ID}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
AC_PREREQ([2.69])
|
||||
define(_CLIENT_VERSION_MAJOR, 27)
|
||||
define(_CLIENT_VERSION_MINOR, 1)
|
||||
define(_CLIENT_VERSION_MINOR, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_RC, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-CLI "1" "June 2024" "bitcoin-cli v27.1.0" "User Commands"
|
||||
.TH BITCOIN-CLI "1" "October 2024" "bitcoin-cli v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-cli \- manual page for bitcoin-cli v27.1.0
|
||||
bitcoin-cli \- manual page for bitcoin-cli v27.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR
|
||||
@@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v27.1.0
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core RPC client version v27.1.0
|
||||
Bitcoin Core RPC client version v27.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-QT "1" "June 2024" "bitcoin-qt v27.1.0" "User Commands"
|
||||
.TH BITCOIN-QT "1" "October 2024" "bitcoin-qt v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-qt \- manual page for bitcoin-qt v27.1.0
|
||||
bitcoin-qt \- manual page for bitcoin-qt v27.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-qt
|
||||
[\fI\,command-line options\/\fR] [\fI\,URI\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v27.1.0
|
||||
Bitcoin Core version v27.2.0
|
||||
.PP
|
||||
Optional URI is a Bitcoin address in BIP21 URI format.
|
||||
.SH OPTIONS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-TX "1" "June 2024" "bitcoin-tx v27.1.0" "User Commands"
|
||||
.TH BITCOIN-TX "1" "October 2024" "bitcoin-tx v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-tx \- manual page for bitcoin-tx v27.1.0
|
||||
bitcoin-tx \- manual page for bitcoin-tx v27.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR
|
||||
@@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v27.1.0
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-tx utility version v27.1.0
|
||||
Bitcoin Core bitcoin\-tx utility version v27.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-UTIL "1" "June 2024" "bitcoin-util v27.1.0" "User Commands"
|
||||
.TH BITCOIN-UTIL "1" "October 2024" "bitcoin-util v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-util \- manual page for bitcoin-util v27.1.0
|
||||
bitcoin-util \- manual page for bitcoin-util v27.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-util
|
||||
[\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-util utility version v27.1.0
|
||||
Bitcoin Core bitcoin\-util utility version v27.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-WALLET "1" "June 2024" "bitcoin-wallet v27.1.0" "User Commands"
|
||||
.TH BITCOIN-WALLET "1" "October 2024" "bitcoin-wallet v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v27.1.0
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v27.2.0
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-wallet version v27.1.0
|
||||
Bitcoin Core bitcoin\-wallet version v27.2.0
|
||||
.PP
|
||||
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
|
||||
By default bitcoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIND "1" "June 2024" "bitcoind v27.1.0" "User Commands"
|
||||
.TH BITCOIND "1" "October 2024" "bitcoind v27.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoind \- manual page for bitcoind v27.1.0
|
||||
bitcoind \- manual page for bitcoind v27.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoind
|
||||
[\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v27.1.0
|
||||
Bitcoin Core version v27.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
27.1 Release Notes
|
||||
27.2 Release Notes
|
||||
=====================
|
||||
|
||||
Bitcoin Core version 27.1 is now available from:
|
||||
Bitcoin Core version 27.2 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-27.1/>
|
||||
<https://bitcoincore.org/bin/bitcoin-core-27.2/>
|
||||
|
||||
This release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
@@ -40,74 +40,52 @@ unsupported systems.
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
### Miniscript
|
||||
### P2P
|
||||
|
||||
- #29853 sign: don't assume we are parsing a sane TapMiniscript
|
||||
- #30394 net: fix race condition in self-connect detection
|
||||
|
||||
### Init
|
||||
|
||||
- #30435 init: change shutdown order of load block thread and scheduler
|
||||
|
||||
### RPC
|
||||
|
||||
- #29869 rpc, bugfix: Enforce maximum value for setmocktime
|
||||
- #29870 rpc: Reword SighashFromStr error message
|
||||
- #30094 rpc: move UniValue in blockToJSON
|
||||
- #30357 Fix cases of calls to FillPSBT errantly returning complete=true
|
||||
|
||||
### Index
|
||||
### PSBT
|
||||
|
||||
- #29776 Fix #29767, set m_synced = true after Commit()
|
||||
|
||||
### Gui
|
||||
|
||||
- #gui812 Fix create unsigned transaction fee bump
|
||||
- #gui813 Don't permit port in proxy IP option
|
||||
- #29855 psbt: Check non witness utxo outpoint early
|
||||
|
||||
### Test
|
||||
|
||||
- #29892 test: Fix failing univalue float test
|
||||
|
||||
### P2P
|
||||
|
||||
- #30085 p2p: detect addnode cjdns peers in GetAddedNodeInfo()
|
||||
|
||||
### Build
|
||||
|
||||
- #29747 depends: fix mingw-w64 Qt DEBUG=1 build
|
||||
- #29859 build: Fix false positive CHECK_ATOMIC test
|
||||
- #29985 depends: Fix build of Qt for 32-bit platforms with recent glibc
|
||||
- #30097 crypto: disable asan for sha256_sse4 with clang and -O0
|
||||
- #30151 depends: Fetch miniupnpc sources from an alternative website
|
||||
- #30216 build: Fix building fuzz binary on on SunOS / illumos
|
||||
- #30217 depends: Update Boost download link
|
||||
- #30552 test: fix constructor of msg_tx
|
||||
|
||||
### Doc
|
||||
|
||||
- #29934 doc: add LLVM instruction for macOS < 13
|
||||
- #30504 doc: use proper doxygen formatting for CTxMemPool::cs
|
||||
|
||||
### Build
|
||||
|
||||
- #30283 upnp: fix build with miniupnpc 2.2.8
|
||||
- #30633 Fixes for GCC 15 compatibility
|
||||
|
||||
### CI
|
||||
|
||||
- #29856 ci: Bump s390x to ubuntu:24.04
|
||||
|
||||
### Misc
|
||||
|
||||
- #29691 Change Luke Dashjr seed to dashjr-list-of-p2p-nodes.us
|
||||
- #30149 contrib: Renew Windows code signing certificate
|
||||
- #30193 ci: move ASan job to GitHub Actions from Cirrus CI
|
||||
- #30299 ci: remove unused bcc variable from workflow
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Antoine Poinsot
|
||||
- Ava Chow
|
||||
- Cory Fields
|
||||
- dergoegge
|
||||
- fanquake
|
||||
- furszy
|
||||
- Hennadii Stepanov
|
||||
- Jon Atack
|
||||
- laanwj
|
||||
- Luke Dashjr
|
||||
- MarcoFalke
|
||||
- nanlour
|
||||
- Sjors Provoost
|
||||
- Martin Zumsande
|
||||
- Matt Whitlock
|
||||
- Max Edwards
|
||||
- Sebastian Falbesoner
|
||||
- Vasil Dimov
|
||||
- willcl-ark
|
||||
|
||||
As well as to everyone that helped with translations on
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <util/chaintype.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -296,10 +296,11 @@ void Shutdown(NodeContext& node)
|
||||
|
||||
StopTorControl();
|
||||
|
||||
// After everything has been shut down, but before things get flushed, stop the
|
||||
// scheduler and load block thread.
|
||||
if (node.scheduler) node.scheduler->stop();
|
||||
if (node.chainman && node.chainman->m_thread_load.joinable()) node.chainman->m_thread_load.join();
|
||||
// After everything has been shut down, but before things get flushed, stop the
|
||||
// the scheduler. After this point, SyncWithValidationInterfaceQueue() should not be called anymore
|
||||
// as this would prevent the shutdown from completing.
|
||||
if (node.scheduler) node.scheduler->stop();
|
||||
|
||||
// After the threads that potentially access these pointers have been stopped,
|
||||
// destruct and reset all to nullptr.
|
||||
|
||||
@@ -163,8 +163,11 @@ static bool ProcessUpnp()
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
int r;
|
||||
|
||||
#if MINIUPNPC_API_VERSION <= 17
|
||||
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
|
||||
#else
|
||||
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), nullptr, 0);
|
||||
#endif
|
||||
if (r == 1)
|
||||
{
|
||||
if (fDiscover) {
|
||||
|
||||
@@ -999,8 +999,8 @@ public:
|
||||
/** Mutex for anything that is only accessed via the msg processing thread */
|
||||
static Mutex g_msgproc_mutex;
|
||||
|
||||
/** Initialize a peer (setup state, queue any initial messages) */
|
||||
virtual void InitializeNode(CNode& node, ServiceFlags our_services) = 0;
|
||||
/** Initialize a peer (setup state) */
|
||||
virtual void InitializeNode(const CNode& node, ServiceFlags our_services) = 0;
|
||||
|
||||
/** Handle removal of a peer (clear state) */
|
||||
virtual void FinalizeNode(const CNode& node) = 0;
|
||||
|
||||
@@ -245,6 +245,9 @@ struct Peer {
|
||||
* Most peers use headers-first syncing, which doesn't use this mechanism */
|
||||
uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
|
||||
|
||||
/** Set to true once initial VERSION message was sent (only relevant for outbound peers). */
|
||||
bool m_outbound_version_message_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
|
||||
|
||||
/** This peer's reported block height when we connected */
|
||||
std::atomic<int> m_starting_height{-1};
|
||||
|
||||
@@ -499,7 +502,7 @@ public:
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);
|
||||
|
||||
/** Implement NetEventsInterface */
|
||||
void InitializeNode(CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
||||
void InitializeNode(const CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
||||
void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
|
||||
bool HasAllDesirableServiceFlags(ServiceFlags services) const override;
|
||||
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override
|
||||
@@ -1563,7 +1566,7 @@ void PeerManagerImpl::UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_s
|
||||
if (state) state->m_last_block_announcement = time_in_seconds;
|
||||
}
|
||||
|
||||
void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
|
||||
void PeerManagerImpl::InitializeNode(const CNode& node, ServiceFlags our_services)
|
||||
{
|
||||
NodeId nodeid = node.GetId();
|
||||
{
|
||||
@@ -1576,9 +1579,6 @@ void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
|
||||
LOCK(m_peer_mutex);
|
||||
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
|
||||
}
|
||||
if (!node.IsInboundConn()) {
|
||||
PushNodeVersion(node, *peer);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
|
||||
@@ -5060,6 +5060,10 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
|
||||
PeerRef peer = GetPeerRef(pfrom->GetId());
|
||||
if (peer == nullptr) return false;
|
||||
|
||||
// For outbound connections, ensure that the initial VERSION message
|
||||
// has been sent first before processing any incoming messages
|
||||
if (!pfrom->IsInboundConn() && !peer->m_outbound_version_message_sent) return false;
|
||||
|
||||
{
|
||||
LOCK(peer->m_getdata_requests_mutex);
|
||||
if (!peer->m_getdata_requests.empty()) {
|
||||
@@ -5548,6 +5552,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||
// disconnect misbehaving peers even before the version handshake is complete.
|
||||
if (MaybeDiscourageAndDisconnect(*pto, *peer)) return true;
|
||||
|
||||
// Initiate version handshake for outbound connections
|
||||
if (!pto->IsInboundConn() && !peer->m_outbound_version_message_sent) {
|
||||
PushNodeVersion(*pto, *peer);
|
||||
peer->m_outbound_version_message_sent = true;
|
||||
}
|
||||
|
||||
// Don't send anything until the version handshake is complete
|
||||
if (!pto->fSuccessfullyConnected || pto->fDisconnect)
|
||||
return true;
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#ifndef BITCOIN_NODE_INTERFACE_UI_H
|
||||
#define BITCOIN_NODE_INTERFACE_UI_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CBlockIndex;
|
||||
enum class SynchronizationState;
|
||||
|
||||
@@ -38,10 +38,8 @@ private:
|
||||
public:
|
||||
/** Fee rate of 0 satoshis per kvB */
|
||||
CFeeRate() : nSatoshisPerK(0) { }
|
||||
template<typename I>
|
||||
template<std::integral I> // Disallow silent float -> int conversion
|
||||
explicit CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) {
|
||||
// We've previously had bugs creep in from silent double->int conversion...
|
||||
static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1173,8 +1173,13 @@ struct PartiallySignedTransaction
|
||||
inputs.push_back(input);
|
||||
|
||||
// Make sure the non-witness utxo matches the outpoint
|
||||
if (input.non_witness_utxo && input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
|
||||
throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
|
||||
if (input.non_witness_utxo) {
|
||||
if (input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
|
||||
throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
|
||||
}
|
||||
if (tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
|
||||
throw std::ios_base::failure("Input specifies output index that does not exist");
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ void ConnmanTestMsg::Handshake(CNode& node,
|
||||
auto& connman{*this};
|
||||
|
||||
peerman.InitializeNode(node, local_services);
|
||||
FlushSendBuffer(node); // Drop the version message added by InitializeNode.
|
||||
peerman.SendMessages(&node);
|
||||
FlushSendBuffer(node); // Drop the version message added by SendMessages.
|
||||
|
||||
CSerializedNetMsg msg_version{
|
||||
NetMsg::Make(NetMsgType::VERSION,
|
||||
|
||||
@@ -363,9 +363,7 @@ public:
|
||||
* that are guarded by it.
|
||||
*
|
||||
* @par Consistency guarantees
|
||||
*
|
||||
* By design, it is guaranteed that:
|
||||
*
|
||||
* 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool
|
||||
* that is consistent with current chain tip (`ActiveChain()` and
|
||||
* `CoinsTip()`) and is fully populated. Fully populated means that if the
|
||||
@@ -373,7 +371,6 @@ public:
|
||||
* previously active chain, all the missing transactions will have been
|
||||
* re-added to the mempool and should be present if they meet size and
|
||||
* consistency constraints.
|
||||
*
|
||||
* 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool
|
||||
* consistent with some chain that was active since `cs_main` was last
|
||||
* locked, and that is fully populated as described above. It is ok for
|
||||
|
||||
@@ -2184,8 +2184,8 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
|
||||
|
||||
// Complete if every input is now signed
|
||||
complete = true;
|
||||
for (const auto& input : psbtx.inputs) {
|
||||
complete &= PSBTInputSigned(input);
|
||||
for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
|
||||
complete &= PSBTInputSignedAndVerified(psbtx, i, &txdata);
|
||||
}
|
||||
|
||||
return TransactionError::OK;
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
"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"
|
||||
],
|
||||
"invalid_with_msg": [
|
||||
[
|
||||
|
||||
26
test/functional/p2p_handshake.py
Executable file
26
test/functional/p2p_handshake.py
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2024 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""
|
||||
Test P2P behaviour during the handshake phase.
|
||||
"""
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import p2p_port
|
||||
|
||||
|
||||
class P2PHandshakeTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Check that connecting to ourself leads to immediate disconnect")
|
||||
with node.assert_debug_log(["connected to self", "disconnecting"]):
|
||||
node_listen_addr = f"127.0.0.1:{p2p_port(0)}"
|
||||
node.addconnection(node_listen_addr, "outbound-full-relay", self.options.v2transport)
|
||||
self.wait_until(lambda: len(node.getpeerinfo()) == 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
P2PHandshakeTest().main()
|
||||
@@ -69,6 +69,28 @@ class PSBTTest(BitcoinTestFramework):
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def test_psbt_incomplete_after_invalid_modification(self):
|
||||
self.log.info("Check that PSBT is correctly marked as incomplete after invalid modification")
|
||||
node = self.nodes[2]
|
||||
wallet = node.get_wallet_rpc(self.default_wallet_name)
|
||||
address = wallet.getnewaddress()
|
||||
wallet.sendtoaddress(address=address, amount=1.0)
|
||||
self.generate(node, nblocks=1, sync_fun=lambda: self.sync_all(self.nodes[:2]))
|
||||
|
||||
utxos = wallet.listunspent(addresses=[address])
|
||||
psbt = wallet.createpsbt([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{wallet.getnewaddress(): 0.9999}])
|
||||
signed_psbt = wallet.walletprocesspsbt(psbt)["psbt"]
|
||||
|
||||
# Modify the raw transaction by changing the output address, so the signature is no longer valid
|
||||
signed_psbt_obj = PSBT.from_base64(signed_psbt)
|
||||
substitute_addr = wallet.getnewaddress()
|
||||
raw = wallet.createrawtransaction([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{substitute_addr: 0.9999}])
|
||||
signed_psbt_obj.g.map[PSBT_GLOBAL_UNSIGNED_TX] = bytes.fromhex(raw)
|
||||
|
||||
# Check that the walletprocesspsbt call succeeds but also recognizes that the transaction is not complete
|
||||
signed_psbt_incomplete = wallet.walletprocesspsbt(signed_psbt_obj.to_base64(), finalize=False)
|
||||
assert signed_psbt_incomplete["complete"] is False
|
||||
|
||||
def test_utxo_conversion(self):
|
||||
self.log.info("Check that non-witness UTXOs are removed for segwit v1+ inputs")
|
||||
mining_node = self.nodes[2]
|
||||
@@ -590,6 +612,7 @@ class PSBTTest(BitcoinTestFramework):
|
||||
|
||||
if self.options.descriptors:
|
||||
self.test_utxo_conversion()
|
||||
self.test_psbt_incomplete_after_invalid_modification()
|
||||
|
||||
self.test_input_confs_control()
|
||||
|
||||
@@ -701,11 +724,9 @@ class PSBTTest(BitcoinTestFramework):
|
||||
assert_equal(analysis['next'], 'creator')
|
||||
assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid')
|
||||
|
||||
analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
|
||||
assert_equal(analysis['next'], 'creator')
|
||||
assert_equal(analysis['error'], 'PSBT is not valid. Input 0 specifies invalid prevout')
|
||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].analyzepsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
|
||||
|
||||
assert_raises_rpc_error(-25, 'Inputs missing or spent', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
|
||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].walletprocesspsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
|
||||
|
||||
self.log.info("Test that we can fund psbts with external inputs specified")
|
||||
|
||||
|
||||
@@ -1293,8 +1293,11 @@ class msg_tx:
|
||||
__slots__ = ("tx",)
|
||||
msgtype = b"tx"
|
||||
|
||||
def __init__(self, tx=CTransaction()):
|
||||
self.tx = tx
|
||||
def __init__(self, tx=None):
|
||||
if tx is None:
|
||||
self.tx = CTransaction()
|
||||
else:
|
||||
self.tx = tx
|
||||
|
||||
def deserialize(self, f):
|
||||
self.tx.deserialize(f)
|
||||
|
||||
@@ -395,6 +395,8 @@ BASE_SCRIPTS = [
|
||||
'rpc_getdescriptorinfo.py',
|
||||
'rpc_mempool_info.py',
|
||||
'rpc_help.py',
|
||||
'p2p_handshake.py',
|
||||
'p2p_handshake.py --v2transport',
|
||||
'feature_dirsymlinks.py',
|
||||
'feature_help.py',
|
||||
'feature_shutdown.py',
|
||||
|
||||
Reference in New Issue
Block a user