• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitcoindevkit / bdk / 3769013972

pending completion
3769013972

push

github

Steve Myers
Merge bitcoindevkit/bdk#805: electrum: add validate_domain to ElectrumBlockchainConfig

2 of 2 new or added lines in 1 file covered. (100.0%)

14366 of 17813 relevant lines covered (80.65%)

9434.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.27
/src/testutils/mod.rs
1
// Bitcoin Dev Kit
2
// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3
//
4
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5
//
6
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9
// You may not use this file except in accordance with one or both of these
10
// licenses.
11
#![allow(missing_docs)]
12

13
#[cfg(test)]
14
#[cfg(feature = "test-blockchains")]
15
pub mod blockchain_tests;
16

17
#[cfg(test)]
18
#[cfg(feature = "test-blockchains")]
19
pub mod configurable_blockchain_tests;
20

21
use bitcoin::{Address, Txid};
22

23
#[derive(Clone, Debug)]
×
24
pub struct TestIncomingInput {
25
    pub txid: Txid,
26
    pub vout: u32,
27
    pub sequence: Option<u32>,
28
}
29

30
impl TestIncomingInput {
31
    pub fn new(txid: Txid, vout: u32, sequence: Option<u32>) -> Self {
×
32
        Self {
×
33
            txid,
×
34
            vout,
×
35
            sequence,
×
36
        }
×
37
    }
×
38

39
    #[cfg(feature = "test-blockchains")]
40
    pub fn into_raw_tx_input(self) -> bitcoincore_rpc::json::CreateRawTransactionInput {
4✔
41
        bitcoincore_rpc::json::CreateRawTransactionInput {
4✔
42
            txid: self.txid,
4✔
43
            vout: self.vout,
4✔
44
            sequence: self.sequence,
4✔
45
        }
4✔
46
    }
4✔
47
}
48

49
#[derive(Clone, Debug)]
4✔
50
pub struct TestIncomingOutput {
51
    pub value: u64,
52
    pub to_address: String,
53
}
54

55
impl TestIncomingOutput {
56
    pub fn new(value: u64, to_address: Address) -> Self {
1,325✔
57
        Self {
1,325✔
58
            value,
1,325✔
59
            to_address: to_address.to_string(),
1,325✔
60
        }
1,325✔
61
    }
1,325✔
62
}
63

64
#[derive(Clone, Debug)]
4✔
65
pub struct TestIncomingTx {
66
    pub input: Vec<TestIncomingInput>,
67
    pub output: Vec<TestIncomingOutput>,
68
    pub min_confirmations: Option<u64>,
69
    pub locktime: Option<i64>,
70
    pub replaceable: Option<bool>,
71
}
72

73
impl TestIncomingTx {
74
    pub fn new(
1,301✔
75
        input: Vec<TestIncomingInput>,
1,301✔
76
        output: Vec<TestIncomingOutput>,
1,301✔
77
        min_confirmations: Option<u64>,
1,301✔
78
        locktime: Option<i64>,
1,301✔
79
        replaceable: Option<bool>,
1,301✔
80
    ) -> Self {
1,301✔
81
        Self {
1,301✔
82
            input,
1,301✔
83
            output,
1,301✔
84
            min_confirmations,
1,301✔
85
            locktime,
1,301✔
86
            replaceable,
1,301✔
87
        }
1,301✔
88
    }
1,301✔
89

90
    pub fn add_input(&mut self, input: TestIncomingInput) {
×
91
        self.input.push(input);
×
92
    }
×
93

94
    pub fn add_output(&mut self, output: TestIncomingOutput) {
×
95
        self.output.push(output);
×
96
    }
×
97
}
98

