Skip to content

Commit d6873da

Browse files
committed
Merge #323: Fix getaddressinfo
6cc26f0 Run the formatter (Jamil Lambert, PhD) b17157e Fix getaddressinfo (Jamil Lambert, PhD) Pull request description: The test was marked as TODO and the fields in the structs do not match what is returned by the RPC. In v20 the return field `labels` changes from a vector of json objects that was modelled as `GetAddressInfoLabel` to a `Vec<String>`. To allow for this make the modelled type a `Vec<String>`, this means for v17-v19 the `name` field is modelled and the `purpose` field of `GetAddressInfoLabel` is not. - Fix all of the fields in v17. - Redefine the types for changes in v18, v29, v22 and v28. - Update the model for to allow for the changes in return types. - Update the test using different `Address` types to check the inner structs contain expected values. ACKs for top commit: tcharding: ACK 6cc26f0 Tree-SHA512: 52f371b06097e5b832edc1a2c0558329081b11b71cb9319fa72b0b157312ceda33b918d5fb0fb657e19225e1c705e09c84376d1c580d656f41ad7f8f4b6d4dd9
2 parents c085b5e + 6cc26f0 commit d6873da

File tree

27 files changed

+1510
-276
lines changed

27 files changed

+1510
-276
lines changed

integration_test/tests/wallet.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![allow(unused_imports)] // Some imports are only used in specific versions.
77

88
use bitcoin::address::{Address, KnownHrp, NetworkChecked};
9-
use bitcoin::{secp256k1, Amount, CompressedPublicKey, FeeRate, PrivateKey, PublicKey};
9+
use bitcoin::{secp256k1, Amount, CompressedPublicKey, FeeRate, Network, PrivateKey, PublicKey};
1010
use integration_test::{Node, NodeExt as _, Wallet};
1111
use node::{mtype, AddressType, ImportMultiRequest, ImportMultiScriptPubKey, ImportMultiTimestamp};
1212

@@ -192,15 +192,34 @@ fn wallet__get_addresses_by_label__modelled() {
192192
}
193193

194194
#[test]
195-
#[cfg(feature = "TODO")] // FIXME: The types are broken.
196-
// TODO: Consider testing a few different address types.
197195
fn wallet__get_address_info__modelled() {
198196
let node = Node::with_wallet(Wallet::Default, &[]);
199-
let address = node.client.new_address().expect("failed to create new address");
200197

201-
let json: GetAddressInfo = node.client.get_address_info(&address).expect("getaddressinfo");
198+
// Test an address with a label.
199+
let label_name = "test-label";
200+
let addr = node.client.new_address_with_label(label_name).unwrap().assume_checked();
201+
let json: GetAddressInfo = node.client.get_address_info(&addr).expect("getaddressinfo legacy");
202202
let model: Result<mtype::GetAddressInfo, GetAddressInfoError> = json.into_model();
203-
model.unwrap();
203+
let model = model.unwrap();
204+
assert_eq!(model.address.assume_checked(), addr);
205+
assert_eq!(model.labels[0], label_name);
206+
207+
// Test a SegWit address with embedded information.
208+
let addr_p2sh = node.client.new_address_with_type(AddressType::P2shSegwit).unwrap();
209+
let json: GetAddressInfo = node.client.get_address_info(&addr_p2sh).expect("getaddressinfo p2sh-segwit");
210+
let model: Result<mtype::GetAddressInfo, GetAddressInfoError> = json.into_model();
211+
let model = model.unwrap();
212+
let embedded = model.embedded.unwrap();
213+
assert_eq!(model.address.assume_checked(), addr_p2sh);
214+
assert_eq!(model.script.unwrap(), mtype::ScriptType::WitnessV0KeyHash);
215+
assert!(embedded.address.is_valid_for_network(Network::Regtest));
216+
217+
// Test a Bech32 address.
218+
let addr_bech32 = node.client.new_address_with_type(AddressType::Bech32).unwrap();
219+
let json: GetAddressInfo = node.client.get_address_info(&addr_bech32).expect("getaddressinfo bech32");
220+
let model: Result<mtype::GetAddressInfo, GetAddressInfoError> = json.into_model();
221+
let model = model.unwrap();
222+
assert_eq!(model.address.assume_checked(), addr_bech32);
204223
}
205224

206225
#[test]

