Commit graph

4400 commits

Author SHA1 Message Date
Olaoluwa Osuntokun
58ee9ef65a server+connmgr: make outbound startup deterministic
In this commit, we define TargetOutbound as the number of automatic
connections and treat explicit Connect requests as additional peers.

Permanent requests could previously consume connection IDs before Start
sampled the shared counter. The resulting automatic count depended on
goroutine scheduling, while the listener reserved the worst-case total.
We now start the configured automatic count directly and cap it by the
peer budget left after permanent peers.

The composition test covers permanent requests on both sides of Start and
pins the same automatic+permanent total for either ordering.
2026-07-21 16:45:44 -07:00
Olaoluwa Osuntokun
5a2c5063b6 integration: synchronize p2p lifecycle stress batches
In this commit, we make each stress wave establish its full set of peers
before disconnecting them together. A ping/pong barrier proves the server
processed each verack, while RPC connection-count barriers prove
registration and removal completed before the next wave starts.

We bound concurrent handshakes from the shared source, drain every worker on
failure, and wait for server-side cleanup. This keeps the test compatible
with the admission limits it exercises and makes a passing run evidence of
the intended NewPeer/DonePeer ordering.
2026-07-21 16:45:25 -07:00
Olaoluwa Osuntokun
097178713e v2transport: restore responder handshake progress
In this commit, we send the responder key as soon as the initiator diverges
from the v1 prefix. This avoids the BIP324 deadlock where both sides can wait
for the other to write before the initiator has sent its complete 64-byte
key.

We split key generation and key agreement into separate admission leases,
and release each lease before the intervening network I/O. The regression
test stops after the first mismatch, requires the responder to make
progress, then completes key agreement and verifies the resulting packet
ciphers interoperate.
2026-07-21 16:45:06 -07:00
Olaoluwa Osuntokun
95c11c560a server+inbound: correct inbound admission accounting
In this commit, we keep loopback and whitelisted peers inside the ordinary
pending-handshake and V2 source budgets, while preserving their existing
no-ban behavior.

We also derive the listener reservation from the configured peer mode.
Connect-only and simnet nodes now reserve just their permanent peers, while
automatic mode accounts for both its target and addpeers without exceeding
MaxPeers.

Finally, a bound V2 handshake consumes its rate budgets once, but reacquires
the concurrency slot for each CPU-bound responder phase. This keeps rate
limiting scoped to the handshake while bounding both expensive phases.
2026-07-21 16:44:43 -07:00
Boris Nagaev
617ebe2b86
peer: close late connections after disconnect
In this commit, we serialize connection association with peer
disconnection. Previously, Disconnect could run before
AssociateConnection, close quit without a socket, and leave a later
connection published with no remaining path that could close it.

We now close connections handed to a peer that is already disconnecting,
and publish the connected flag only after the socket and connection time
are initialized. The tests pin both call orderings and race the
transitions to verify the socket closes exactly once.
2026-07-18 00:17:56 -05:00
Boris Nagaev
6c056ec471
server: centralize inbound handshake admission
In this commit, we introduce a server-wide admission policy for
incomplete inbound handshakes and the CPU-bound portion of v2 responder
setup. Source accounting uses normalized IPv4 and IPv6 prefixes, while
global, per-source, and concurrent v2 budgets remain independent and
bounded.

Peer construction passes the policy through a small interface only for
inbound v2 responders. Handshake slots release on verack or disconnect,
and the connection manager reserves MaxPeers capacity for automatic
outbound peers.
2026-07-18 00:17:55 -05:00
Boris Nagaev
ad8d94e62c
connmgr: bound accepted inbound connections
In this commit, we add an optional inbound connection limit at the
listener boundary. Each accepted socket owns a slot until Close releases
it exactly once, which makes connection lifetime, rather than accept
rate, the accounting unit.

The default remains unlimited for existing callers. The new tests cover
the configured bound, concurrent admission, callback ordering, and slot
reuse.
2026-07-18 00:17:55 -05:00
Boris Nagaev
6cad393577
v2transport: refactor responder setup
In this commit, we split the responder handshake into transport
classification, key setup, and wire completion phases. This lets callers
install a narrow admission interface after the full v2 candidate is
available, while preserving NewPeer compatibility and the existing
transcript.

