nostr
nostr copied to clipboard
Failed to parse nprofile
Describe the bug
The nprofile nprofile1qyxhwumn8ghj7cnjvghxjme0qyxhwumn8ghj7cnjvghxjme0qyt8wumn8ghj7etyv4hzumn0wd68ytnvv9hxgtcpzemhxue69uhk2er9dchxummnw3ezumrpdejz7qgwwaehxw309ahx7uewd3hkctcppemhxue69uhkummn9ekx7mp0qy08wumn8ghj7mn0wd68yttsw43zuam9d3kx7unyv4ezumn9wshsz8nhwden5te0dehhxarj94c82c3wwajkcmr0wfjx2u3wdejhgtcpr4mhxue69uhkummnw3ezucnfw33k76twv4ezuum0vd5kzmp0qyv8wumn8ghj7mn0wd68ytnxd46zuamf0ghxy6t69uq3samnwvaz7tmwdaehgu3wvekhgtnhd9azucnf0ghsz9mhwden5te0dehhxarj9eex2mrp09jhytnnv5hsz9mhwden5te0dehhxarj9eex2mrp09jhytnnv5hszythwden5te0dehhxarj9emkjmn99uq3gamnwvaz7tmwdaehgu3w0qcxvtn0wfnj7qgnwaehxw309ahkvenrdpskjm3wwp6kytcpzdmhxue69uhk7enxvd5xz6tw9ec82c30qyv8wumn8ghj7un9d3shjtnrw4e8yetwwshxv7tf9uq3samnwvaz7tmjv4kxz7fwvd6hyun9de6zuenedyhsz9thwden5te0wfjkccte9ejxzmt4wvhxjme0qy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qgkwaehxw309aex2mrp0yhx6mmnw3ezuur4vghsz9mhwden5te0wfjkccte9ehx7um5wghxyctwvshsz9mhwden5te0wfjkccte9ehx7um5wghxjmnxduhsz9mhwden5te0wfjkccte9ehx7um5wghxjmnxduhszxthwden5te0wfjkccte9ehx7umhdpjhyefwvdhk6tcpzamhxue69uhhyetvv9ujuurjd9kkzmpwdejhgtcpr9mhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv9uq3jamnwvaz7tmjv4kxz7fwwdhx7un59eek7cmfv9kz7qpqsyluunzwwmc70d85d9alzqc2jrc6pdur7xrax2vqpfxas6tljavsrwlyyy fails to parse to a Nip19Profile with the error rust.nostr.sdk.NostrSdkException$Generic: no valid bech32 or bech32m checksum.
I found this nprofile while scrolling nostr (nevent1qqsw2w7ha4vn0cx4ygd4y9pxmypa8ctfgym52v3lpsjd7xk3rnryeagzyz7mj6knrtr27y3uw6pu24m4acsn3ks03uq3uwv5644zwfcwdyjh2qcyqqqqqqgpr3mhxue69uhkummnw3ezucnfw33k76twv4ezuum0vd5kzmquw82w6). Other clients have no problem parsing it so maybe failing the parse process is too harsh?
To Reproduce
Use nprofile above
Expected behavior
Ignore the error or keep it as is. If the nprofile really is invalid and you think failing is the correct move then close this issue, I just want to let you know that these nprofiles are out there
Build environment
- Library: nostr-sdk
- Language: Kotlin
- Language version: v0.38.3
- Tag/commit:
- OS+version:
Additional context
I think it's related to the same issue I mentioned here: https://github.com/rust-nostr/nostr/pull/394#pullrequestreview-1986706154
The bech32 crate check the string length from v0.11 (enforced by the BIP-173), and that nprofile is pretty long.
I receive this error:
Bech32Decode(Checksum(CodeLength(CodeLengthError { encoded_length: 1179, code_length: 1023 })))
- https://github.com/rust-bitcoin/rust-bech32/issues/140
- https://github.com/rust-bitcoin/rust-bech32/pull/142
- https://github.com/rust-bitcoin/rust-bech32/issues/156
@yukibtc What do you think about forking rust-bech32 and revert the pull request?
I tried the following change, it decode it right. But when I tried it with encode it produce a different nprofile.
impl FromBech32 for Nip19Profile {
type Err = Error;
fn from_bech32(profile: &str) -> Result<Self, Self::Err> {
struct TestBech32;
const GEN: [u32; 5] = [
0x3b6a_57b2,
0x2650_8e6d,
0x1ea1_19fa,
0x3d42_33dd,
0x2a14_62b3,
];
impl bech32::Checksum for TestBech32 {
type MidstateRepr = u32;
const CODE_LENGTH: usize = usize::MAX;
const CHECKSUM_LENGTH: usize = 6;
const GENERATOR_SH: [u32; 5] = GEN;
const TARGET_RESIDUE: u32 = 1;
}
let hrp_str =
bech32::primitives::decode::CheckedHrpstring::new::<TestBech32>(profile).unwrap();
if hrp_str.hrp() != HRP_PROFILE {
return Err(Error::WrongPrefix);
}
Self::from_bech32_data(hrp_str.byte_iter().collect())
// let (hrp, data) = bech32::decode(profile)?;
// if hrp != HRP_PROFILE {
// return Err(Error::WrongPrefix);
// }
// Self::from_bech32_data(data)
}
}
This is the encoding change, if you want to try it
impl ToBech32 for Nip19Profile {
type Err = Error;
fn to_bech32(&self) -> Result<String, Self::Err> {
struct TestBech32;
const GEN: [u32; 5] = [
0x3b6a_57b2,
0x2650_8e6d,
0x1ea1_19fa,
0x3d42_33dd,
0x2a14_62b3,
];
impl bech32::Checksum for TestBech32 {
type MidstateRepr = u32;
const CODE_LENGTH: usize = usize::MAX;
const CHECKSUM_LENGTH: usize = 6;
const GENERATOR_SH: [u32; 5] = GEN;
const TARGET_RESIDUE: u32 = 1;
}
// Allocate capacity
let relays_len: usize = self.relays.iter().map(|u| 2 + u.as_str().len()).sum();
let mut bytes: Vec<u8> = Vec::with_capacity(FIXED_1_1_32_BYTES_TVL + relays_len);
bytes.push(SPECIAL); // Type
bytes.push(32); // Len
bytes.extend(self.public_key.as_bytes()); // Value
for relay in self.relays.iter() {
let url: &[u8] = relay.as_str().as_bytes();
bytes.push(RELAY); // Type
bytes.push(url.len() as u8); // Len
bytes.extend(url); // Value
}
Ok(bech32::encode::<TestBech32>(HRP_PROFILE, &bytes)?)
}
}
Closed as not planned for the reasons described at https://github.com/rust-nostr/nostr/pull/785#pullrequestreview-2728568914