diff --git a/client/src/client_sync/v26/hidden.rs b/client/src/client_sync/v26/hidden.rs new file mode 100644 index 00000000..5fc27833 --- /dev/null +++ b/client/src/client_sync/v26/hidden.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Macros for implementing JSON-RPC methods on a client. +//! +//! Specifically this is `== Hidden ==` methods that are not listed in the +//! API docs of Bitcoin Core `v26`. +//! +//! All macros require `Client` to be in scope. +//! +//! See or use the `define_jsonrpc_bitreq_client!` macro to define a `Client`. + +/// Implements Bitcoin Core JSON-RPC API method `getrawaddrman`. +#[macro_export] +macro_rules! impl_client_v26__get_raw_addrman { + () => { + impl Client { + pub fn get_raw_addrman(&self) -> Result { + self.call("getrawaddrman", &[]) + } + } + }; +} diff --git a/client/src/client_sync/v26/mod.rs b/client/src/client_sync/v26/mod.rs index dd004165..c74cb563 100644 --- a/client/src/client_sync/v26/mod.rs +++ b/client/src/client_sync/v26/mod.rs @@ -5,6 +5,7 @@ //! We ignore option arguments unless they effect the shape of the returned JSON data. pub mod blockchain; +pub mod hidden; pub mod mining; pub mod network; pub mod raw_transactions; @@ -82,6 +83,7 @@ crate::impl_client_v17__invalidate_block!(); // == Hidden == crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__estimate_raw_fee!(); +crate::impl_client_v26__get_raw_addrman!(); crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); diff --git a/client/src/client_sync/v27/mod.rs b/client/src/client_sync/v27/mod.rs index 54c15700..861f8b57 100644 --- a/client/src/client_sync/v27/mod.rs +++ b/client/src/client_sync/v27/mod.rs @@ -76,6 +76,7 @@ crate::impl_client_v17__invalidate_block!(); // == Hidden == crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__estimate_raw_fee!(); +crate::impl_client_v26__get_raw_addrman!(); crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); diff --git a/client/src/client_sync/v28/mod.rs b/client/src/client_sync/v28/mod.rs index cb296ba3..bddf3676 100644 --- a/client/src/client_sync/v28/mod.rs +++ b/client/src/client_sync/v28/mod.rs @@ -79,6 +79,7 @@ crate::impl_client_v17__invalidate_block!(); // == Hidden == crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__estimate_raw_fee!(); +crate::impl_client_v26__get_raw_addrman!(); crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); diff --git a/client/src/client_sync/v29/mod.rs b/client/src/client_sync/v29/mod.rs index 1b52b58c..818b90e4 100644 --- a/client/src/client_sync/v29/mod.rs +++ b/client/src/client_sync/v29/mod.rs @@ -79,6 +79,7 @@ crate::impl_client_v17__invalidate_block!(); // == Hidden == crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__estimate_raw_fee!(); +crate::impl_client_v26__get_raw_addrman!(); crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); diff --git a/client/src/client_sync/v30/mod.rs b/client/src/client_sync/v30/mod.rs index 59c8352d..420e96e7 100644 --- a/client/src/client_sync/v30/mod.rs +++ b/client/src/client_sync/v30/mod.rs @@ -79,6 +79,7 @@ crate::impl_client_v17__invalidate_block!(); // == Hidden == crate::impl_client_v21__add_peer_address!(); +crate::impl_client_v26__get_raw_addrman!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index bf14931e..e07ac688 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -28,3 +28,27 @@ fn hidden__estimate_raw_fee__modelled() { assert!(estimate.long.scale > 0); } + +#[test] +#[cfg(not(feature = "v25_and_below"))] +fn hidden__get_raw_addrman() { + let node = Node::with_wallet(Wallet::None, &[]); + + // Add a peer address so the address manager has something. + let peer_address = "1.2.3.4"; + let peer_port = 8333; + node.client.add_peer_address(peer_address, peer_port).expect("addpeeraddress"); + + let json: GetRawAddrman = node.client.get_raw_addrman().expect("getrawaddrman"); + + let entry = json + .new + .values() + .find(|e| e.address == peer_address && e.port == peer_port) + .expect("added peer should appear in the 'new' table"); + + assert_eq!(entry.network, "ipv4"); + + // mapped_as field added in v28, only present with -asmap config. + assert!(entry.mapped_as.is_none(), "mapped_as requires -asmap config"); +} diff --git a/types/src/v26/hidden.rs b/types/src/v26/hidden.rs new file mode 100644 index 00000000..810645f6 --- /dev/null +++ b/types/src/v26/hidden.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The JSON-RPC API for Bitcoin Core `v26` - hidden. +//! +//! Types for methods that are excluded from the API docs by default. + +use alloc::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; + +/// Result of JSON-RPC method `getrawaddrman`. +/// +/// > getrawaddrman +/// > +/// > EXPERIMENTAL warning: this call may be changed in future releases. +/// > +/// > Returns information on all address manager entries for the new and tried tables. +/// +/// This is a hidden RPC, useful for testing and development. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] +pub struct GetRawAddrman { + /// Addresses in the "new" table (potential peers discovered but not yet connected to). + pub new: BTreeMap, + /// Addresses in the "tried" table (peers successfully connected to in the past). + pub tried: BTreeMap, +} + +/// An entry in the address manager table. Part of `getrawaddrman`. +/// +/// The key in the parent map is formatted as "bucket/position" indicating the +/// location in the relevant address manager table. +/// +/// Field order matches Bitcoin Core's RPC response definition. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] +pub struct RawAddrmanEntry { + /// The address of the node. + pub address: String, + /// Mapped AS (Autonomous System) number at the end of the BGP route to the peer. + /// Only present if the -asmap config option is set. + /// Added in Bitcoin Core v28. + pub mapped_as: Option, + /// The port number of the node. + pub port: u16, + /// The network (ipv4, ipv6, onion, i2p, cjdns) of the address. + pub network: String, + /// The services offered by the node. + pub services: u64, + /// The UNIX epoch time when the node was last seen. + pub time: i64, + /// The address that relayed the address to us. + pub source: String, + /// The network (ipv4, ipv6, onion, i2p, cjdns) of the source address. + pub source_network: String, + /// Mapped AS (Autonomous System) number at the end of the BGP route to the source. + /// Only present if the -asmap config option is set. + /// Added in Bitcoin Core v28. + pub source_mapped_as: Option, +} diff --git a/types/src/v26/mod.rs b/types/src/v26/mod.rs index 4a2ab341..78e46de5 100644 --- a/types/src/v26/mod.rs +++ b/types/src/v26/mod.rs @@ -250,6 +250,7 @@ mod blockchain; mod control; +mod hidden; mod mining; mod network; mod raw_transactions; @@ -262,6 +263,7 @@ pub use self::{ GetTxOutSetInfo, GetTxOutSetInfoError, LoadTxOutSet, LoadTxOutSetError, }, control::Logging, + hidden::{GetRawAddrman, RawAddrmanEntry}, mining::{GetPrioritisedTransactions, PrioritisedTransaction}, network::{AddrManInfoNetwork, GetAddrManInfo, GetPeerInfo, PeerInfo}, raw_transactions::{ diff --git a/types/src/v27/mod.rs b/types/src/v27/mod.rs index 6f032eaa..8ad6d986 100644 --- a/types/src/v27/mod.rs +++ b/types/src/v27/mod.rs @@ -334,11 +334,11 @@ pub use crate::{ v26::{ AddrManInfoNetwork, ChainState, CreateWallet, DescriptorProcessPsbt, DescriptorProcessPsbtError, DumpTxOutSet, DumpTxOutSetError, GetAddrManInfo, GetBalances, - GetBalancesError, GetChainStates, GetChainStatesError, GetPeerInfo, GetTransaction, - GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, GetWalletInfo, + GetBalancesError, GetChainStates, GetChainStatesError, GetPeerInfo, GetRawAddrman, + GetTransaction, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, GetWalletInfo, GetWalletInfoError, GetWalletInfoScanning, LastProcessedBlock, LastProcessedBlockError, - LoadTxOutSet, LoadTxOutSetError, LoadWallet, Logging, PeerInfo, SubmitPackage, - SubmitPackageError, SubmitPackageTxResult, SubmitPackageTxResultError, + LoadTxOutSet, LoadTxOutSetError, LoadWallet, Logging, PeerInfo, RawAddrmanEntry, + SubmitPackage, SubmitPackageError, SubmitPackageTxResult, SubmitPackageTxResultError, SubmitPackageTxResultFees, SubmitPackageTxResultFeesError, UnloadWallet, WalletProcessPsbt, WalletProcessPsbtError, }, diff --git a/types/src/v28/mod.rs b/types/src/v28/mod.rs index 22a6e0e3..7182cdb7 100644 --- a/types/src/v28/mod.rs +++ b/types/src/v28/mod.rs @@ -353,11 +353,11 @@ pub use crate::{ v26::{ AddrManInfoNetwork, ChainState, CreateWallet, DescriptorProcessPsbt, DescriptorProcessPsbtError, DumpTxOutSet, DumpTxOutSetError, GetAddrManInfo, GetBalances, - GetBalancesError, GetChainStates, GetChainStatesError, GetPeerInfo, GetTransactionError, - GetTxOutSetInfo, GetTxOutSetInfoError, GetWalletInfo, GetWalletInfoError, - GetWalletInfoScanning, LastProcessedBlock, LastProcessedBlockError, LoadTxOutSet, - LoadTxOutSetError, LoadWallet, PeerInfo, UnloadWallet, WalletProcessPsbt, - WalletProcessPsbtError, + GetBalancesError, GetChainStates, GetChainStatesError, GetPeerInfo, GetRawAddrman, + GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, GetWalletInfo, + GetWalletInfoError, GetWalletInfoScanning, LastProcessedBlock, LastProcessedBlockError, + LoadTxOutSet, LoadTxOutSetError, LoadWallet, PeerInfo, RawAddrmanEntry, UnloadWallet, + WalletProcessPsbt, WalletProcessPsbtError, }, v27::{GetPrioritisedTransactions, PrioritisedTransaction}, }; diff --git a/types/src/v29/mod.rs b/types/src/v29/mod.rs index f2661c44..0f9b1b02 100644 --- a/types/src/v29/mod.rs +++ b/types/src/v29/mod.rs @@ -346,10 +346,10 @@ pub use crate::{ v26::{ AddrManInfoNetwork, CreateWallet, DescriptorProcessPsbt, DescriptorProcessPsbtError, DumpTxOutSet, DumpTxOutSetError, GetAddrManInfo, GetBalances, GetBalancesError, - GetPeerInfo, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, GetWalletInfo, - GetWalletInfoError, GetWalletInfoScanning, LastProcessedBlock, LastProcessedBlockError, - LoadTxOutSet, LoadTxOutSetError, LoadWallet, PeerInfo, UnloadWallet, WalletProcessPsbt, - WalletProcessPsbtError, + GetPeerInfo, GetRawAddrman, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, + GetWalletInfo, GetWalletInfoError, GetWalletInfoScanning, LastProcessedBlock, + LastProcessedBlockError, LoadTxOutSet, LoadTxOutSetError, LoadWallet, PeerInfo, + RawAddrmanEntry, UnloadWallet, WalletProcessPsbt, WalletProcessPsbtError, }, v27::{GetPrioritisedTransactions, PrioritisedTransaction}, v28::{ diff --git a/types/src/v30/mod.rs b/types/src/v30/mod.rs index 5f665580..37b3b2e9 100644 --- a/types/src/v30/mod.rs +++ b/types/src/v30/mod.rs @@ -335,9 +335,9 @@ pub use crate::{ v26::{ AddrManInfoNetwork, CreateWallet, DescriptorProcessPsbt, DescriptorProcessPsbtError, DumpTxOutSet, DumpTxOutSetError, GetAddrManInfo, GetBalances, GetBalancesError, - GetPeerInfo, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, LoadTxOutSet, - LoadTxOutSetError, LoadWallet, PeerInfo, UnloadWallet, WalletProcessPsbt, - WalletProcessPsbtError, + GetPeerInfo, GetRawAddrman, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoError, + LoadTxOutSet, LoadTxOutSetError, LoadWallet, PeerInfo, RawAddrmanEntry, UnloadWallet, + WalletProcessPsbt, WalletProcessPsbtError, }, v27::{GetPrioritisedTransactions, PrioritisedTransaction}, v28::{