We also propagate handshake write failures, reject short writes, and
cover v1 fallback, incomplete candidates, admission lifetime, and
end-to-end v2 interoperability.
2026-07-18 00:17:55 -05:00
Olaoluwa Osuntokun
484d39e6b0
Merge pull request #2567 from starius/psbt-trailing2
Some checks failed
Build and Test / Build (push) Has been cancelled
Build and Test / Unit coverage (push) Has been cancelled
Build and Test / Unit race (push) Has been cancelled
Build and Test / Unit rpctest (push) Has been cancelled
psbt: reject trailing final witness data
2026-07-16 20:53:32 -05:00
Boris Nagaev
c87168eba8
psbt: test final witness trailing data rejection 2026-07-08 00:14:19 -05:00
Boris Nagaev
468853e436
psbt: reject trailing final witness data 2026-07-08 00:14:19 -05:00
Olaoluwa Osuntokun
6cfd7172ea
Merge pull request #2558 from starius/trailing
Some checks failed
Build and Test / Build (push) Has been cancelled
Build and Test / Unit coverage (push) Has been cancelled
Build and Test / Unit race (push) Has been cancelled
Build and Test / Unit rpctest (push) Has been cancelled
multi: reject trailing characters when parsing inputs
2026-07-01 16:14:25 -07:00
Boris Nagaev
934349f12d
blockchain: test strict best block loading 2026-06-26 12:17:37 -05:00
Boris Nagaev
29cfb6ec9f
blockchain: load database blocks strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
f3ec349a60
rpc: test mempool accept trailing byte rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
676f61b91e
rpc: test submitblock trailing byte rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
ac17d23235
rpc: test block proposal trailing byte rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
7840b814d3
rpc: decode block proposals strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
40aca93c9c
rpc: test decoderawtransaction trailing byte rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
0d7259ee15
rpc: decode raw transaction RPC input strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
8074ebe950
rpc: test sendrawtransaction trailing byte rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
59db835591
rpc: decode sent raw transactions strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
81b07f6657
multi: use local submodules in root 2026-06-26 12:17:37 -05:00
Boris Nagaev
4a7a9fea10
musig2: test partial signature short reads 2026-06-26 12:17:37 -05:00
Boris Nagaev
63bc064d84
musig2: return partial signature read errors 2026-06-26 12:17:37 -05:00
Boris Nagaev
e72a65de00
btcutil: test byte constructors reject trailing data 2026-06-26 12:17:37 -05:00
Boris Nagaev
41d537d85e
btcutil: reject trailing data in byte constructors 2026-06-26 12:17:37 -05:00
Boris Nagaev
def22fa88e
btcutil/bloom: fix malformed filter test transaction 2026-06-26 12:17:37 -05:00
Boris Nagaev
42077fdb4a
wire: test v2 message trailing payload rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
03aeb81a6f
wire: reject trailing v2 message payload data 2026-06-26 12:17:37 -05:00
Boris Nagaev
0a33ccea29
psbt: test strict base64 packet decoding 2026-06-26 12:17:37 -05:00
Boris Nagaev
70e8ceb921
psbt: decode base64 packets strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
40ad911752
psbt: test witness utxo txout strict parsing 2026-06-26 12:17:37 -05:00
Boris Nagaev
b4c5cf1660
psbt: parse witness utxo txouts strictly 2026-06-26 12:17:37 -05:00
Boris Nagaev
0a1300ddf6
psbt: test trailing packet data rejection 2026-06-26 12:17:37 -05:00
Boris Nagaev
d1de2bc3ad
psbt: reject trailing packet data 2026-06-26 12:17:37 -05:00
Boris Nagaev
0293b6e0e0
psbt: add strict tx value regression test 2026-06-26 12:17:37 -05:00
Boris Nagaev
f945179f2a
psbt: reject trailing data in tx values 2026-06-26 12:17:37 -05:00
Boris Nagaev
da5792a8ce
psbt: add reader exhaustion helper 2026-06-26 12:17:37 -05:00
Olaoluwa Osuntokun
280d4d2db6
Merge pull request #2552 from btcsuite/version-bump
Some checks failed
Build and Test / Build (push) Has been cancelled
Build and Test / Unit coverage (push) Has been cancelled
Build and Test / Unit race (push) Has been cancelled
Build and Test / Unit rpctest (push) Has been cancelled
version: bump to v0.26.0-beta for final release
2026-06-18 15:57:54 -07:00
Olaoluwa Osuntokun
abec11012e version: bump to v0.26.0-beta for final release
In this commit, we drop the rc1 pre-release suffix, taking the version
from v0.26.0-beta.rc1 to v0.26.0-beta for the final release.
2026-06-18 15:45:55 -07:00
Olaoluwa Osuntokun
9dcdd4814b
Merge pull request #2548 from guggero/netsync-simnet-sync-candidate
Some checks are pending
Build and Test / Build (push) Waiting to run
Build and Test / Unit coverage (push) Waiting to run
Build and Test / Unit race (push) Waiting to run
Build and Test / Unit rpctest (push) Waiting to run
netsync: require block-serving services on regtest/simnet sync peers
2026-06-17 11:10:57 -07:00
Olaoluwa Osuntokun
3b9f0eb4ff
Merge pull request #2551 from ellemouton/ellemouton/rpcclient-submitpackage
rpcclient: add typed SubmitPackage method
2026-06-17 11:09:57 -07:00
Elle Mouton
de3d460e76
rpcclient: add typed SubmitPackage method
Add SubmitPackage / SubmitPackageAsync / FutureSubmitPackageResult,
wrapping the submitpackage RPC the same way TestMempoolAccept wraps
testmempoolaccept: serialize the topologically-sorted package to hex,
issue the btcjson submitpackage command, and decode the response into
btcjson.SubmitPackageResult (which already maps the raw fields to
higher-level types via its UnmarshalJSON).

