Skip to content

Commit 60057a7

Browse files
committed
Deprecate backward compatible get_checksum_bytes, get_checksum functions
Rename replacement functions calc_checksum_bytes and calc_checksum
1 parent e2a4a58 commit 60057a7

File tree

5 files changed

+68
-25
lines changed

5 files changed

+68
-25
lines changed

src/blockchain/rpc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::bitcoin::hashes::hex::ToHex;
3535
use crate::bitcoin::{Network, OutPoint, Transaction, TxOut, Txid};
3636
use crate::blockchain::*;
3737
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
38-
use crate::descriptor::get_checksum;
38+
use crate::descriptor::calc_checksum;
3939
use crate::error::MissingCachedScripts;
4040
use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
4141
use bitcoin::Script;
@@ -801,7 +801,7 @@ fn is_wallet_descriptor(client: &Client) -> Result<bool, Error> {
801801

802802
fn descriptor_from_script_pubkey(script: &Script) -> String {
803803
let desc = format!("raw({})", script.to_hex());
804-
format!("{}#{}", desc, get_checksum(&desc).unwrap())
804+
format!("{}#{}", desc, calc_checksum(&desc).unwrap())
805805
}
806806

807807
/// Factory of [`RpcBlockchain`] instances, implements [`BlockchainFactory`]

src/descriptor/checksum.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ fn poly_mod(mut c: u64, val: u64) -> u64 {
4343

4444
/// Computes the checksum bytes of a descriptor.
4545
/// `exclude_hash = true` ignores all data after the first '#' (inclusive).
46-
pub fn get_checksum_bytes(mut desc: &str, exclude_hash: bool) -> Result<[u8; 8], DescriptorError> {
46+
pub(crate) fn calc_checksum_bytes_internal(
47+
mut desc: &str,
48+
exclude_hash: bool,
49+
) -> Result<[u8; 8], DescriptorError> {
4750
let mut c = 1;
4851
let mut cls = 0;
4952
let mut clscount = 0;
@@ -91,34 +94,74 @@ pub fn get_checksum_bytes(mut desc: &str, exclude_hash: bool) -> Result<[u8; 8],
9194
Ok(checksum)
9295
}
9396

97+
/// Compute the checksum bytes of a descriptor, any existing checksum hash will be excluded from the calculation
98+
pub fn calc_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError> {
99+
calc_checksum_bytes_internal(desc, true)
100+
}
101+
102+
/// Compute the checksum of a descriptor, any existing checksum hash will be excluded from the calculation
103+
pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError> {
104+
// unsafe is okay here as the checksum only uses bytes in `CHECKSUM_CHARSET`
105+
calc_checksum_bytes_internal(desc, true)
106+
.map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) })
107+
}
108+
109+
// TODO in release 0.25.0, remove get_checksum_bytes and get_checksum
110+
// TODO in release 0.25.0, consolidate calc_checksum_bytes_internal into calc_checksum_bytes
111+
112+
/// Compute the checksum bytes of a descriptor
113+
#[deprecated(
114+
since = "0.24.0",
115+
note = "Use new `calc_checksum_bytes` function which excludes any existing hash before calculating the checksum hash bytes. See https://github.com/bitcoindevkit/bdk/pull/765."
116+
)]
117+
pub fn get_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError> {
118+
calc_checksum_bytes_internal(desc, false)
119+
}
120+
94121
/// Compute the checksum of a descriptor
122+
#[deprecated(
123+
since = "0.24.0",
124+
note = "Use new `calc_checksum` function which excludes any existing hash before calculating the checksum hash. See https://github.com/bitcoindevkit/bdk/pull/765."
125+
)]
95126
pub fn get_checksum(desc: &str) -> Result<String, DescriptorError> {
96127
// unsafe is okay here as the checksum only uses bytes in `CHECKSUM_CHARSET`
97-
get_checksum_bytes(desc, true).map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) })
128+
calc_checksum_bytes_internal(desc, false)
129+
.map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) })
98130
}
99131

