Skip to content

Commit 9a94166

Browse files
committed
Merge rust-bitcoin#2870: Remove Denomination::MilliSatoshi
362c3b8 api: Run just check-api (Jamil Lambert, PhD) 9ea8c58 Fix case sensitivity of denomination (Jamil Lambert, PhD) 67569ca Remove denominations < 1 satoshi (Jamil Lambert, PhD) Pull request description: The denomination `MilliSatoshi` has been removed from `Amount`. `NanoBitcoin` and `PicoBitcoin` have also been removed since they are also less than 1 satoshi and the same reason for removing milliSatoshi in Issue rust-bitcoin#2820 should apply to them. The second patch fixes the way the denominations with various combinations of upper and lower case are handled when converted from a string. Close: rust-bitcoin#2820 ACKs for top commit: Kixunil: ACK 362c3b8 tcharding: ACK 362c3b8 Tree-SHA512: d2dc23366023dae66705352822fbd25b90567971cbe0139ab6937b4dc419a1fd4681af1380232f39cd7844422e069d7861274eb2fd9bfe6730798271f1b50349
2 parents 40d1335 + 362c3b8 commit 9a94166

File tree

4 files changed

+17
-103
lines changed

4 files changed

+17
-103
lines changed

api/units/all-features.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -635,9 +635,6 @@ pub bitcoin_units::amount::Denomination::Bitcoin
635635
pub bitcoin_units::amount::Denomination::CentiBitcoin
636636
pub bitcoin_units::amount::Denomination::MicroBitcoin
637637
pub bitcoin_units::amount::Denomination::MilliBitcoin
638-
pub bitcoin_units::amount::Denomination::MilliSatoshi
639-
pub bitcoin_units::amount::Denomination::NanoBitcoin
640-
pub bitcoin_units::amount::Denomination::PicoBitcoin
641638
pub bitcoin_units::amount::Denomination::Satoshi
642639
pub bitcoin_units::amount::ParseAmountError::InputTooLarge(bitcoin_units::amount::InputTooLargeError)
643640
pub bitcoin_units::amount::ParseAmountError::InvalidCharacter(bitcoin_units::amount::InvalidCharacterError)

api/units/alloc-only.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,9 +593,6 @@ pub bitcoin_units::amount::Denomination::Bitcoin
593593
pub bitcoin_units::amount::Denomination::CentiBitcoin
594594
pub bitcoin_units::amount::Denomination::MicroBitcoin
595595
pub bitcoin_units::amount::Denomination::MilliBitcoin
596-
pub bitcoin_units::amount::Denomination::MilliSatoshi
597-
pub bitcoin_units::amount::Denomination::NanoBitcoin
598-
pub bitcoin_units::amount::Denomination::PicoBitcoin
599596
pub bitcoin_units::amount::Denomination::Satoshi
600597
pub bitcoin_units::amount::ParseAmountError::InputTooLarge(bitcoin_units::amount::InputTooLargeError)
601598
pub bitcoin_units::amount::ParseAmountError::InvalidCharacter(bitcoin_units::amount::InvalidCharacterError)

api/units/no-features.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,6 @@ pub bitcoin_units::amount::Denomination::Bitcoin
249249
pub bitcoin_units::amount::Denomination::CentiBitcoin
250250
pub bitcoin_units::amount::Denomination::MicroBitcoin
251251
pub bitcoin_units::amount::Denomination::MilliBitcoin
252-
pub bitcoin_units::amount::Denomination::MilliSatoshi
253-
pub bitcoin_units::amount::Denomination::NanoBitcoin
254-
pub bitcoin_units::amount::Denomination::PicoBitcoin
255252
pub bitcoin_units::amount::Denomination::Satoshi
256253
pub bitcoin_units::amount::ParseAmountError::InputTooLarge(bitcoin_units::amount::InputTooLargeError)
257254
pub bitcoin_units::amount::ParseAmountError::InvalidCharacter(bitcoin_units::amount::InvalidCharacterError)

units/src/amount.rs