types/src/model/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ pub use self::{
5151
SignMessageWithPrivKey, ValidateAddress,
5252
},
5353
wallet::{
54-
AddMultisigAddress, AddressInformation, AddressLabel, AddressPurpose, Bip125Replaceable,
55-
BumpFee, CreateWallet, DumpPrivKey, GetAddressInfo, GetAddressInfoEmbedded,
56-
GetAddressesByLabel, GetBalance, GetBalances, GetBalancesMine, GetBalancesWatchOnly,
57-
GetNewAddress, GetRawChangeAddress, GetReceivedByAddress, GetReceivedByLabel,
58-
GetTransaction, GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo,
59-
LastProcessedBlock, ListAddressGroupings, ListAddressGroupingsItem, ListLabels,
60-
ListLockUnspent, ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem,
61-
ListReceivedByLabel, ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction,
62-
ListTransactions, ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets,
63-
LoadWallet, PsbtBumpFee, RescanBlockchain, ScriptType, Send, SendAll, SendMany,
64-
SendToAddress, SignMessage, SimulateRawTransaction, TransactionCategory, UnloadWallet,
65-
WalletCreateFundedPsbt, WalletDisplayAddress, WalletProcessPsbt,
54+
AddMultisigAddress, AddressInformation, AddressPurpose, Bip125Replaceable, BumpFee,
55+
CreateWallet, DumpPrivKey, GetAddressInfo, GetAddressInfoEmbedded, GetAddressesByLabel,
56+
GetBalance, GetBalances, GetBalancesMine, GetBalancesWatchOnly, GetNewAddress,
57+
GetRawChangeAddress, GetReceivedByAddress, GetReceivedByLabel, GetTransaction,
58+
GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo, LastProcessedBlock,
59+
ListAddressGroupings, ListAddressGroupingsItem, ListLabels, ListLockUnspent,
60+
ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem, ListReceivedByLabel,
61+
ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction, ListTransactions,
62+
ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets, LoadWallet, PsbtBumpFee,
63+
RescanBlockchain, ScriptType, Send, SendAll, SendMany, SendToAddress, SignMessage,
64+
SimulateRawTransaction, TransactionCategory, UnloadWallet, WalletCreateFundedPsbt,
65+
WalletDisplayAddress, WalletProcessPsbt,
6666
},
6767
};

