improvement(NIP-19): identify and parse NIP-19 addresses

This commit is contained in:
w3irdrobot 2022-12-21 14:44:50 -05:00 committed by Greg Heartsfield
parent 6f1a4e7d76
commit c1152ce430
4 changed files with 42 additions and 6 deletions

7
Cargo.lock generated
View File

@ -280,6 +280,12 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "bech32"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
[[package]] [[package]]
name = "bitcoin_hashes" name = "bitcoin_hashes"
version = "0.10.0" version = "0.10.0"
@ -1531,6 +1537,7 @@ dependencies = [
"anyhow", "anyhow",
"async-std", "async-std",
"async-trait", "async-trait",
"bech32",
"bitcoin_hashes", "bitcoin_hashes",
"chrono", "chrono",
"clap", "clap",

View File

@ -48,6 +48,7 @@ sqlx = { version ="0.6.2", features=["runtime-tokio-rustls", "postgres", "chrono
chrono = "0.4.23" chrono = "0.4.23"
prometheus = "0.13.3" prometheus = "0.13.3"
indicatif = "0.17.3" indicatif = "0.17.3"
bech32 = "0.9.1"
[dev-dependencies] [dev-dependencies]
anyhow = "1" anyhow = "1"

View File

@ -1,5 +1,5 @@
//! Utilities for searching hexadecimal //! Utilities for searching hexadecimal
use crate::utils::is_hex; use crate::utils::{is_hex};
use hex; use hex;
/// Types of hexadecimal queries. /// Types of hexadecimal queries.
@ -20,15 +20,14 @@ fn is_all_fs(s: &str) -> bool {
/// Find the next hex sequence greater than the argument. /// Find the next hex sequence greater than the argument.
#[must_use] pub fn hex_range(s: &str) -> Option<HexSearch> { #[must_use] pub fn hex_range(s: &str) -> Option<HexSearch> {
// handle special cases let mut hash_base = s.to_owned();
if !is_hex(s) || s.len() > 64 { if !is_hex(&hash_base) || hash_base.len() > 64 {
return None; return None;
} }
if s.len() == 64 { if hash_base.len() == 64 {
return Some(HexSearch::Exact(hex::decode(s).ok()?)); return Some(HexSearch::Exact(hex::decode(&hash_base).ok()?));
} }
// if s is odd, add a zero // if s is odd, add a zero
let mut hash_base = s.to_owned();
let mut odd = hash_base.len() % 2 != 0; let mut odd = hash_base.len() % 2 != 0;
if odd { if odd {
// extend the string to make it even // extend the string to make it even

View File

@ -1,4 +1,5 @@
//! Common utility functions //! Common utility functions
use bech32::FromBase32;
use std::time::SystemTime; use std::time::SystemTime;
/// Seconds since 1970. /// Seconds since 1970.
@ -14,6 +15,17 @@ use std::time::SystemTime;
s.chars().all(|x| char::is_ascii_hexdigit(&x)) s.chars().all(|x| char::is_ascii_hexdigit(&x))
} }
/// Check if string is a nip19 string
pub fn is_nip19(s: &str) -> bool {
s.starts_with("npub") || s.starts_with("note")
}
pub fn nip19_to_hex(s: &str) -> Result<String, bech32::Error> {
let (_hrp, data, _checksum) = bech32::decode(s)?;
let data = Vec::<u8>::from_base32(&data)?;
Ok(hex::encode(data))
}
/// Check if a string contains only lower-case hex chars. /// Check if a string contains only lower-case hex chars.
#[must_use] pub fn is_lower_hex(s: &str) -> bool { #[must_use] pub fn is_lower_hex(s: &str) -> bool {
s.chars().all(|x| { s.chars().all(|x| {
@ -30,4 +42,21 @@ mod tests {
let hexstr = "abcd0123"; let hexstr = "abcd0123";
assert_eq!(is_lower_hex(hexstr), true); assert_eq!(is_lower_hex(hexstr), true);
} }
#[test]
fn nip19() {
let hexkey = "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
let nip19key = "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
assert_eq!(is_nip19(hexkey), false);
assert_eq!(is_nip19(nip19key), true);
}
#[test]
fn nip19_hex() {
let nip19key = "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6";
let expected = "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
let got = nip19_to_hex(nip19key).unwrap();
assert_eq!(expected, got);
}
} }