100132
#[cfg(test)]
101133
mod test {
102134
use super::*;
103-
use crate::descriptor::get_checksum;
135+
use crate::descriptor::calc_checksum;
104136

105-
// test get_checksum() function; it should return the same value as Bitcoin Core
137+
// test calc_checksum() function; it should return the same value as Bitcoin Core
106138
#[test]
107-
fn test_get_checksum() {
139+
fn test_calc_checksum() {
108140
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
109-
assert_eq!(get_checksum(desc).unwrap(), "tqz0nc62");
141+
assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
110142

111143
let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
112-
assert_eq!(get_checksum(desc).unwrap(), "lasegmfs");
144+
assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
145+
}
146+
147+
// test calc_checksum() function; it should return the same value as Bitcoin Core even if the
148+
// descriptor string includes a checksum hash
149+
#[test]
150+
fn test_calc_checksum_with_checksum_hash() {
151+
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62";
152+
assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
153+
154+
let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmfs";
155+
assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
113156
}
114157

115158
#[test]
116-
fn test_get_checksum_invalid_character() {
159+
fn test_calc_checksum_invalid_character() {
117160
let sparkle_heart = unsafe { std::str::from_utf8_unchecked(&[240, 159, 146, 150]) };
118161
let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
119162

120163
assert!(matches!(
121-
get_checksum(&invalid_desc).err(),
164+
calc_checksum(&invalid_desc).err(),
122165
Some(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart.as_bytes()[0]
123166
));
124167
}

src/descriptor/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ pub mod error;
3939
pub mod policy;
4040
pub mod template;
4141

42-
pub use self::checksum::get_checksum;
43-
use self::checksum::get_checksum_bytes;
42+
pub use self::checksum::calc_checksum;
43+
use self::checksum::calc_checksum_bytes;
4444
pub use self::derived::{AsDerived, DerivedDescriptorKey};
4545
pub use self::error::Error as DescriptorError;
4646
pub use self::policy::Policy;
@@ -87,7 +87,7 @@ impl IntoWalletDescriptor for &str {
8787
) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
8888
let descriptor = match self.split_once('#') {
8989
Some((desc, original_checksum)) => {
90-
let checksum = get_checksum_bytes(desc, false)?;
90+
let checksum = calc_checksum_bytes(desc)?;
9191
if original_checksum.as_bytes() != checksum {
9292
return Err(DescriptorError::InvalidDescriptorChecksum);
9393
}

src/descriptor/policy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use crate::keys::ExtScriptContext;
6060
use crate::wallet::signer::{SignerId, SignersContainer};
6161
use crate::wallet::utils::{self, After, Older, SecpCtx};
6262

63-
use super::checksum::get_checksum;
63+
use super::checksum::calc_checksum;
6464
use super::error::Error;
6565
use super::XKeyUtils;
6666
use bitcoin::util::psbt::{Input as PsbtInput, PartiallySignedTransaction as Psbt};
@@ -165,7 +165,7 @@ impl SatisfiableItem {
165165

166166
/// Returns a unique id for the [`SatisfiableItem`]
167167
pub fn id(&self) -> String {
168-
get_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
168+
calc_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
169169
.expect("Failed to compute a SatisfiableItem id")
170170
}
171171
}

src/wallet/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ use utils::{check_nlocktime, check_nsequence_rbf, After, Older, SecpCtx};
6464
use crate::blockchain::{GetHeight, NoopProgress, Progress, WalletSync};
6565
use crate::database::memory::MemoryDatabase;
6666
use crate::database::{AnyDatabase, BatchDatabase, BatchOperations, DatabaseUtils, SyncTime};
67-
use crate::descriptor::checksum::get_checksum_bytes;
67+
use crate::descriptor::checksum::calc_checksum_bytes_internal;
6868
use crate::descriptor::derived::AsDerived;
6969
use crate::descriptor::policy::BuildSatisfaction;
7070
use crate::descriptor::{
71-
get_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DerivedDescriptorMeta,
71+
calc_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DerivedDescriptorMeta,
7272
DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor,
7373
Policy, XKeyUtils,
7474
};
@@ -248,12 +248,12 @@ where
248248
/// actual checksum, and the second time with the checksum of `descriptor+checksum`. The second
249249
/// check is necessary for backwards compatibility of a checksum-inception bug.
250250
fn db_checksum(db: &mut D, desc: &str, kind: KeychainKind) -> Result<(), Error> {
251-
let checksum = get_checksum_bytes(desc, true)?;
251+
let checksum = calc_checksum_bytes_internal(desc, true)?;
252252
if db.check_descriptor_checksum(kind, checksum).is_ok() {
253253
return Ok(());
254254
}
255255

256-
let checksum_inception = get_checksum_bytes(desc, false)?;
256+
let checksum_inception = calc_checksum_bytes_internal(desc, false)?;
257257
db.check_descriptor_checksum(kind, checksum_inception)
258258
}
259259

@@ -1878,14 +1878,14 @@ where
18781878
.into_wallet_descriptor(secp, network)?
18791879
.0
18801880
.to_string();
1881-
let mut wallet_name = get_checksum(&descriptor[..descriptor.find('#').unwrap()])?;
1881+
let mut wallet_name = calc_checksum(&descriptor[..descriptor.find('#').unwrap()])?;
18821882
if let Some(change_descriptor) = change_descriptor {
18831883
let change_descriptor = change_descriptor
18841884
.into_wallet_descriptor(secp, network)?
18851885
.0
18861886
.to_string();
18871887
wallet_name.push_str(
1888-
get_checksum(&change_descriptor[..change_descriptor.find('#').unwrap()])?.as_str(),
1888+
calc_checksum(&change_descriptor[..change_descriptor.find('#').unwrap()])?.as_str(),
18891889
);
18901890
}
18911891

@@ -1958,7 +1958,7 @@ pub(crate) mod test {
19581958
let checksum = wallet.descriptor_checksum(KeychainKind::External);
19591959
assert_eq!(checksum.len(), 8);
19601960
assert_eq!(
1961-
get_checksum(&wallet.descriptor.to_string()).unwrap(),
1961+
calc_checksum(&wallet.descriptor.to_string()).unwrap(),
19621962
checksum
19631963
);
19641964
}
@@ -1968,8 +1968,8 @@ pub(crate) mod test {
19681968
let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
19691969
let desc = wallet.descriptor.to_string();
19701970

1971-
let checksum = get_checksum_bytes(&desc, true).unwrap();
1972-
let checksum_inception = get_checksum_bytes(&desc, false).unwrap();
1971+
let checksum = calc_checksum_bytes_internal(&desc, true).unwrap();
1972+
let checksum_inception = calc_checksum_bytes_internal(&desc, false).unwrap();
19731973
let checksum_invalid = [b'q'; 8];
19741974

19751975
let mut db = MemoryDatabase::new();

0 commit comments

Comments
 (0)