types/src/model/wallet.rs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,16 @@ pub struct GetAddressInfo {
117117
pub is_mine: bool,
118118
/// If the address is watchonly.
119119
pub is_watch_only: bool,
120+
/// Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys.
121+
pub solvable: Option<bool>,
122+
/// A descriptor for spending coins sent to this address (only when solvable).
123+
pub descriptor: Option<String>,
124+
/// The descriptor used to derive this address if this is a descriptor wallet
125+
pub parent_descriptor: Option<String>,
120126
/// If the key is a script.
121-
pub is_script: bool,
127+
pub is_script: Option<bool>,
128+
/// If the address was used for change output.
129+
pub is_change: Option<bool>,
122130
/// If the address is a witness address.
123131
pub is_witness: bool,
124132
/// The version number of the witness program.
@@ -140,18 +148,20 @@ pub struct GetAddressInfo {
140148
pub pubkey: Option<PublicKey>,
141149
/// Information about the address embedded in P2SH or P2WSH, if relevant and known.
142150
pub embedded: Option<GetAddressInfoEmbedded>,
143-
/// If the address is compressed.
144-
pub is_compressed: bool,
151+
/// If the pubkey is compressed.
152+
pub is_compressed: Option<bool>,
145153
/// The label associated with the address, "" is the default account.
146-
pub label: String,
154+
pub label: Option<String>,
147155
/// The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT).
148156
pub timestamp: Option<u32>,
149157
/// The HD keypath if the key is HD and available.
150158
pub hd_key_path: Option<bip32::DerivationPath>,
151159
/// The Hash160 of the HD seed.
152160
pub hd_seed_id: Option<hash160::Hash>,
161+
/// The fingerprint of the master key.
162+
pub hd_master_fingerprint: Option<bip32::Fingerprint>,
153163
/// Labels associated with the address.
154-
pub labels: Vec<AddressLabel>,
164+
pub labels: Vec<String>,
155165
}
156166

157167
/// An address script type.
@@ -177,16 +187,6 @@ pub enum ScriptType {
177187
WitnessUnknown,
178188
}
179189

180-
/// An address label.
181-
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
182-
#[serde(deny_unknown_fields)]
183-
pub struct AddressLabel {
184-
/// The address label.
185-
pub name: String,
186-
/// Purpose of address (send or receive).
187-
pub purpose: AddressPurpose,
188-
}
189-
190190
/// The `embedded` field of `GetAddressInfo`.
191191
///
192192
/// It includes all getaddressinfo output fields for the embedded address, excluding metadata
@@ -200,8 +200,16 @@ pub struct GetAddressInfoEmbedded {
200200
pub address: Address<NetworkUnchecked>,
201201
/// The hex encoded scriptPubKey generated by the address.
202202
pub script_pubkey: ScriptBuf,
203+
/// Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys.
204+
pub solvable: Option<bool>,
205+
/// A descriptor for spending coins sent to this address (only when solvable).
206+
pub descriptor: Option<String>,
207+
/// The descriptor used to derive this address if this is a descriptor wallet
208+
pub parent_descriptor: Option<String>,
203209
/// If the key is a script.
204-
pub is_script: bool,
210+
pub is_script: Option<bool>,
211+
/// If the address was used for change output.
212+
pub is_change: Option<bool>,
205213
/// If the address is a witness address.
206214
pub is_witness: bool,
207215
/// The version number of the witness program.
@@ -215,17 +223,17 @@ pub struct GetAddressInfoEmbedded {
215223
/// The redeemscript for the p2sh address.
216224
pub hex: Option<ScriptBuf>,
217225
/// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig").
218-
pub pubkeys: Vec<PublicKey>,
226+
pub pubkeys: Option<Vec<PublicKey>>,
219227
/// Number of signatures required to spend multisig output (only if "script" is "multisig").
220228
pub sigs_required: Option<u32>,
221229
/// The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH).
222230
pub pubkey: Option<PublicKey>,
223231
/// If the address is compressed.
224-
pub is_compressed: bool,
232+
pub is_compressed: Option<bool>,
225233
/// The label associated with the address, "" is the default account.
226-
pub label: String,
234+
pub label: Option<String>,
227235
/// Labels associated with the address.
228-
pub labels: Vec<AddressLabel>,
236+
pub labels: Option<Vec<String>>,
229237
}
230238

231239
/// Models the result of JSON-RPC method `getbalance`.

types/src/v17/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
//! | getaccountaddress | returns nothing | |
164164
//! | getaddressbyaccount | returns nothing | |
165165
//! | getaddressesbylabel | version + model | |
166-
//! | getaddressinfo | version + model | UNTESTED |
166+
//! | getaddressinfo | version + model | |
167167
//! | getbalance | version + model | |
168168
//! | getnewaddress | version + model | |
169169
//! | getrawchangeaddress | version + model | |
@@ -283,9 +283,9 @@ pub use self::{
283283
ListReceivedByAddressError, ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError,
284284
ListSinceBlockTransaction, ListSinceBlockTransactionError, ListTransactions,
285285
ListTransactionsItem, ListTransactionsItemError, ListUnspent, ListUnspentItem,
286-
ListUnspentItemError, ListWallets, LoadWallet, LockUnspent, RescanBlockchain, SendMany,
287-
SendToAddress, SetTxFee, SignMessage, TransactionCategory, WalletCreateFundedPsbt,
288-
WalletCreateFundedPsbtError, WalletProcessPsbt,
286+
ListUnspentItemError, ListWallets, LoadWallet, LockUnspent, RescanBlockchain, ScriptType,
287+
SendMany, SendToAddress, SetTxFee, SignMessage, TransactionCategory,
288+
WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WalletProcessPsbt,
289289
},
290290
zmq::GetZmqNotifications,
291291
};

types/src/v17/wallet/into.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,18 @@ impl GetAddressInfo {
169169
.map_err(E::HdKeyPath)?;
170170
let hd_seed_id =
171171
self.hd_seed_id.map(|s| s.parse::<hash160::Hash>()).transpose().map_err(E::HdSeedId)?;
172-
let labels = self.labels.into_iter().map(|label| label.into_model()).collect();
172+
let labels = self.labels.into_iter().map(|label| label.name).collect();
173173

174174
Ok(model::GetAddressInfo {
175175
address,
176176
script_pubkey,
177177
is_mine: self.is_mine,
178178
is_watch_only: self.is_watch_only,
179-
is_script: self.is_script,
179+
solvable: None, // v18 and above only.
180+
descriptor: None, // v18 and above only.
181+
parent_descriptor: None, // v22 and above only.
182+
is_script: Some(self.is_script),
183+
is_change: None, // v18 and above only.
180184
is_witness: self.is_witness,
181185
witness_version,
182186
witness_program,
@@ -187,10 +191,11 @@ impl GetAddressInfo {
187191
pubkey,
188192
embedded,
189193
is_compressed: self.is_compressed,
190-
label: self.label,
194+
label: Some(self.label),
191195
timestamp: self.timestamp,
192196
hd_key_path,
193197
hd_seed_id,
198+
hd_master_fingerprint: None, // v18 and above only.
194199
labels,
195200
})
196201
}
@@ -243,21 +248,20 @@ impl GetAddressInfoEmbedded {
243248
let script = self.script.map(|s| s.into_model());
244249
let redeem_script =
245250
self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?;
246-
let pubkeys = self
247-
.pubkeys
248-
.iter()
249-
.map(|s| s.parse::<PublicKey>())
250-
.collect::<Result<Vec<_>, _>>()
251-
.map_err(E::Pubkeys)?;
251+
let pubkeys = None;
252252
let sigs_required =
253253
self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?;
254254
let pubkey = self.pubkey.map(|s| s.parse::<PublicKey>()).transpose().map_err(E::Pubkey)?;
255-
let labels = self.labels.into_iter().map(|label| label.into_model()).collect();
255+
let labels = self.labels.map(|labels| labels.into_iter().map(|label| label.name).collect());
256256

257257
Ok(model::GetAddressInfoEmbedded {
258258
address,
259259
script_pubkey,
260+
solvable: None, // v18 and above only.
261+
descriptor: None, // v18 and above only.
262+
parent_descriptor: None, // v22 and above only.
260263
is_script: self.is_script,
264+
is_change: None, // v18 and above only.
261265
is_witness: self.is_witness,
262266
witness_version,
263267
witness_program,
@@ -273,13 +277,6 @@ impl GetAddressInfoEmbedded {
273277
}
274278
}
275279

276-
impl GetAddressInfoLabel {
277-
/// Converts version specific type to a version nonspecific, more strongly typed type.
278-
pub fn into_model(self) -> model::AddressLabel {
279-
model::AddressLabel { name: self.name, purpose: self.purpose.into_model() }
280-
}
281-
}
282-
283280
impl GetBalance {
284281
/// Converts version specific type to a version nonspecific, more strongly typed type.
285282
pub fn into_model(self) -> Result<model::GetBalance, ParseAmountError> {

types/src/v17/wallet/mod.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,9 @@ pub struct GetAddressInfo {
273273
pub embedded: Option<GetAddressInfoEmbedded>,
274274
/// If the address is compressed.
275275
#[serde(rename = "iscompressed")]
276-
pub is_compressed: bool,
276+
pub is_compressed: Option<bool>,
277277
/// The label associated with the address, "" is the default account.
278278
pub label: String,
279-
/// DEPRECATED. The account associated with the address, "" is the default account.
280-
pub account: String,
281279
/// The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT).
282280
pub timestamp: Option<u32>,
283281
/// The HD keypath if the key is HD and available.
@@ -342,7 +340,7 @@ pub struct GetAddressInfoEmbedded {
342340
pub script_pubkey: String,
343341
/// If the key is a script.
344342
#[serde(rename = "isscript")]
345-
pub is_script: bool,
343+
pub is_script: Option<bool>,
346344
/// If the address is a witness address.
347345
#[serde(rename = "iswitness")]
348346
pub is_witness: bool,
@@ -356,20 +354,18 @@ pub struct GetAddressInfoEmbedded {
356354
pub script: Option<ScriptType>,
357355
/// The redeemscript for the p2sh address.
358356
pub hex: Option<String>,
359-
/// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig").
360-
pub pubkeys: Vec<String>,
361357
/// Number of signatures required to spend multisig output (only if "script" is "multisig").
362358
#[serde(rename = "sigsrequired")]
363359
pub sigs_required: Option<i64>,
364360
/// The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH).
365361
pub pubkey: Option<String>,
366362
/// If the address is compressed.
367363
#[serde(rename = "iscompressed")]
368-
pub is_compressed: bool,
364+
pub is_compressed: Option<bool>,
369365
/// The label associated with the address, "" is the default account.
370-
pub label: String,
366+
pub label: Option<String>,
371367
/// Array of labels associated with the address.
372-
pub labels: Vec<GetAddressInfoLabel>,
368+
pub labels: Option<Vec<GetAddressInfoLabel>>,
373369
}
374370

375371
/// The `label` field of `GetAddressInfo` (and `GetAddressInfoEmbedded`).

0 commit comments

Comments
 (0)