This keeps the multi-backend RPC layering intact so callers (e.g.
btcwallet's chain.Interface) can invoke a typed method instead of a
RawRequest. submitpackage is a Bitcoin Core RPC (v24+); btcd has no
server handler for it.
2026-06-17 08:59:16 -07:00
Oli
a7e980dd34
netsync: require block-serving services on regtest/simnet sync peers
Commit 26124d275 made every peer a sync candidate on regtest and
simnet so that nodes on non-localhost networks (e.g. Docker bridge
networks) can be synced from. Dropping the address requirement was
the intent, but the change also dropped the service-flag requirement,
so light clients became eligible sync peers.

A light client (e.g. neutrino) advertises a recent best height but
can serve neither headers nor blocks. Electing one as the sync peer
stalls the sync until the stall handler disconnects it, and with
other light client connections present the next one is elected and
stalls again, livelocking the sync indefinitely. This surfaced in
neutrino's sync tests, where a btcd simnet node connected to both a
neutrino instance and other btcd nodes never synced.

Keep accepting any peer address on regtest/simnet, but require the
peer to signal SFNodeNetwork or SFNodeNetworkLimited like on any
other network.
2026-06-17 13:45:43 +02:00
Yong
1966c38453
Merge pull request #2536 from kcalvinalvin/2026-05-30-run-and-fix-broken-integration-tests-1
Some checks failed
Build and Test / Build (push) Has been cancelled
Build and Test / Unit coverage (push) Has been cancelled
Build and Test / Unit race (push) Has been cancelled
Build and Test / Unit rpctest (push) Has been cancelled
.github: actually run the integration tests in the CI
2026-06-04 15:18:53 +08:00
Calvin Kim
f8ce7a7da8 rpctest: scope shared state to the current process
Two pieces of rpctest's global state silently aliased across concurrent
test processes (which is what `go test ./...` does by default, so any
`make unit` that exercises -tags=rpctest hit this):

- btcdExecutablePath compiled to a fixed path /tmp/btcd/rpctest/btcd.
  Two `go build` invocations would race on the same file, occasionally
  yielding a truncated or stale binary and downstream "tls: certificate
  signed by unknown authority" failures when the harness tried to talk
  to the resulting node.

- lastPort started at the same defaultNodePort in every process. The
  bind-test in NextAvailablePort closes the listener before returning,
  so two processes climbing from the same base would frequently hand
  out the same port and one harness would die with "connection refused"
  when btcd failed to bind.

Suffix the executable with a random uint32 and seed lastPort with a
random offset into a 50k-port window so each process climbs through
its own range.
2026-05-30 17:49:55 +09:00
Calvin Kim
bfb36e52e7 netsync: process inv announcements when no syncPeer is set
handleInvMsg early-returned for any inv from a non-syncPeer whenever
sm.current() was false, with the comment that it prevents fetching a
mass of orphans. That guard assumes a syncPeer is already fetching
blocks; when syncPeer is nil, the assumption breaks down and the
early return becomes a deadlock.

The deadlock is reachable whenever two nodes connect at equal heights:
startSync exits without picking a syncPeer (no peer is "higher"), and
nothing later promotes the freshly-mined blocks the peer announces via
inv. The pre-verack disconnect and sync-race regression tests in
integration/sync_race_test.go fail consistently because of this.

Only skip the inv when we actually have a syncPeer. When syncPeer is
nil, fall through and let the normal request path queue the block --
the inv is the only signal that there are blocks to fetch.
2026-05-30 17:25:51 +09:00
Calvin Kim
79752a8880 btcjson: accept null in StringOrArray.UnmarshalJSON
StringOrArray.MarshalJSON emits JSON null for a nil slice (see existing
test "nil slice marshals as null" in TestStringOrArrayMarshalJSON), but
UnmarshalJSON did not have a matching case for null and fell to the
default branch, returning "invalid string_or_array value: <nil>". A
round trip of a nil slice therefore failed.

This bit the rpcclient against btcd's own getblockchaininfo, whose
Warnings field is a StringOrArray that the server leaves as a nil slice
when there are no warnings. Every rpctest integration test that touches
GetBlockChainInfo (TestBIP0009, TestBIP0068AndBIP0112Activation,
TestBIP0113Activation, TestPrune) failed to decode the response.

Handle the nil case explicitly so null decodes back to a nil slice, and
add regression cases for "warnings: null" and an omitted warnings field
to TestGetBlockChainInfoWarnings.
2026-05-30 16:47:18 +09:00
Calvin Kim
221178501c integration: fix p2a_test build under -tags=rpctest
p2a_test.go calls btcutil.NewAddressPayToAnchor, but the
NewAddressPayToAnchor constructor lives in the address/v2 module's
address package. Import that package and call it through there so the
integration package builds when -tags=rpctest is set.
2026-05-30 16:47:18 +09:00