|
5 | 5 | #![allow(non_snake_case)] // Test names intentionally use double underscore. |
6 | 6 | #![allow(unused_imports)] // Because of feature gated tests. |
7 | 7 |
|
| 8 | +use bitcoin::bip32::DerivationPath; |
8 | 9 | use bitcoin::consensus::encode; |
9 | 10 | use bitcoin::hex::FromHex as _; |
10 | 11 | use bitcoin::opcodes::all::*; |
11 | 12 | use bitcoin::{ |
12 | 13 | absolute, consensus, hex, psbt, script, transaction, Amount, ScriptBuf, Transaction, TxOut, |
13 | 14 | }; |
14 | | -use integration_test::{Node, NodeExt as _, Wallet}; |
| 15 | +use integration_test::{test_keys, Node, NodeExt as _, Wallet}; |
15 | 16 | use node::vtype::*; |
16 | 17 | use node::{mtype, Input, Output}; // All the version specific types. |
17 | 18 |
|
@@ -127,57 +128,57 @@ fn raw_transactions__create_raw_transaction__modelled() { |
127 | 128 | create_sign_send(&node); |
128 | 129 | } |
129 | 130 |
|
130 | | -// Notes on testing decoding of PBST. |
131 | | -// |
132 | | -// - `bip32_derivs` field in the input list of the decoded PSBT changes shape a bunch of times. |
133 | | -// - In v23 a bunch of additional fields are added. |
134 | | -// - In v24 taproot fields are added. |
135 | | -// |
136 | | -// All this should still be handled by `into_model` because `bitcoin::Psbt` has all optional fields. |
| 131 | +// Tests PSBT decoding across Bitcoin Core versions. |
| 132 | +// Version-specific assertions are gated below. |
137 | 133 | #[test] |
138 | 134 | fn raw_transactions__decode_psbt__modelled() { |
139 | 135 | let node = Node::with_wallet(Wallet::Default, &["-txindex"]); |
140 | 136 | node.fund_wallet(); |
141 | 137 |
|
| 138 | + // v17: utxoupdatepsbt unavailable |
| 139 | + #[cfg(feature = "v17")] |
142 | 140 | let mut psbt = create_a_psbt(&node); |
143 | 141 |
|
144 | | - // A bunch of new fields got added in v23. |
145 | | - // |
146 | | - // Add an arbitrary global xpub to see if it decodes. Before v23 this will end up in `unknown`, |
147 | | - // from v23 onwards in should be in its own field. |
148 | | - { |
149 | | - use std::collections::BTreeMap; |
150 | | - |
151 | | - use bitcoin::bip32::{DerivationPath, Fingerprint, Xpub}; |
| 142 | + // v18+: utxoupdatepsbt available |
| 143 | + #[cfg(not(feature = "v17"))] |
| 144 | + let mut psbt = { |
| 145 | + let psbt = create_a_psbt(&node); |
| 146 | + let updated: UtxoUpdatePsbt = node.client.utxo_update_psbt(&psbt).expect("utxoupdatepsbt"); |
| 147 | + updated.into_model().expect("UtxoUpdatePsbt into model").0 |
| 148 | + }; |
152 | 149 |
|
153 | | - let mut map = BTreeMap::default(); |
154 | | - // Some arbitrary xpub I grabbed from rust-bitcoin. |
155 | | - let xpub = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"; |
156 | | - let xpub = xpub.parse::<Xpub>().expect("failed to parse xpub"); |
157 | | - let fp = Fingerprint::from([1u8, 2, 3, 42]); |
158 | | - let path = |
159 | | - "m/84'/0'/0'/0/1".parse::<DerivationPath>().expect("failed to parse derivation path"); |
160 | | - map.insert(xpub, (fp, path)); |
| 150 | + let keys = test_keys(); |
| 151 | + let path: DerivationPath = "m/84'/0'/0'/0/1".parse().expect("valid derivation path"); |
| 152 | + psbt.xpub.insert(keys.xpub, (keys.fingerprint, path)); |
161 | 153 |
|
162 | | - psbt.xpub = map; |
| 154 | + // v24+: Taproot fields |
| 155 | + #[cfg(not(feature = "v23_and_below"))] |
| 156 | + { |
| 157 | + psbt.inputs[0].tap_internal_key = Some(keys.x_only_public_key); |
163 | 158 | } |
164 | 159 |
|
165 | 160 | let encoded = psbt.to_string(); |
166 | | - |
167 | 161 | let json: DecodePsbt = node.client.decode_psbt(&encoded).expect("decodepsbt"); |
168 | 162 | let model: Result<mtype::DecodePsbt, DecodePsbtError> = json.into_model(); |
169 | | - |
170 | | - #[allow(unused_variables)] |
171 | 163 | let decoded = model.unwrap(); |
172 | 164 |
|
173 | | - // Before Core v23 global xpubs was not a known keypair. |
| 165 | + // v18/v19: utxoupdatepsbt can't populate UTXO data, so fee is None |
| 166 | + #[cfg(feature = "v19_and_below")] |
| 167 | + assert!(decoded.fee.is_none()); |
| 168 | + |
| 169 | + // v20+: utxoupdatepsbt allows fee to be calculated |
| 170 | + #[cfg(not(feature = "v19_and_below"))] |
| 171 | + assert!(decoded.fee.expect("fee should be present").to_sat() > 0); |
| 172 | + |
| 173 | + // v23+: dedicated xpub field; earlier versions store in `unknown`. |
174 | 174 | #[cfg(feature = "v22_and_below")] |
175 | 175 | assert_eq!(decoded.psbt.unknown.len(), 1); |
176 | 176 |
|
177 | 177 | #[cfg(not(feature = "v22_and_below"))] |
178 | 178 | assert_eq!(decoded.psbt.xpub.len(), 1); |
179 | 179 |
|
180 | | - // TODO: Add a taproot field and test it with v24 |
| 180 | + #[cfg(not(feature = "v23_and_below"))] |
| 181 | + assert_eq!(decoded.psbt.inputs[0].tap_internal_key, Some(keys.x_only_public_key)); |
181 | 182 | } |
182 | 183 |
|
183 | 184 | #[test] |
|
0 commit comments