commit c055121e750b82e7a099b71ae8305b72b57680de
parent 805349013d731e423ad62e7cb3f20ec695fcd092
Author: William Casarin <jb55@jb55.com>
Date: Wed, 10 Dec 2025 07:10:42 -0800
Add giftwrap support
Changelog-Added: Add support for processing and viewing giftwraps
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
5 files changed, 256 insertions(+), 17 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -44,6 +44,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
+name = "adler32"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
+
+[[package]]
name = "aead"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -189,6 +195,9 @@ name = "arbitrary"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
+dependencies = [
+ "derive_arbitrary",
+]
[[package]]
name = "arboard"
@@ -1203,6 +1212,15 @@ dependencies = [
]
[[package]]
+name = "core2"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1335,6 +1353,12 @@ dependencies = [
]
[[package]]
+name = "dary_heap"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04"
+
+[[package]]
name = "data-encoding"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1379,6 +1403,17 @@ dependencies = [
]
[[package]]
+name = "derive_arbitrary"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
name = "derive_builder"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1705,7 +1740,7 @@ checksum = "59a81c221a1e4dad06cb9c9deb19aea1193a5eea084e8cd42d869068132bf876"
dependencies = [
"document-features",
"js-sys",
- "ureq",
+ "ureq 2.12.1",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
@@ -1973,6 +2008,18 @@ dependencies = [
]
[[package]]
+name = "filetime"
+version = "0.2.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "libredox",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
name = "flatbuffers"
version = "23.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1989,6 +2036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
dependencies = [
"crc32fast",
+ "libz-rs-sys",
"miniz_oxide",
]
@@ -2087,6 +2135,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
+[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2523,7 +2577,18 @@ checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"allocator-api2",
"equivalent",
- "foldhash",
+ "foldhash 0.1.5",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+dependencies = [
+ "allocator-api2",
+ "equivalent",
+ "foldhash 0.2.0",
]
[[package]]
@@ -3210,6 +3275,30 @@ dependencies = [
]
[[package]]
+name = "libflate"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3248b8d211bd23a104a42d81b4fa8bb8ac4a3b75e7a43d85d2c9ccb6179cd74"
+dependencies = [
+ "adler32",
+ "core2",
+ "crc32fast",
+ "dary_heap",
+ "libflate_lz77",
+]
+
+[[package]]
+name = "libflate_lz77"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a599cb10a9cd92b1300debcef28da8f70b935ec937f44fcd1b70a7c986a11c5c"
+dependencies = [
+ "core2",
+ "hashbrown 0.16.1",
+ "rle-decode-fast",
+]
+
+[[package]]
name = "libfuzzer-sys"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3241,6 +3330,32 @@ dependencies = [
]
[[package]]
+name = "libsodium-sys-stable"
+version = "1.22.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8119f38969584f49be1d1da6f011ed268cc64e3eac5b4f9374c40d9694ad1421"
+dependencies = [
+ "cc",
+ "libc",
+ "libflate",
+ "minisign-verify",
+ "pkg-config",
+ "tar",
+ "ureq 3.1.4",
+ "vcpkg",
+ "zip",
+]
+
+[[package]]
+name = "libz-rs-sys"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b484ba8d4f775eeca644c452a56650e544bf7e617f1d170fe7298122ead5222"
+dependencies = [
+ "zlib-rs",
+]
+
+[[package]]
name = "lightning-invoice"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3488,6 +3603,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
+name = "minisign-verify"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e856fdd13623a2f5f2f54676a4ee49502a96a80ef4a62bcedd23d52427c44d43"
+
+[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3724,13 +3845,14 @@ dependencies = [
[[package]]
name = "nostrdb"
version = "0.8.0"
-source = "git+https://github.com/damus-io/nostrdb-rs?rev=6956b9f955463404b8eff3b7abe0cc3092cb5958#6956b9f955463404b8eff3b7abe0cc3092cb5958"
+source = "git+https://github.com/damus-io/nostrdb-rs?rev=78468aca8c263e50cae463743536d760239cc43d#78468aca8c263e50cae463743536d760239cc43d"
dependencies = [
"bindgen 0.69.5",
"cc",
"flatbuffers",
"futures",
"libc",
+ "libsodium-sys-stable",
"thiserror 2.0.12",
"tokio",
"tracing",
@@ -5351,6 +5473,12 @@ dependencies = [
]
[[package]]
+name = "rle-decode-fast"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
+
+[[package]]
name = "rmp"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6099,6 +6227,17 @@ dependencies = [
]
[[package]]
+name = "tar"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
+[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6742,6 +6881,31 @@ dependencies = [
]
[[package]]
+name = "ureq"
+version = "3.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a"
+dependencies = [
+ "base64 0.22.1",
+ "log",
+ "percent-encoding",
+ "ureq-proto",
+ "utf-8",
+]
+
+[[package]]
+name = "ureq-proto"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f"
+dependencies = [
+ "base64 0.22.1",
+ "http",
+ "httparse",
+ "log",
+]
+
+[[package]]
name = "url"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7981,6 +8145,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
[[package]]
+name = "xattr"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
+dependencies = [
+ "libc",
+ "rustix 1.0.7",
+]
+
+[[package]]
name = "xcursor"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -8202,6 +8376,38 @@ dependencies = [
]
[[package]]
+name = "zip"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb2a05c7c36fde6c09b08576c9f7fb4cda705990f73b58fe011abf7dfb24168b"
+dependencies = [
+ "arbitrary",
+ "crc32fast",
+ "flate2",
+ "indexmap 2.9.0",
+ "memchr",
+ "zopfli",
+]
+
+[[package]]
+name = "zlib-rs"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36134c44663532e6519d7a6dfdbbe06f6f8192bde8ae9ed076e9b213f0e31df7"
+
+[[package]]
+name = "zopfli"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7"
+dependencies = [
+ "bumpalo",
+ "crc32fast",
+ "log",
+ "simd-adler32",
+]
+
+[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
@@ -51,7 +51,7 @@ md5 = "0.7.0"
nostr = { version = "0.37.0", default-features = false, features = ["std", "nip49"] }
nwc = "0.39.0"
mio = { version = "1.0.3", features = ["os-poll", "net"] }
-nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "6956b9f955463404b8eff3b7abe0cc3092cb5958" }
+nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "78468aca8c263e50cae463743536d760239cc43d" }
#nostrdb = "0.6.1"
notedeck = { path = "crates/notedeck" }
notedeck_chrome = { path = "crates/notedeck_chrome" }
diff --git a/crates/notedeck/src/account/cache.rs b/crates/notedeck/src/account/cache.rs
@@ -110,6 +110,10 @@ impl AccountCache {
&self.fallback
}
+ pub fn accounts(&self) -> impl Iterator<Item = &UserAccount> {
+ self.accounts.values()
+ }
+
pub(super) fn accounts_mut(&mut self) -> impl Iterator<Item = &mut UserAccount> {
self.accounts.values_mut()
}
diff --git a/crates/notedeck/src/app.rs b/crates/notedeck/src/app.rs
@@ -252,13 +252,18 @@ impl Notedeck {
&mut unknown_ids,
);
- {
- for key in &parsed_args.keys {
- info!("adding account: {}", &key.pubkey);
- if let Some(resp) = accounts.add_account(key.clone()) {
- resp.unk_id_action
- .process_action(&mut unknown_ids, &ndb, &txn);
- }
+ for key in &parsed_args.keys {
+ info!("adding account: {}", &key.pubkey);
+ if let Some(resp) = accounts.add_account(key.clone()) {
+ resp.unk_id_action
+ .process_action(&mut unknown_ids, &ndb, &txn);
+ }
+ }
+
+ /* add keys to nostrdb ingest threads for giftwrap processing */
+ for account in accounts.cache.accounts() {
+ if let Some(seckey) = &account.key.secret_key {
+ ndb.add_key(&seckey.secret_bytes());
}
}
diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs
@@ -342,7 +342,8 @@ impl<'a, 'd> NoteView<'a, 'd> {
#[profiling::function]
fn note_header(
ui: &mut egui::Ui,
- i18n: &mut Localization,
+ txn: &Transaction,
+ note_context: &mut NoteContext,
note: &Note,
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
flags: NoteOptions,
@@ -350,10 +351,12 @@ impl<'a, 'd> NoteView<'a, 'd> {
let horiz_resp = ui
.horizontal_wrapped(|ui| {
ui.spacing_mut().item_spacing.x = if is_narrow(ui.ctx()) { 1.0 } else { 2.0 };
- let response = ui
- .add(Username::new(i18n, profile.as_ref().ok(), note.pubkey()).abbreviated(20));
+ let response = ui.add(
+ Username::new(note_context.i18n, profile.as_ref().ok(), note.pubkey())
+ .abbreviated(20),
+ );
if !flags.contains(NoteOptions::FullCreatedDate) {
- return render_notetime(ui, i18n, note.created_at(), true);
+ return render_notetime(ui, note_context.i18n, note.created_at(), true);
}
response
})
@@ -370,6 +373,25 @@ impl<'a, 'd> NoteView<'a, 'd> {
ui.painter()
.circle_filled(circle_center, radius, crate::colors::PINK);
}
+
+ if note.is_rumor() {
+ ui.horizontal_wrapped(|ui| {
+ ui.spacing_mut().item_spacing.x = if is_narrow(ui.ctx()) { 1.0 } else { 2.0 };
+
+ secondary_label(ui, "encrypted privately to");
+
+ crate::Mention::new(
+ note_context.ndb,
+ note_context.img_cache,
+ note_context.jobs,
+ txn,
+ note.rumor_receiver_pubkey().expect("expected pubkey"),
+ )
+ .size(10.0)
+ .selectable(true)
+ .show(ui);
+ });
+ }
}
fn wide_ui(
@@ -400,7 +422,8 @@ impl<'a, 'd> NoteView<'a, 'd> {
ui.horizontal_centered(|ui| {
NoteView::note_header(
ui,
- self.note_context.i18n,
+ txn,
+ self.note_context,
self.note,
profile,
self.flags,
@@ -509,7 +532,8 @@ impl<'a, 'd> NoteView<'a, 'd> {
if !self.flags.contains(NoteOptions::NotificationPreview) {
NoteView::note_header(
ui,
- self.note_context.i18n,
+ txn,
+ self.note_context,
self.note,
profile,
self.flags,