Repository navigation
rpc, init: -v2pqtransport, startup line, getpqtransportinfo, peer fields, -netinfo and GUI (#184 part 6) #209
Description
Part 6 of 9 · #184 · Size L · Base 1.x.x · Needs part 2 (#186), part 4 (#199), part 5 (#206) · Unblocks part 7 (#212), part 8 (#215)
Consolidates work items F5 (#209) and F6 (#210), each formerly its own sub-issue. Their full text is below as sections; the closed issues point here.
Goal
Operator controls and visibility: -v2pqtransport (default off until part 9), the test options and the startup line; getpqtransportinfo, the getpeerinfo and getnetworkinfo fields, 2p in -netinfo, and the GUI string.
Work items
In suggested commit order. Each item is a section below.
- F5 · init: add -v2pqtransport, the test options and the startup line
- F6 · rpc: add getpqtransportinfo and hybrid transport fields; -netinfo and GUI
Starting early
- F5 can start once part 4 merges, alongside part 5.
- F6 needs part 5's statistics.
F5 · init: add -v2pqtransport, the test options and the startup line
Needs E3 (#199).
Goal
Make the feature configurable, default off until R1 (#222), through one immutable effective configuration, with a startup line that shows the state and test hooks for the functional tests.
Context
- The
-v2transportpath to follow: registered atsrc/init.cpp:567and read at:971, thenCConnman::Options,CNodeOptions(src/net.h:673),MakeTransport(src/net.cpp:3802-3808) and theV2Transportconstructors. Alsosrc/net.h:667,1065andsrc/init.cpp:2097. - Every qbit boolean option parses
trueas 0 (src/common/args.cpp:78-83); negation is normalized at:129-140. -testoptions are listed inTEST_OPTIONS_DOC(src/common/args.cpp:743) and are regtest only (src/init.cpp:1095-1098).
Scope
DEFAULT_V2_PQ_TRANSPORT = false. R1 (release: hybrid v2 transport release gate and default-on (#184 part 9) #222) changes it.- One immutable configuration, computed from the same effective
ArgsManagervalues used for startup warnings and RPC:Inbound transports getstruct PQTransportConfig { bool v2_enabled{false}; bool pq_requested{false}; bool fail_first_packet{false}; bool Enabled() const noexcept { return v2_enabled && pq_requested; } }; // CConnman::Options: PQTransportConfig m_pq; CNodeOptions: V2PQOptions pq; std::optional<PQEndpointKey> pq_endpoint; static std::unique_ptr<Transport> MakeTransport(NodeId id, const CNodeOptions& options, bool inbound) noexcept;
NEGOTIATEonly when the configuration is enabled; outbound transports also check F3's fallback set. -v2pqtransport. It has no effect when-v2transport=0, and-helplists it.- An explicit
-v2pqtransport=1with-v2transport=0raises anInitWarningon the console and in the GUI:-v2pqtransport=1 has no effect because -v2transport=0. Set -v2transport=1 to use hybrid post-quantum v2 transport.An explicit 0, or the default, never warns. - A non-numeric value raises an
InitWarningthat names the effective setting, sov2pqtransport=true, which parses as 0, can't silently switch the feature off. Inspect the effectiveSettingsValue: an empty value means true, negated booleans are valid, and explicit strings must parse completely as integers, sotrue,1abcand overflow warn. Don't changeInterpretBoolglobally.
- An explicit
-mlkemportable, hidden, debug category, all chains: forces portable C by callingmlkem::InitializeRuntime(true)before any networking object exists. It is the field escape hatch if native code misbehaves on some CPU family.- Test options, in
TEST_OPTIONS_DOCin its snake_case style, regtest only:-test=pq_fail_first_packetsetscorrupt_shared_secreton every hybrid handshake while set;-test=mlkem_portableforces portable C.
- Startup line, always logged, naming the active backends:
v2 pq: enabled arith=<…> keccak=<…>v2 pq: disabled (-v2pqtransport=0) arith=<…> keccak=<…>v2 pq: disabled (-v2transport=0) arith=<…> keccak=<…>when v2 is off, whatever the PQ switch says.
Tests
New test/functional/rpc_pqtransport.py (F6 adds the RPC cases to the same file):
test_configuration:- the command line,
qbit.conf,-no…and restart toggles, observed through a live connection between two nodes (v2 pq: switchedin the debug log); - an explicit contradictory pair gives the exact warning, and an explicit 0, or
-v2transport=0alone, gives none; - a non-numeric value gives its warning;
-helplists the option;assert_debug_logchecks each of the three startup lines.
- the command line,
test_portable_options:-mlkemportableand-test=mlkem_portableeach make the startup line reportportablefor both backends; a non-regtest chain rejects the test options; nodes started with each test option print nothing to stderr.
Acceptance criteria
- The tests pass, the default stays off, and the existing functional suite is unchanged.
Suggested commit: init: add -v2pqtransport and hybrid transport test options.
F6 · rpc: add getpqtransportinfo and hybrid transport fields; -netinfo and GUI
Needs F2 (#206), F3 (#206), F4 (#206), F5, B3 (#186).
Goal
Everything an operator or monitoring script needs to see the feature, using the exact RPC contract in #184.
Scope
getpqtransportinfo, a new RPC that matches the schema in p2p: add hybrid post-quantum key exchange (ML-KEM-1024) to BIP324 v2 transport #184 field for field. Every field is always present, empty collections are[],statusvalues are tokens,instance_idis 64 lowercase hex characters, and ring entries are oldest first. It includesload_shedding(F4), the inboundshedcount,fallback_setandfailure_streaks(F3). Write the help text.getpeerinfogainstransport_pq(bool) andtransport_pq_status(pending,hybrid,legacy_peer,fallback,offorv1).transport_protocol_typekeeps its values (detectinguntil confirmation, thenv2), because-netinfo, the GUI and the functional tests compare against"v2".session_idis the hybrid session id whentransport_pqis true.
getnetworkinfogainsconnections_pqnext toconnections_inandconnections_out(src/rpc/net.cpp:792-794). It countstransport_pq=trueover exactly the peersgetpeerinfoshows:- factor
getpeerinfo's visibility filter (src/rpc/net.cpp:208-223) into a shared helper; - don't use
ForEachNode(src/net.cpp:3642), which only sees fully connected nodes.
- factor
- Fuzz.
src/test/fuzz/rpc.cpp: addgetpqtransportinfoto the safe list (:390-398) in the same commit as the RPC, because the fuzz initializer aborts on unclassified commands. - Docs.
doc/rpc/annotations/v30.2-delta.yml. -netinfo(src/bitcoin-cli.cpp:589-596, a 2-character%2scolumn) shows2pfor hybrid peers, and its help legend explains2p. A server that doesn't returntransport_pq, such as v1.0.0, counts as not hybrid, the way-netinfotreats other missing fields (:557).- GUI. The peer-details transport reads
v2 (hybrid post-quantum)(src/qt/rpcconsole.cpp:492-496).
Tests
Extend test/functional/rpc_pqtransport.py (from F5). Two nodes with -test=pq_fail_first_packet on one side produce failures in both directions, and legacy Python v2 peers that disconnect early produce abandoned.
| Test | Setup | Expect |
|---|---|---|
test_counts |
One isolated scenario per restart, or snapshot deltas | Exact per-direction counts, including switched plus a failure on one connection |
test_rings |
Keep one outbound failure; create 300 inbound failures | Outbound entry kept; inbound holds 256; dropped +44; sequences contiguous per ring |
test_abandoned |
Offer received; no authenticated version; close or time out | One abandoned; no switched |
test_connection_count |
One hybrid and one legacy peer; then the switch off | connections_pq == 1 == count(transport_pq) with a stable peer set; 0 when off |
test_states |
Switch off, switch on, fallback | Every getpqtransportinfo field; instance_id changes on restart |
Also:
rpc_net.py(:148): the exactgetpeerinfodict gains both fields. An ordinary Python peer stays legacy even in whole-suite PQ mode (G3).interface_bitcoin_cli.py: with one hybrid and one legacy peer,-netinfoshows2pand2, and the legend explains2p.p2p_v2_previous_release.py(B3): this release'sqbit-cli -netinfoagainst a v1.0.0 node shows2without errors.
Acceptance criteria
- The tests pass, and the
rpcfuzz target runs. - The help text and the annotations are updated.
Suggested commit: rpc: expose hybrid transport state and diagnostics.
One pull request against 1.x.x closes this issue. The shared contract is the Design section of #184; change it there first if needed.
Activity
[-]init: add -v2pqtransport, the test options and the startup line (#184 F5)[/-][+]rpc, init: -v2pqtransport, startup line, getpqtransportinfo, peer fields, -netinfo and GUI (#184 part 6)[/+]djh58 commentedon Oct 23, 2026
Done in #236, merged into
feature/pq-transportas 9e2e884. It reaches1.1.0with #233 and ships in 1.1.0.