Lines changed: 17 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,8 @@ use internals::write_err;
3030
/// assert_eq!(Amount::from_str("1 cBTC").unwrap(), Amount::from_sat(1_000_000));
3131
/// assert_eq!(Amount::from_str("1 mBTC").unwrap(), Amount::from_sat(100_000));
3232
/// assert_eq!(Amount::from_str("1 uBTC").unwrap(), Amount::from_sat(100));
33-
/// assert_eq!(Amount::from_str("10 nBTC").unwrap(), Amount::from_sat(1));
34-
/// assert_eq!(Amount::from_str("10000 pBTC").unwrap(), Amount::from_sat(1));
3533
/// assert_eq!(Amount::from_str("1 bit").unwrap(), Amount::from_sat(100));
3634
/// assert_eq!(Amount::from_str("1 sat").unwrap(), Amount::from_sat(1));
37-
/// assert_eq!(Amount::from_str("1000 msats").unwrap(), Amount::from_sat(1));
3835
/// ```
3936
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
4037
#[non_exhaustive]
@@ -47,16 +44,10 @@ pub enum Denomination {
4744
MilliBitcoin,
4845
/// uBTC
4946
MicroBitcoin,
50-
/// nBTC
51-
NanoBitcoin,
52-
/// pBTC
53-
PicoBitcoin,
5447
/// bits
5548
Bit,
5649
/// satoshi
5750
Satoshi,
58-
/// msat
59-
MilliSatoshi,
6051
}
6152

6253
impl Denomination {
@@ -73,11 +64,8 @@ impl Denomination {
7364
Denomination::CentiBitcoin => -6,
7465
Denomination::MilliBitcoin => -5,
7566
Denomination::MicroBitcoin => -2,
76-
Denomination::NanoBitcoin => 1,
77-
Denomination::PicoBitcoin => 4,
7867
Denomination::Bit => -2,
7968
Denomination::Satoshi => 0,
80-
Denomination::MilliSatoshi => 3,
8169
}
8270
}
8371

@@ -88,11 +76,8 @@ impl Denomination {
8876
Denomination::CentiBitcoin => "cBTC",
8977
Denomination::MilliBitcoin => "mBTC",
9078
Denomination::MicroBitcoin => "uBTC",
91-
Denomination::NanoBitcoin => "nBTC",
92-
Denomination::PicoBitcoin => "pBTC",
9379
Denomination::Bit => "bits",
9480
Denomination::Satoshi => "satoshi",
95-
Denomination::MilliSatoshi => "msat",
9681
}
9782
}
9883

@@ -103,21 +88,18 @@ impl Denomination {
10388
"cBTC" | "cbtc" => Some(Denomination::CentiBitcoin),
10489
"mBTC" | "mbtc" => Some(Denomination::MilliBitcoin),
10590
"uBTC" | "ubtc" => Some(Denomination::MicroBitcoin),
106-
"nBTC" | "nbtc" => Some(Denomination::NanoBitcoin),
107-
"pBTC" | "pbtc" => Some(Denomination::PicoBitcoin),
10891
"bit" | "bits" | "BIT" | "BITS" => Some(Denomination::Bit),
10992
"SATOSHI" | "satoshi" | "SATOSHIS" | "satoshis" | "SAT" | "sat" | "SATS" | "sats" =>
11093
Some(Denomination::Satoshi),
111-
"mSAT" | "msat" | "mSATs" | "msats" => Some(Denomination::MilliSatoshi),
11294
_ => None,
11395
}
11496
}
11597
}
11698

11799
/// These form are ambigous and could have many meanings. For example, M could denote Mega or Milli.
118100
/// If any of these forms are used, an error type PossiblyConfusingDenomination is returned.
119-
const CONFUSING_FORMS: [&str; 9] =
120-
["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"];
101+
const CONFUSING_FORMS: [&str; 6] =
102+
["MBTC", "Mbtc", "CBTC", "Cbtc", "UBTC", "Ubtc"];
121103

122104
impl fmt::Display for Denomination {
123105
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.as_str()) }
@@ -128,11 +110,13 @@ impl FromStr for Denomination {
128110

129111
/// Convert from a str to Denomination.
130112
///
131-
/// Any combination of upper and/or lower case, excluding uppercase of SI(m, u, n, p) is considered valid.
132-
/// - Singular: BTC, mBTC, uBTC, nBTC, pBTC
133-
/// - Plural or singular: sat, satoshi, bit, msat
113+
/// # Accepted Denominations
134114
///
135-
/// Due to ambiguity between mega and milli, pico and peta we prohibit usage of leading capital 'M', 'P'.
115+
/// All upper or lower case, excluding SI prefix (c, m, u) which must be lower case.
116+
/// - Singular: BTC, cBTC, mBTC, uBTC
117+
/// - Plural or singular: sat, satoshi, bit
118+
///
119+
/// Due to ambiguity between mega and milli we prohibit usage of leading capital 'M'.
136120
fn from_str(s: &str) -> Result<Self, Self::Err> {
137121
use self::ParseDenominationError::*;
138122

@@ -2033,7 +2017,7 @@ mod tests {
20332017
#[test]
20342018
#[cfg(feature = "alloc")]
20352019
fn from_str_zero() {
2036-
let denoms = ["BTC", "mBTC", "uBTC", "nBTC", "pBTC", "bits", "sats", "msats"];
2020+
let denoms = ["BTC", "mBTC", "uBTC", "bits", "sats"];
20372021
for denom in denoms {
20382022
for v in &["0", "000"] {
20392023
let s = format!("{} {}", v, denom);
@@ -2173,13 +2157,10 @@ mod tests {
21732157
assert_eq!(f(11.22, D::Bitcoin), Ok(sat(1122000000)));
21742158
assert_eq!(sf(-11.22, D::MilliBitcoin), Ok(ssat(-1122000)));
21752159
assert_eq!(f(11.22, D::Bit), Ok(sat(1122)));
2176-
assert_eq!(sf(-1000.0, D::MilliSatoshi), Ok(ssat(-1)));
21772160
assert_eq!(f(0.0001234, D::Bitcoin), Ok(sat(12340)));
21782161
assert_eq!(sf(-0.00012345, D::Bitcoin), Ok(ssat(-12345)));
21792162

2180-
assert_eq!(f(-100.0, D::MilliSatoshi), Err(OutOfRangeError::negative().into()));
21812163
assert_eq!(f(11.22, D::Satoshi), Err(TooPreciseError { position: 3 }.into()));
2182-
assert_eq!(sf(-100.0, D::MilliSatoshi), Err(TooPreciseError { position: 1 }.into()));
21832164
assert_eq!(f(42.123456781, D::Bitcoin), Err(TooPreciseError { position: 11 }.into()));
21842165
assert_eq!(sf(-184467440738.0, D::Bitcoin), Err(OutOfRangeError::too_small().into()));
21852166
assert_eq!(
@@ -2204,7 +2185,6 @@ mod tests {
22042185
assert_eq!(btc(2.5).to_float_in(D::Bitcoin), 2.5);
22052186
assert_eq!(btc(-2.5).to_float_in(D::MilliBitcoin), -2500.0);
22062187
assert_eq!(btc(2.5).to_float_in(D::Satoshi), 250000000.0);
2207-
assert_eq!(btc(-2.5).to_float_in(D::MilliSatoshi), -250000000000.0);
22082188

22092189
let btc = move |f| Amount::from_btc(f).unwrap();
22102190
assert_eq!(&btc(0.0012).to_float_in(D::Bitcoin).to_string(), "0.0012")
@@ -2216,7 +2196,6 @@ mod tests {
22162196
use super::ParseAmountError as E;
22172197
let btc = Denomination::Bitcoin;
22182198
let sat = Denomination::Satoshi;
2219-
let msat = Denomination::MilliSatoshi;
22202199
let p = Amount::from_str_in;
22212200
let sp = SignedAmount::from_str_in;
22222201

@@ -2249,15 +2228,11 @@ mod tests {
22492228
#[cfg(feature = "alloc")]
22502229
assert_eq!(p(&more_than_max, btc), Err(OutOfRangeError::too_big(false).into()));
22512230
assert_eq!(p("0.000000042", btc), Err(TooPreciseError { position: 10 }.into()));
2252-
assert_eq!(p("999.0000000", msat), Err(TooPreciseError { position: 0 }.into()));
2253-
assert_eq!(p("1.0000000", msat), Err(TooPreciseError { position: 0 }.into()));
2254-
assert_eq!(p("1.1", msat), Err(TooPreciseError { position: 0 }.into()));
2255-
assert_eq!(p("1000.1", msat), Err(TooPreciseError { position: 5 }.into()));
2256-
assert_eq!(p("1001.0000000", msat), Err(TooPreciseError { position: 3 }.into()));
2257-
assert_eq!(p("1000.0000001", msat), Err(TooPreciseError { position: 11 }.into()));
2258-
assert_eq!(p("1000.1000000", msat), Err(TooPreciseError { position: 5 }.into()));
2259-
assert_eq!(p("1100.0000000", msat), Err(TooPreciseError { position: 1 }.into()));
2260-
assert_eq!(p("10001.0000000", msat), Err(TooPreciseError { position: 4 }.into()));
2231+
assert_eq!(p("1.0000000", sat), Ok(Amount::from_sat(1)));
2232+
assert_eq!(p("1.1", sat), Err(TooPreciseError { position: 2 }.into()));
2233+
assert_eq!(p("1000.1", sat), Err(TooPreciseError { position: 5 }.into()));
2234+
assert_eq!(p("1001.0000000", sat), Ok(Amount::from_sat(1001)));
2235+
assert_eq!(p("1000.0000001", sat), Err(TooPreciseError { position: 11 }.into()));
22612236

22622237
assert_eq!(p("1", btc), Ok(Amount::from_sat(1_000_000_00)));
22632238
assert_eq!(sp("-.5", btc), Ok(SignedAmount::from_sat(-500_000_00)));
@@ -2273,8 +2248,6 @@ mod tests {
22732248
p("12345678901.12345678", btc),
22742249
Ok(Amount::from_sat(12_345_678_901__123_456_78))
22752250
);
2276-
assert_eq!(p("1000.0", msat), Ok(Amount::from_sat(1)));
2277-
assert_eq!(p("1000.000000000000000000000000000", msat), Ok(Amount::from_sat(1)));
22782251

22792252
// make sure satoshi > i64::MAX is checked.
22802253
#[cfg(feature = "alloc")]
@@ -2287,10 +2260,6 @@ mod tests {
22872260
assert!(Amount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat).is_ok());
22882261
}
22892262

2290-
assert_eq!(
2291-
p("12.000", Denomination::MilliSatoshi),
2292-
Err(TooPreciseError { position: 0 }.into())
2293-
);
22942263
// exactly 50 chars.
22952264
assert_eq!(
22962265
p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin),
@@ -2315,7 +2284,6 @@ mod tests {
23152284
assert_eq!(SignedAmount::from_sat(-42).to_string_in(D::Bitcoin), "-0.00000042");
23162285

23172286
assert_eq!(Amount::ONE_BTC.to_string_with_denomination(D::Bitcoin), "1 BTC");
2318-
assert_eq!(Amount::ONE_SAT.to_string_with_denomination(D::MilliSatoshi), "1000 msat");
23192287
assert_eq!(
23202288
SignedAmount::ONE_BTC.to_string_with_denomination(D::Satoshi),
23212289
"100000000 satoshi"
@@ -2499,19 +2467,6 @@ mod tests {
24992467
btc_check_fmt_non_negative_show_denom_align_2, 1, "{:^16}", " 0.00000001";
25002468
}
25012469

2502-
check_format_non_negative! {
2503-
MilliSatoshi;
2504-
msat_check_fmt_non_negative_0, 0, "{}", "0";
2505-
msat_check_fmt_non_negative_1, 1, "{}", "1000";
2506-
msat_check_fmt_non_negative_2, 1, "{:5}", " 1000";
2507-
msat_check_fmt_non_negative_3, 1, "{:05}", "01000";
2508-
msat_check_fmt_non_negative_4, 1, "{:.1}", "1000.0";
2509-
msat_check_fmt_non_negative_5, 1, "{:6.1}", "1000.0";
2510-
msat_check_fmt_non_negative_6, 1, "{:06.1}", "1000.0";
2511-
msat_check_fmt_non_negative_7, 1, "{:7.1}", " 1000.0";
2512-
msat_check_fmt_non_negative_8, 1, "{:07.1}", "01000.0";
2513-
}
2514-
25152470
#[test]
25162471
fn test_unsigned_signed_conversion() {
25172472
let sa = SignedAmount::from_sat;
@@ -2617,10 +2572,6 @@ mod tests {
26172572
assert_eq!("-5", SignedAmount::from_sat(-5).to_string_in(D::Satoshi));
26182573
assert_eq!("0.1", Amount::from_sat(100_000_00).to_string_in(D::Bitcoin));
26192574
assert_eq!("-100", SignedAmount::from_sat(-10_000).to_string_in(D::Bit));
2620-
assert_eq!("2535830", Amount::from_sat(253583).to_string_in(D::NanoBitcoin));
2621-
assert_eq!("-100000", SignedAmount::from_sat(-10_000).to_string_in(D::NanoBitcoin));
2622-
assert_eq!("2535830000", Amount::from_sat(253583).to_string_in(D::PicoBitcoin));
2623-
assert_eq!("-100000000", SignedAmount::from_sat(-10_000).to_string_in(D::PicoBitcoin));
26242575

26252576
assert_eq!("0.50", format!("{:.2}", Amount::from_sat(50).display_in(D::Bit)));
26262577
assert_eq!("-0.50", format!("{:.2}", SignedAmount::from_sat(-50).display_in(D::Bit)));
@@ -2661,31 +2612,6 @@ mod tests {
26612612
Err(OutOfRangeError::too_small().into())
26622613
);
26632614

2664-
assert_eq!(
2665-
sa_str(&sa_sat(-1).to_string_in(D::NanoBitcoin), D::NanoBitcoin),
2666-
Ok(sa_sat(-1))
2667-
);
2668-
assert_eq!(
2669-
sa_str(&sa_sat(i64::MAX).to_string_in(D::Satoshi), D::NanoBitcoin),
2670-
Err(TooPreciseError { position: 18 }.into())
2671-
);
2672-
assert_eq!(
2673-
sa_str(&sa_sat(i64::MIN).to_string_in(D::Satoshi), D::NanoBitcoin),
2674-
Err(TooPreciseError { position: 19 }.into())
2675-
);
2676-
2677-
assert_eq!(
2678-
sa_str(&sa_sat(-1).to_string_in(D::PicoBitcoin), D::PicoBitcoin),
2679-
Ok(sa_sat(-1))
2680-
);
2681-
assert_eq!(
2682-
sa_str(&sa_sat(i64::MAX).to_string_in(D::Satoshi), D::PicoBitcoin),
2683-
Err(TooPreciseError { position: 18 }.into())
2684-
);
2685-
assert_eq!(
2686-
sa_str(&sa_sat(i64::MIN).to_string_in(D::Satoshi), D::PicoBitcoin),
2687-
Err(TooPreciseError { position: 19 }.into())
2688-
);
26892615
}
26902616

26912617
#[cfg(feature = "alloc")]
@@ -2702,9 +2628,6 @@ mod tests {
27022628
assert_eq!(Amount::from_str(&denom(amt, D::MicroBitcoin)), Ok(amt));
27032629
assert_eq!(Amount::from_str(&denom(amt, D::Bit)), Ok(amt));
27042630
assert_eq!(Amount::from_str(&denom(amt, D::Satoshi)), Ok(amt));
2705-
assert_eq!(Amount::from_str(&denom(amt, D::NanoBitcoin)), Ok(amt));
2706-
assert_eq!(Amount::from_str(&denom(amt, D::MilliSatoshi)), Ok(amt));
2707-
assert_eq!(Amount::from_str(&denom(amt, D::PicoBitcoin)), Ok(amt));
27082631

27092632
assert_eq!(
27102633
Amount::from_str("42 satoshi BTC"),
@@ -2918,7 +2841,7 @@ mod tests {
29182841
// Non-exhaustive list of valid forms.
29192842
let valid = [
29202843
"BTC", "btc", "mBTC", "mbtc", "uBTC", "ubtc", "SATOSHI", "satoshi", "SATOSHIS",
2921-
"satoshis", "SAT", "sat", "SATS", "sats", "bit", "bits", "nBTC", "pBTC",
2844+
"satoshis", "SAT", "sat", "SATS", "sats", "bit", "bits",
29222845
];
29232846
for denom in valid.iter() {
29242847
assert!(Denomination::from_str(denom).is_ok());
@@ -2927,7 +2850,7 @@ mod tests {
29272850

29282851
#[test]
29292852
fn disallow_confusing_forms() {
2930-
let confusing = ["Msat", "Msats", "MSAT", "MSATS", "MSat", "MSats", "MBTC", "Mbtc", "PBTC"];
2853+
let confusing = ["CBTC", "Cbtc", "MBTC", "Mbtc", "UBTC", "Ubtc"];
29312854
for denom in confusing.iter() {
29322855
match Denomination::from_str(denom) {
29332856
Ok(_) => panic!("from_str should error for {}", denom),
@@ -2940,7 +2863,7 @@ mod tests {
29402863
#[test]
29412864
fn disallow_unknown_denomination() {
29422865
// Non-exhaustive list of unknown forms.
2943-
let unknown = ["NBTC", "UBTC", "ABC", "abc", "cBtC", "Sat", "Sats"];
2866+
let unknown = ["NBTC", "ABC", "abc", "mSat", "msat"];
29442867
for denom in unknown.iter() {
29452868
match Denomination::from_str(denom) {
29462869
Ok(_) => panic!("from_str should error for {}", denom),

0 commit comments

Comments
 (0)