Skip to content

Commit 7207926

Browse files
committed
Merge #148: Use pass-by-copy for Hrp when possible
faf8651 Use pass-by-copy for Hrp when possible (Tobin C. Harding) Pull request description: We currently have some code that uses pass-by-reference and some that uses pass-by-copy. Further investigation shows that when messing with iterators we have to have a reference to the `Hrp` so that the iterator has somewhere in memory to point to while iterating. The iterator API is intentionally low level, we can make the higher level APIs more ergonomic by using pass-by-copy. ACKs for top commit: apoelstra: ACK faf8651 Tree-SHA512: c7e547033cdec865d887b82ddc0a7c38762693dbf77851355c584afde1082bac1c046f4b4c2ac22a2f016b0a599974701a0ac0914c91629787259747df47d8c2
2 parents 413e8b5 + faf8651 commit 7207926

File tree

8 files changed

+37
-37
lines changed

8 files changed

+37
-37
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
//! assert_eq!(address, ADDR);
4242
//!
4343
//! // Encode arbitrary data as a Bitcoin taproot address.
44-
//! let taproot_address = segwit::encode(&hrp::BC, segwit::VERSION_1, &DATA).expect("valid witness version and program");
44+
//! let taproot_address = segwit::encode(hrp::BC, segwit::VERSION_1, &DATA).expect("valid witness version and program");
4545
//! assert_eq!(taproot_address, TAP_ADDR);
4646
//!
4747
//! // No-alloc: Encode without allocating (ignoring that String::new() allocates :).

src/primitives/checksum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ impl<Ck: Checksum> Engine<Ck> {
9898

9999
/// Feeds `hrp` into the checksum engine.
100100
#[inline]
101-
pub fn input_hrp(&mut self, hrp: &Hrp) {
102-
for fe in HrpFe32Iter::new(hrp) {
101+
pub fn input_hrp(&mut self, hrp: Hrp) {
102+
for fe in HrpFe32Iter::new(&hrp) {
103103
self.input_fe(fe)
104104
}
105105
}

src/primitives/decode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl<'s> UncheckedHrpstring<'s> {
178178
}
179179

180180
let mut checksum_eng = checksum::Engine::<Ck>::new();
181-
checksum_eng.input_hrp(&self.hrp());
181+
checksum_eng.input_hrp(self.hrp());
182182

183183
// Unwrap ok since we checked all characters in our constructor.
184184
for fe in self.data.iter().map(|&b| Fe32::from_char_unchecked(b)) {

src/primitives/encode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ where
183183
/// Adapts the `Fe32Iter` iterator to yield characters representing the bech32 encoding.
184184
#[inline]
185185
pub fn new(hrp: &'hrp Hrp, data: WitnessVersionIter<I>) -> Self {
186-
let checksummed = Checksummed::new_hrp(hrp, data);
186+
let checksummed = Checksummed::new_hrp(*hrp, data);
187187
Self { hrp_iter: Some(hrp.lowercase_char_iter()), checksummed }
188188
}
189189
}
@@ -258,7 +258,7 @@ where
258258
#[inline]
259259
pub fn new(hrp: &'hrp Hrp, data: WitnessVersionIter<I>) -> Self {
260260
let hrp_iter = HrpFe32Iter::new(hrp);
261-
let checksummed = Checksummed::new_hrp(hrp, data);
261+
let checksummed = Checksummed::new_hrp(*hrp, data);
262262
Self { hrp_iter: Some(hrp_iter), checksummed }
263263
}
264264
}

src/primitives/iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ where
256256
/// Creates a new checksummed iterator which adapts a data iterator of field elements by
257257
/// first inputting the [`Hrp`] and then appending a checksum.
258258
#[inline]
259-
pub fn new_hrp(hrp: &Hrp, data: I) -> Checksummed<I, Ck> {
259+
pub fn new_hrp(hrp: Hrp, data: I) -> Checksummed<I, Ck> {
260260
let mut ret = Self::new(data);
261261
ret.checksum_engine.input_hrp(hrp);
262262
ret

src/segwit.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
//! ];
2121
//!
2222
//! // Encode a taproot address suitable for use on mainnet.
23-
//! let _ = segwit::encode_v1(&hrp::BC, &witness_prog);
23+
//! let _ = segwit::encode_v1(hrp::BC, &witness_prog);
2424
//!
2525
//! // Encode a segwit v0 address suitable for use on testnet.
26-
//! let _ = segwit::encode_v0(&hrp::TB, &witness_prog);
26+
//! let _ = segwit::encode_v0(hrp::TB, &witness_prog);
2727
//!
2828
//! // If you have the witness version already you can use:
2929
//! # let witness_version = segwit::VERSION_0;
30-
//! let _ = segwit::encode(&hrp::BC, witness_version, &witness_prog);
30+
//! let _ = segwit::encode(hrp::BC, witness_version, &witness_prog);
3131
//!
3232
//! // Decode a Bitcoin bech32 segwit address.
3333
//! let address = "bc1q2s3rjwvam9dt2ftt4sqxqjf3twav0gdx0k0q2etxflx38c3x8tnssdmnjq";
@@ -94,7 +94,7 @@ pub fn decode(s: &str) -> Result<(Hrp, Fe32, Vec<u8>), DecodeError> {
9494
#[cfg(feature = "alloc")]
9595
#[inline]
9696
pub fn encode(
97-
hrp: &Hrp,
97+
hrp: Hrp,
9898
witness_version: Fe32,
9999
witness_program: &[u8],
100100
) -> Result<String, EncodeError> {
@@ -109,14 +109,14 @@ pub fn encode(
109109
/// Encodes a segwit version 0 address.
110110
#[cfg(feature = "alloc")]
111111
#[inline]
112-
pub fn encode_v0(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
112+
pub fn encode_v0(hrp: Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
113113
encode(hrp, VERSION_0, witness_program)
114114
}
115115

116116
/// Encodes a segwit version 1 address.
117117
#[cfg(feature = "alloc")]
118118
#[inline]
119-
pub fn encode_v1(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
119+
pub fn encode_v1(hrp: Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
120120
encode(hrp, VERSION_1, witness_program)
121121
}
122122

@@ -127,7 +127,7 @@ pub fn encode_v1(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeErro
127127
#[inline]
128128
pub fn encode_to_fmt_unchecked<W: fmt::Write>(
129129
fmt: &mut W,
130-
hrp: &Hrp,
130+
hrp: Hrp,
131131
witness_version: Fe32,
132132
witness_program: &[u8],
133133
) -> fmt::Result {
@@ -140,19 +140,19 @@ pub fn encode_to_fmt_unchecked<W: fmt::Write>(
140140
/// the [`crate::primitives::segwit`] module for validation functions).
141141
pub fn encode_lower_to_fmt_unchecked<W: fmt::Write>(
142142
fmt: &mut W,
143-
hrp: &Hrp,
143+
hrp: Hrp,
144144
witness_version: Fe32,
145145
witness_program: &[u8],
146146
) -> fmt::Result {
147147
let iter = witness_program.iter().copied().bytes_to_fes();
148148
match witness_version {
149149
VERSION_0 => {
150-
for c in iter.with_checksum::<Bech32>(hrp).with_witness_version(VERSION_0).chars() {
150+
for c in iter.with_checksum::<Bech32>(&hrp).with_witness_version(VERSION_0).chars() {
151151
fmt.write_char(c)?;
152152
}
153153
}
154154
version => {
155-
for c in iter.with_checksum::<Bech32m>(hrp).with_witness_version(version).chars() {
155+
for c in iter.with_checksum::<Bech32m>(&hrp).with_witness_version(version).chars() {
156156
fmt.write_char(c)?;
157157
}
158158
}
@@ -169,19 +169,19 @@ pub fn encode_lower_to_fmt_unchecked<W: fmt::Write>(
169169
#[inline]
170170
pub fn encode_upper_to_fmt_unchecked<W: fmt::Write>(
171171
fmt: &mut W,
172-
hrp: &Hrp,
172+
hrp: Hrp,
173173
witness_version: Fe32,
174174
witness_program: &[u8],
175175
) -> fmt::Result {
176176
let iter = witness_program.iter().copied().bytes_to_fes();
177177
match witness_version {
178178
VERSION_0 => {
179-
for c in iter.with_checksum::<Bech32>(hrp).with_witness_version(VERSION_0).chars() {
179+
for c in iter.with_checksum::<Bech32>(&hrp).with_witness_version(VERSION_0).chars() {
180180
fmt.write_char(c.to_ascii_uppercase())?;
181181
}
182182
}
183183
version => {
184-
for c in iter.with_checksum::<Bech32m>(hrp).with_witness_version(version).chars() {
184+
for c in iter.with_checksum::<Bech32m>(&hrp).with_witness_version(version).chars() {
185185
fmt.write_char(c.to_ascii_uppercase())?;
186186
}
187187
}
@@ -198,7 +198,7 @@ pub fn encode_upper_to_fmt_unchecked<W: fmt::Write>(
198198
#[inline]
199199
pub fn encode_to_writer_unchecked<W: std::io::Write>(
200200
w: &mut W,
201-
hrp: &Hrp,
201+
hrp: Hrp,
202202
witness_version: Fe32,
203203
witness_program: &[u8],
204204
) -> std::io::Result<()> {
@@ -213,20 +213,20 @@ pub fn encode_to_writer_unchecked<W: std::io::Write>(
213213
#[inline]
214214
pub fn encode_lower_to_writer_unchecked<W: std::io::Write>(
215215
w: &mut W,
216-
hrp: &Hrp,
216+
hrp: Hrp,
217217
witness_version: Fe32,
218218
witness_program: &[u8],
219219
) -> std::io::Result<()> {
220220
let iter = witness_program.iter().copied().bytes_to_fes();
221221
match witness_version {
222222
VERSION_0 => {
223-
for c in iter.with_checksum::<Bech32>(hrp).with_witness_version(VERSION_0).chars() {
224-
w.write_all(&[c as u8])?;
223+
for c in iter.with_checksum::<Bech32>(&hrp).with_witness_version(VERSION_0).chars() {
224+
w.write_all(&[c.to_ascii_lowercase() as u8])?;
225225
}
226226
}
227227
version => {
228-
for c in iter.with_checksum::<Bech32m>(hrp).with_witness_version(version).chars() {
229-
w.write_all(&[c as u8])?;
228+
for c in iter.with_checksum::<Bech32m>(&hrp).with_witness_version(version).chars() {
229+
w.write_all(&[c.to_ascii_lowercase() as u8])?;
230230
}
231231
}
232232
}
@@ -243,19 +243,19 @@ pub fn encode_lower_to_writer_unchecked<W: std::io::Write>(
243243
#[inline]
244244
pub fn encode_upper_to_writer_unchecked<W: std::io::Write>(
245245
w: &mut W,
246-
hrp: &Hrp,
246+
hrp: Hrp,
247247
witness_version: Fe32,
248248
witness_program: &[u8],
249249
) -> std::io::Result<()> {
250250
let iter = witness_program.iter().copied().bytes_to_fes();
251251
match witness_version {
252252
VERSION_0 => {
253-
for c in iter.with_checksum::<Bech32>(hrp).with_witness_version(VERSION_0).chars() {
253+
for c in iter.with_checksum::<Bech32>(&hrp).with_witness_version(VERSION_0).chars() {
254254
w.write_all(&[c.to_ascii_uppercase() as u8])?;
255255
}
256256
}
257257
version => {
258-
for c in iter.with_checksum::<Bech32m>(hrp).with_witness_version(version).chars() {
258+
for c in iter.with_checksum::<Bech32m>(&hrp).with_witness_version(version).chars() {
259259
w.write_all(&[c.to_ascii_uppercase() as u8])?;
260260
}
261261
}
@@ -357,7 +357,7 @@ mod tests {
357357

358358
for address in addresses {
359359
let (hrp, version, program) = decode(address).expect("failed to decode valid address");
360-
let encoded = encode(&hrp, version, &program).expect("failed to encode address");
360+
let encoded = encode(hrp, version, &program).expect("failed to encode address");
361361
assert_eq!(encoded, address);
362362
}
363363
}
@@ -373,7 +373,7 @@ mod tests {
373373
fn encode_lower_to_fmt() {
374374
let program = witness_program();
375375
let mut address = String::new();
376-
encode_to_fmt_unchecked(&mut address, &hrp::BC, VERSION_0, &program)
376+
encode_to_fmt_unchecked(&mut address, hrp::BC, VERSION_0, &program)
377377
.expect("failed to encode address to QR code");
378378

379379
let want = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4";
@@ -384,7 +384,7 @@ mod tests {
384384
fn encode_upper_to_fmt() {
385385
let program = witness_program();
386386
let mut address = String::new();
387-
encode_upper_to_fmt_unchecked(&mut address, &hrp::BC, VERSION_0, &program)
387+
encode_upper_to_fmt_unchecked(&mut address, hrp::BC, VERSION_0, &program)
388388
.expect("failed to encode address to QR code");
389389

390390
let want = "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4";
@@ -396,7 +396,7 @@ mod tests {
396396
fn encode_lower_to_writer() {
397397
let program = witness_program();
398398
let mut buf = Vec::new();
399-
encode_lower_to_writer_unchecked(&mut buf, &hrp::BC, VERSION_0, &program)
399+
encode_lower_to_writer_unchecked(&mut buf, hrp::BC, VERSION_0, &program)
400400
.expect("failed to encode");
401401

402402
let address = std::str::from_utf8(&buf).expect("ascii is valid utf8");
@@ -409,7 +409,7 @@ mod tests {
409409
fn encode_upper_to_writer() {
410410
let program = witness_program();
411411
let mut buf = Vec::new();
412-
encode_upper_to_writer_unchecked(&mut buf, &hrp::BC, VERSION_0, &program)
412+
encode_upper_to_writer_unchecked(&mut buf, hrp::BC, VERSION_0, &program)
413413
.expect("failed to encode");
414414

415415
let address = std::str::from_utf8(&buf).expect("ascii is valid utf8");
@@ -423,7 +423,7 @@ mod tests {
423423
let program = witness_program();
424424
let mut buf = Vec::new();
425425
let hrp = Hrp::parse_unchecked("BC");
426-
encode_lower_to_writer_unchecked(&mut buf, &hrp, VERSION_0, &program)
426+
encode_lower_to_writer_unchecked(&mut buf, hrp, VERSION_0, &program)
427427
.expect("failed to encode");
428428

429429
let address = std::str::from_utf8(&buf).expect("ascii is valid utf8");

tests/bip_173_test_vectors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ macro_rules! check_valid_address_roundtrip {
6060
// tested by the test vectors. However when BIP-350 came into effect only witness
6161
// version 0 uses bech32 (and this is enforced by encode/decode).
6262
if let Ok((hrp, bech32::Fe32::Q, program)) = bech32::segwit::decode($addr) {
63-
let encoded = bech32::segwit::encode_v0(&hrp, &program).expect("failed to encode address");
63+
let encoded = bech32::segwit::encode_v0(hrp, &program).expect("failed to encode address");
6464
// The bips specifically say that encoder should output lowercase characters so we uppercase manually.
6565
if encoded != $addr {
6666
let got = encoded.to_uppercase();

tests/bip_350_test_vectors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ macro_rules! check_valid_address_roundtrip {
5656
#[cfg(feature = "alloc")]
5757
fn $test_name() {
5858
let (hrp, version, program) = bech32::segwit::decode($addr).expect("failed to decode valid address");
59-
let encoded = bech32::segwit::encode(&hrp, version, &program).expect("failed to encode address");
59+
let encoded = bech32::segwit::encode(hrp, version, &program).expect("failed to encode address");
6060

6161
// The bips specifically say that encoder should output lowercase characters so we uppercase manually.
6262
if encoded != $addr {

0 commit comments

Comments
 (0)