Skip to content
Merged
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
3 changes: 2 additions & 1 deletion client/src/client_sync/v29/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! We ignore option arguments unless they effect the shape of the returned JSON data.

pub mod blockchain;
pub mod util;

use std::collections::BTreeMap;
use std::path::Path;
Expand Down Expand Up @@ -126,7 +127,7 @@ crate::impl_client_v22__enumerate_signers!();

// == Util ==
crate::impl_client_v17__create_multisig!();
crate::impl_client_v18__derive_addresses!();
crate::impl_client_v29__derive_addresses!();
crate::impl_client_v17__estimate_smart_fee!();
crate::impl_client_v18__get_descriptor_info!();
crate::impl_client_v21__get_index_info!();
Expand Down
33 changes: 33 additions & 0 deletions client/src/client_sync/v29/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: CC0-1.0

//! Macros for implementing JSON-RPC methods on a client.
//!
//! Specifically this is methods found under the `== Util ==` section of the
//! API docs of Bitcoin Core `v29`.
//!
//! All macros require `Client` to be in scope.
//!
//! See or use the `define_jsonrpc_minreq_client!` macro to define a `Client`.

/// Implements Bitcoin Core JSON-RPC API method `deriveaddresses`.
#[macro_export]
macro_rules! impl_client_v29__derive_addresses {
() => {
impl Client {
// For single derivation descriptors.
pub fn derive_addresses(&self, descriptor: &str) -> Result<DeriveAddresses> {
self.call("deriveaddresses", &[descriptor.into()])
}

// For multipath descriptors.
pub fn derive_addresses_multipath(
&self,
descriptor: &str,
range: (u32, u32),
) -> Result<DeriveAddressesMultipath> {
let range = json!([range.0, range.1]);
self.call("deriveaddresses", &[descriptor.into(), range.into()])
}
}
};
}
18 changes: 18 additions & 0 deletions integration_test/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ fn util__derive_addresses__modelled() {
let json: DeriveAddresses = node.client.derive_addresses(descriptor).expect("deriveaddresses");
let res: Result<mtype::DeriveAddresses, _> = json.into_model();
let _ = res.expect("DeriveAddresses into model");

// For v29 and above test a multipath descriptor.
#[cfg(not(feature = "v28_and_below"))]
{
// Create a multipath descriptor taken from running `listdescriptors` on the node. With 2 derivation paths.
let multipath_descriptor = "wpkh([26b4ed16/84h/1h/0h]tpubDDe7JUw2CGU1rYZxupmNrhDXuE1fv25gs4je3BBuWCFwTW9QHGgyh5cjAEugd14ysJXTVshPvnUVABfD66HZKCS9gp5AYFd5K2WN2oVFp8t/<0;1>/*)#grvmsm8m";

let range = (0, 3);
let json: DeriveAddressesMultipath = node.client.derive_addresses_multipath(multipath_descriptor, range)
.expect("deriveaddresses");
let res: Result<mtype::DeriveAddressesMultipath, _> = json.into_model();
let derived = res.expect("DeriveAddressesMultipath into model");

// Should return 2 `DeriveAddresses`, one for each derivation path (0 and 1).
assert_eq!(derived.addresses.len(), 2);
// Each `DeriveAddresses` should contain 4 addresses for range [0, 3].
assert_eq!(derived.addresses[0].addresses.len(), 4);
}
}

#[test]
Expand Down
3 changes: 2 additions & 1 deletion types/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ pub use self::{
TestMempoolAccept, UtxoUpdatePsbt,
},
util::{
CreateMultisig, DeriveAddresses, EstimateSmartFee, SignMessageWithPrivKey, ValidateAddress,
CreateMultisig, DeriveAddresses, DeriveAddressesMultipath, EstimateSmartFee,
SignMessageWithPrivKey, ValidateAddress,
},
wallet::{
AddMultisigAddress, AddressInformation, AddressLabel, AddressPurpose, Bip125Replaceable,
Expand Down
8 changes: 8 additions & 0 deletions types/src/model/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ pub struct DeriveAddresses {
pub addresses: Vec<Address<NetworkUnchecked>>,
}

/// Models the result of JSON-RPC method `deriveaddresses` for multipath descriptors.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct DeriveAddressesMultipath {
/// The derived addresses for each of the multipath expansions of the descriptor, in multipath specifier order.
pub addresses: Vec<DeriveAddresses>,
}

/// Models the result of JSON-RPC method `signmessagewithprivkey`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SignMessageWithPrivKey(pub sign_message::MessageSignature);
Expand Down
4 changes: 2 additions & 2 deletions types/src/v29/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
//! | JSON-RPC Method Name | Returns | Notes |
//! |:-----------------------------------|:---------------:|:--------------------------------------:|
//! | createmultisig | version + model | |
//! | deriveaddresses | version + model | TODO |
//! | deriveaddresses | version + model | |
//! | estimatesmartfee | version + model | |
//! | getdescriptorinfo | version | |
//! | getindexinfo | version | |
Expand Down Expand Up @@ -267,7 +267,7 @@ pub use self::{
BlockTemplateTransaction, GetMiningInfo, GetMiningInfoError, NextBlockInfo,
NextBlockInfoError,
},
util::GetDescriptorInfo,
util::{DeriveAddressesMultipath, GetDescriptorInfo},
};
#[doc(inline)]
pub use crate::{
Expand Down
26 changes: 26 additions & 0 deletions types/src/v29/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,34 @@
//!
//! Types for methods found under the `== Util ==` section of the API docs.

use bitcoin::address;
use serde::{Deserialize, Serialize};

use super::DeriveAddresses;
use crate::model;

/// Result of JSON-RPC method `deriveaddresses` for multipath descriptors.
///
/// > deriveaddresses "descriptor" ( range )
/// >
/// > Derives one or more addresses corresponding to an output descriptor.
/// > Returns an array of derived addresses.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct DeriveAddressesMultipath(pub Vec<DeriveAddresses>);

impl DeriveAddressesMultipath {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::DeriveAddressesMultipath, address::ParseError> {
let derive_addresses = self
.0
.into_iter()
.map(|derive_addresses| derive_addresses.into_model())
.collect::<Result<Vec<_>, _>>()?;
Ok(model::DeriveAddressesMultipath { addresses: derive_addresses })
}
}

/// Result of JSON-RPC method `getdescriptorinfo`.
///
/// > getdescriptorinfo "descriptor"
Expand Down