99
#[doc(hidden)]
100
#[macro_export]
101
macro_rules! testutils {
102
    ( @external $descriptors:expr, $child:expr ) => ({
103
        use $crate::bitcoin::secp256k1::Secp256k1;
104
        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
105

106
        let secp = Secp256k1::new();
107

108
        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
109
        parsed.at_derivation_index($child).address(bitcoin::Network::Regtest).expect("No address form")
110
    });
111
    ( @internal $descriptors:expr, $child:expr ) => ({
112
        use $crate::bitcoin::secp256k1::Secp256k1;
113
        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
114

115
        let secp = Secp256k1::new();
116

117
        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
118
        parsed.at_derivation_index($child).address($crate::bitcoin::Network::Regtest).expect("No address form")
119
    });
120
    ( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
121
    ( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
122
    ( @addr $addr:expr ) => ({ $addr });
123

124
    ( @tx ( $( ( $( $addr:tt )* ) => $amount:expr ),+ ) $( ( @inputs $( ($txid:expr, $vout:expr) ),+ ) )? $( ( @locktime $locktime:expr ) )? $( ( @confirmations $confirmations:expr ) )? $( ( @replaceable $replaceable:expr ) )? ) => ({
125
        let outs = vec![$( $crate::testutils::TestIncomingOutput::new($amount, testutils!( $($addr)* ))),+];
126
        let _ins: Vec<$crate::testutils::TestIncomingInput> = vec![];
127
        $(
128
            let _ins = vec![$( $crate::testutils::TestIncomingInput { txid: $txid, vout: $vout, sequence: None }),+];
129
        )?
130

131
        let locktime = None::<i64>$(.or(Some($locktime)))?;
132

133
        let min_confirmations = None::<u64>$(.or(Some($confirmations)))?;
134
        let replaceable = None::<bool>$(.or(Some($replaceable)))?;
135

136
        $crate::testutils::TestIncomingTx::new(_ins, outs, min_confirmations, locktime, replaceable)
137
    });
138

139
    ( @literal $key:expr ) => ({
140
        let key = $key.to_string();
141
        (key, None::<String>, None::<String>)
142
    });
143
    ( @generate_xprv $( $external_path:expr )? $( ,$internal_path:expr )? ) => ({
144
        use rand::Rng;
145

146
        let mut seed = [0u8; 32];
147
        rand::thread_rng().fill(&mut seed[..]);
148

149
        let key = $crate::bitcoin::util::bip32::ExtendedPrivKey::new_master(
150
            $crate::bitcoin::Network::Testnet,
151
            &seed,
152
        );
153

154
        let external_path = None::<String>$(.or(Some($external_path.to_string())))?;
155
        let internal_path = None::<String>$(.or(Some($internal_path.to_string())))?;
156

157
        (key.unwrap().to_string(), external_path, internal_path)
158
    });
159
    ( @generate_wif ) => ({
160
        use rand::Rng;
161

162
        let mut key = [0u8; $crate::bitcoin::secp256k1::constants::SECRET_KEY_SIZE];
163
        rand::thread_rng().fill(&mut key[..]);
164

165
        ($crate::bitcoin::PrivateKey {
166
            compressed: true,
167
            network: $crate::bitcoin::Network::Testnet,
168
            key: $crate::bitcoin::secp256k1::SecretKey::from_slice(&key).unwrap(),
169
        }.to_string(), None::<String>, None::<String>)
170
    });
171

172
    ( @keys ( $( $alias:expr => ( $( $key_type:tt )* ) ),+ ) ) => ({
173
        let mut map = std::collections::HashMap::new();
174
        $(
175
            let alias: &str = $alias;
176
            map.insert(alias, testutils!( $($key_type)* ));
177
        )+
178

179
        map
180
    });
181

182
    ( @descriptors ( $external_descriptor:expr ) $( ( $internal_descriptor:expr ) )? $( ( @keys $( $keys:tt )* ) )* ) => ({
183
        use std::str::FromStr;
184
        use std::collections::HashMap;
185
        use std::convert::Infallible;
186

187
        use $crate::miniscript::descriptor::Descriptor;
188
        use $crate::miniscript::TranslatePk;
189

190
        struct Translator {
191
            keys: HashMap<&'static str, (String, Option<String>, Option<String>)>,
192
            is_internal: bool,
193
        }
194

195
        impl $crate::miniscript::Translator<String, String, Infallible> for Translator {
196
            fn pk(&mut self, pk: &String) -> Result<String, Infallible> {
582✔
197
                match self.keys.get(pk.as_str()) {
582✔
198
                    Some((key, ext_path, int_path)) => {
280✔
199
                        let path = if self.is_internal { int_path } else { ext_path };
280✔
200
                        Ok(format!("{}{}", key, path.clone().unwrap_or_default()))
280✔
201
                    }
202
                    None => Ok(pk.clone()),
302✔
203
                }
204
            }
582✔
205
            fn sha256(&mut self, sha256: &String) -> Result<String, Infallible> { Ok(sha256.clone()) }
×
206
            fn hash256(&mut self, hash256: &String) -> Result<String, Infallible> { Ok(hash256.clone()) }
×
207
            fn ripemd160(&mut self, ripemd160: &String) -> Result<String, Infallible> { Ok(ripemd160.clone()) }
×
208
            fn hash160(&mut self, hash160: &String) -> Result<String, Infallible> { Ok(hash160.clone()) }
×
209
        }
210

211
        #[allow(unused_assignments, unused_mut)]
212
        let mut keys = HashMap::new();
213
        $(
214
            keys = testutils!{ @keys $( $keys )* };
215
        )*
216

217
        let mut translator = Translator { keys, is_internal: false };
218

219
        let external: Descriptor<String> = FromStr::from_str($external_descriptor).unwrap();
220
        let external = external.translate_pk(&mut translator).expect("Infallible conversion");
221
        let external = external.to_string();
222

223
        translator.is_internal = true;
224

225
        let internal = None::<String>$(.or({
226
            let internal: Descriptor<String> = FromStr::from_str($internal_descriptor).unwrap();
227
            let internal = internal.translate_pk(&mut translator).expect("Infallible conversion");
228
            Some(internal.to_string())
229
        }))?;
230

231
        (external, internal)
232
    })
233
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc