Skip to content

Commit 0c9b6c7

Browse files
authored
Merge pull request #3223 from ProvableHQ/chore/update-bech32
[Chore] Update `bech32` and `sha2`
2 parents 159f04c + 8bfe24b commit 0c9b6c7

20 files changed

Lines changed: 313 additions & 357 deletions

File tree

Cargo.lock

Lines changed: 183 additions & 223 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ version = "1.0"
534534
version = "2.0"
535535

536536
[workspace.dependencies.sha2]
537-
version = "0.10"
537+
version = "0.11"
538538
default-features = false
539539

540540
[workspace.dependencies.smallvec]

console/account/src/signature/parse.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ impl<N: Network> FromStr for Signature<N> {
4040
/// Reads in the signature string.
4141
fn from_str(signature: &str) -> Result<Self, Self::Err> {
4242
// Decode the signature string from bech32m.
43-
let (hrp, data, variant) = bech32::decode(signature)?;
44-
if hrp != SIGNATURE_PREFIX {
43+
let checked = bech32::primitives::decode::CheckedHrpstring::new::<LongBech32m>(signature)?;
44+
let hrp = checked.hrp();
45+
let data: Vec<u8> = checked.byte_iter().collect();
46+
if hrp.as_str() != SIGNATURE_PREFIX {
4547
bail!("Failed to decode signature: '{hrp}' is an invalid prefix")
4648
} else if data.is_empty() {
4749
bail!("Failed to decode signature: data field is empty")
48-
} else if variant != bech32::Variant::Bech32m {
49-
bail!("Found an signature that is not bech32m encoded: {signature}");
5050
}
51-
// Decode the signature data from u5 to u8, and into the signature.
52-
Ok(Self::read_le(&Vec::from_base32(&data)?[..])?)
51+
// Decode the signature data into the signature.
52+
Ok(Self::read_le(&data[..])?)
5353
}
5454
}
5555

@@ -65,8 +65,8 @@ impl<N: Network> Display for Signature<N> {
6565
// Convert the signature to bytes.
6666
let bytes = self.to_bytes_le().map_err(|_| fmt::Error)?;
6767
// Encode the bytes into bech32m.
68-
let string =
69-
bech32::encode(SIGNATURE_PREFIX, bytes.to_base32(), bech32::Variant::Bech32m).map_err(|_| fmt::Error)?;
68+
let string = bech32::encode::<LongBech32m>(bech32::Hrp::parse_unchecked(SIGNATURE_PREFIX), &bytes)
69+
.map_err(|_| fmt::Error)?;
7070
// Output the string.
7171
Display::fmt(&string, f)
7272
}

console/network/environment/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ workspace = true
2121
workspace = true
2222

2323
[dependencies.bech32]
24-
version = "0.9"
24+
version = "0.11"
2525

2626
[dependencies.itertools]
2727
workspace = true

console/network/environment/src/helpers/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,21 @@ pub use sanitizer::Sanitizer;
2121

2222
pub mod variable_length;
2323
pub use variable_length::{read_variable_length_integer, variable_length_integer};
24+
25+
/// A bech32m checksum with no hard length limit.
26+
///
27+
/// bech32 0.11 caps [`bech32::Bech32m`] at 1023 characters, but Aleo types such as
28+
/// ciphertexts, state paths, and snark keys can legitimately exceed this. This type
29+
/// uses identical generator coefficients and target residue as `Bech32m`, so encoded
30+
/// strings are valid bech32m and round-trip correctly with any standard decoder that
31+
/// does not enforce a maximum length.
32+
pub enum LongBech32m {}
33+
34+
impl bech32::primitives::checksum::Checksum for LongBech32m {
35+
type MidstateRepr = u32;
36+
37+
const CHECKSUM_LENGTH: usize = 6;
38+
const CODE_LENGTH: usize = usize::MAX;
39+
const GENERATOR_SH: [u32; 5] = [0x3b6a_57b2, 0x2650_8e6d, 0x1ea1_19fa, 0x3d42_33dd, 0x2a14_62b3];
40+
const TARGET_RESIDUE: u32 = 0x2bc830a3;
41+
}

console/network/environment/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub mod prelude {
134134
};
135135

136136
pub use anyhow::{Error, Result, anyhow, bail, ensure};
137-
pub use bech32::{self, FromBase32, ToBase32};
137+
pub use bech32;
138138
pub use itertools::Itertools;
139139
pub use nom::{
140140
Err,

console/network/src/helpers/id.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use crate::prelude::*;
1717

1818
use anyhow::Result;
19-
use bech32::{self, FromBase32, ToBase32};
2019
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
2120
use std::borrow::Borrow;
2221

@@ -127,30 +126,28 @@ impl<F: FieldTrait, const PREFIX: u16> FromStr for AleoID<F, PREFIX> {
127126
bail!("Invalid byte size for a bech32m hash: {} bytes", string.len())
128127
}
129128

130-
let (hrp, data, variant) = bech32::decode(string)?;
129+
let checked = bech32::primitives::decode::CheckedHrpstring::new::<LongBech32m>(string)?;
130+
let hrp = checked.hrp();
131+
let data: Vec<u8> = checked.byte_iter().collect();
131132
if hrp.as_bytes() != PREFIX.to_le_bytes() {
132133
bail!("Invalid prefix for a bech32m hash: {hrp}")
133134
};
134135
if data.is_empty() {
135136
bail!("Bech32m hash data is empty")
136137
}
137-
if variant != bech32::Variant::Bech32m {
138-
bail!("Hash is not a bech32m hash")
139-
}
140-
Ok(Self::read_le(&*Vec::from_base32(&data)?)?)
138+
Ok(Self::read_le(&*data)?)
141139
}
142140
}
143141

144142
impl<F: FieldTrait, const PREFIX: u16> Display for AleoID<F, PREFIX> {
145143
#[inline]
146144
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
147-
bech32::encode_to_fmt(
145+
bech32::encode_to_fmt::<LongBech32m, _>(
148146
f,
149-
&Self::prefix(),
150-
self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(),
151-
bech32::Variant::Bech32m,
147+
bech32::Hrp::parse_unchecked(&Self::prefix()),
148+
&self.0.to_bytes_le().expect("Failed to write data as bytes"),
152149
)
153-
.expect("Failed to encode in bech32m")
150+
.map_err(|_| fmt::Error)
154151
}
155152
}
156153

console/network/src/helpers/object.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use crate::prelude::*;
1717

1818
use anyhow::Result;
19-
use bech32::{self, FromBase32, ToBase32};
2019
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
2120
use std::borrow::Borrow;
2221

@@ -97,17 +96,16 @@ impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, cons
9796
/// Reads in a bech32m string.
9897
#[inline]
9998
fn from_str(string: &str) -> Result<Self, Self::Err> {
100-
let (hrp, data, variant) = bech32::decode(string)?;
99+
let checked = bech32::primitives::decode::CheckedHrpstring::new::<LongBech32m>(string)?;
100+
let hrp = checked.hrp();
101+
let data: Vec<u8> = checked.byte_iter().collect();
101102
if hrp.as_bytes() != PREFIX.to_le_bytes() {
102103
bail!("Invalid prefix for a bech32m hash: {hrp}")
103104
};
104105
if data.is_empty() {
105106
bail!("Bech32m hash data is empty")
106107
}
107-
if variant != bech32::Variant::Bech32m {
108-
bail!("Hash is not a bech32m hash")
109-
}
110-
Ok(Self::read_le(&*Vec::from_base32(&data)?)?)
108+
Ok(Self::read_le(&*data)?)
111109
}
112110
}
113111

@@ -116,13 +114,12 @@ impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, cons
116114
{
117115
#[inline]
118116
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
119-
bech32::encode_to_fmt(
117+
bech32::encode_to_fmt::<LongBech32m, _>(
120118
f,
121-
&Self::prefix(),
122-
self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(),
123-
bech32::Variant::Bech32m,
119+
bech32::Hrp::parse_unchecked(&Self::prefix()),
120+
&self.0.to_bytes_le().expect("Failed to write data as bytes"),
124121
)
125-
.expect("Failed to encode in bech32m")
122+
.map_err(|_| fmt::Error)
126123
}
127124
}
128125

console/program/src/data/ciphertext/parse.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ impl<N: Network> FromStr for Ciphertext<N> {
4040
/// Reads in the ciphertext string.
4141
fn from_str(ciphertext: &str) -> Result<Self, Self::Err> {
4242
// Decode the ciphertext string from bech32m.
43-
let (hrp, data, variant) = bech32::decode(ciphertext)?;
44-
if hrp != CIPHERTEXT_PREFIX {
43+
let checked = bech32::primitives::decode::CheckedHrpstring::new::<LongBech32m>(ciphertext)?;
44+
let hrp = checked.hrp();
45+
let data: Vec<u8> = checked.byte_iter().collect();
46+
if hrp.as_str() != CIPHERTEXT_PREFIX {
4547
bail!("Failed to decode ciphertext: '{hrp}' is an invalid prefix")
4648
} else if data.is_empty() {
4749
bail!("Failed to decode ciphertext: data field is empty")
48-
} else if variant != bech32::Variant::Bech32m {
49-
bail!("Found an ciphertext that is not bech32m encoded: {ciphertext}");
5050
}
51-
// Decode the ciphertext data from u5 to u8, and into the ciphertext.
52-
Ok(Self::read_le(&Vec::from_base32(&data)?[..])?)
51+
// Decode the ciphertext data into the ciphertext.
52+
Ok(Self::read_le(&data[..])?)
5353
}
5454
}
5555

@@ -65,8 +65,8 @@ impl<N: Network> Display for Ciphertext<N> {
6565
// Convert the ciphertext to bytes.
6666
let bytes = self.to_bytes_le().map_err(|_| fmt::Error)?;
6767
// Encode the bytes into bech32m.
68-
let string =
69-
bech32::encode(CIPHERTEXT_PREFIX, bytes.to_base32(), bech32::Variant::Bech32m).map_err(|_| fmt::Error)?;
68+
let string = bech32::encode::<LongBech32m>(bech32::Hrp::parse_unchecked(CIPHERTEXT_PREFIX), &bytes)
69+
.map_err(|_| fmt::Error)?;
7070
// Output the string.
7171
Display::fmt(&string, f)
7272
}

console/program/src/data/record/parse_ciphertext.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ impl<N: Network> FromStr for Record<N, Ciphertext<N>> {
4040
/// Reads in the ciphertext string.
4141
fn from_str(ciphertext: &str) -> Result<Self, Self::Err> {
4242
// Decode the ciphertext string from bech32m.
43-
let (hrp, data, variant) = bech32::decode(ciphertext)?;
44-
if hrp != RECORD_CIPHERTEXT_PREFIX {
43+
let checked = bech32::primitives::decode::CheckedHrpstring::new::<LongBech32m>(ciphertext)?;
44+
let hrp = checked.hrp();
45+
let data: Vec<u8> = checked.byte_iter().collect();
46+
if hrp.as_str() != RECORD_CIPHERTEXT_PREFIX {
4547
bail!("Failed to decode record ciphertext: '{hrp}' is an invalid prefix")
4648
} else if data.is_empty() {
4749
bail!("Failed to decode record ciphertext: data field is empty")
48-
} else if variant != bech32::Variant::Bech32m {
49-
bail!("Found a record ciphertext that is not bech32m encoded: {ciphertext}");
5050
}
51-
// Decode the record ciphertext data from u5 to u8, and into the record ciphertext.
52-
Ok(Self::read_le(&Vec::from_base32(&data)?[..])?)
51+
// Decode the record ciphertext data into the record ciphertext.
52+
Ok(Self::read_le(&data[..])?)
5353
}
5454
}
5555

@@ -65,7 +65,7 @@ impl<N: Network> Display for Record<N, Ciphertext<N>> {
6565
// Convert the ciphertext to bytes.
6666
let bytes = self.to_bytes_le().map_err(|_| fmt::Error)?;
6767
// Encode the bytes into bech32m.
68-
let string = bech32::encode(RECORD_CIPHERTEXT_PREFIX, bytes.to_base32(), bech32::Variant::Bech32m)
68+
let string = bech32::encode::<LongBech32m>(bech32::Hrp::parse_unchecked(RECORD_CIPHERTEXT_PREFIX), &bytes)
6969
.map_err(|_| fmt::Error)?;
7070
// Output the string.
7171
Display::fmt(&string, f)

0 commit comments

Comments
 (0)