commit 017d32014e53f0769fadbd666a0b4703c2eb773d
parent 6956b9f955463404b8eff3b7abe0cc3092cb5958
Author: William Casarin <jb55@jb55.com>
Date: Thu, 22 Jan 2026 13:39:03 -0800
Merge giftwrap support
William Casarin (7):
build: add libsodium
bindings: update posix bindings for giftwrap changes
ndb: add add_key, process_giftwraps, rumor note fns
giftwraps: fix double free bug
nostrdb: fix crash in ingester thread
win: fix windows build
Diffstat:
6 files changed, 449 insertions(+), 2 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -24,6 +24,7 @@ thiserror = "2.0.7"
futures = "0.3.31"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "time"] }
tracing = "0.1.40"
+libsodium-sys-stable = { version = "1.22.5", features = ["optimized", "minimal"] }
[dev-dependencies]
hex = "0.4.3"
diff --git a/build.rs b/build.rs
@@ -1,7 +1,7 @@
// build.rs
use cc::Build;
use std::env;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
fn secp256k1_build(base_config: &mut Build) {
// Actual build
@@ -30,6 +30,10 @@ fn secp256k1_build(base_config: &mut Build) {
.file("nostrdb/deps/secp256k1/src/precomputed_ecmult.c")
.file("nostrdb/deps/secp256k1/src/secp256k1.c");
+ // libsodium
+ //base_config
+ //.file("nostrdb/deps/libsodium/src/libsodium/crypto_stream/chacha20/stream_chacha20.c");
+
if env::var("PROFILE").unwrap() == "debug" {
base_config.flag("-O1");
}
@@ -69,6 +73,10 @@ fn main() {
"nostrdb/src/bolt11/bech32.c",
"nostrdb/src/block.c",
"nostrdb/src/metadata.c",
+ "nostrdb/src/nip44.c",
+ "nostrdb/src/base64.c",
+ "nostrdb/src/hmac_sha256.c",
+ "nostrdb/src/hkdf_sha256.c",
"nostrdb/src/binmoji.c",
"nostrdb/deps/flatcc/src/runtime/json_parser.c",
"nostrdb/deps/flatcc/src/runtime/verifier.c",
@@ -88,6 +96,46 @@ fn main() {
//.flag("-Werror")
//.flag("-g")
+ {
+ // Provided by libsodium-sys-stable’s build script
+ let dep_include = std::env::var("DEP_SODIUM_INCLUDE")
+ .expect("DEP_SODIUM_INCLUDE not set; is libsodium-sys-stable a dependency?");
+
+ let dep_include_path = Path::new(&dep_include);
+
+ // If DEP_SODIUM_INCLUDE doesn't directly contain `sodium/`, try the known Windows layout:
+ // <...>/out/installed/libsodium/include
+ let mut include_root = dep_include_path.to_path_buf();
+
+ if !include_root.join("sodium").is_dir() {
+ // try sibling layout relative to the libsodium build output
+ // (DEP_SODIUM_INCLUDE is often <...>/out/installed/include on Windows)
+ let candidate = dep_include_path
+ .parent() // <...>/out/installed
+ .unwrap_or(dep_include_path)
+ .join("libsodium")
+ .join("include");
+
+ if candidate.join("sodium").is_dir() {
+ include_root = candidate;
+ }
+ }
+
+ build.include(include_root);
+
+ // static libsodium on MSVC: avoid __imp_ dllimport mismatch
+ if cfg!(target_env = "msvc") {
+ build.define("SODIUM_STATIC", Some("1"));
+ }
+
+ // Optionally use DEP_SODIUM_LIB as well
+ let sodium_lib_dir = std::env::var("DEP_SODIUM_LIB").ok();
+ // Make sure the linker knows where libsodium lives
+ if let Some(lib_dir) = sodium_lib_dir {
+ println!("cargo:rustc-link-search=native={lib_dir}");
+ }
+ }
+
// Link Security framework on macOS
if !cfg!(target_os = "windows") {
build.files(bolt11_deps());
@@ -117,6 +165,15 @@ fn main() {
secp256k1_build(&mut build);
build.compile("libnostrdb.a");
+ build.define("SODIUM_STATIC", Some("1"));
+
+ {
+ let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
+ let is_windows = target_env == "msvc";
+ let sodium_name = if is_windows { "libsodium" } else { "sodium" };
+
+ println!("cargo:rustc-link-lib=static={sodium_name}");
+ }
println!("cargo:rustc-link-lib=static=nostrdb");
diff --git a/src/bindings_posix.rs b/src/bindings_posix.rs
@@ -356,6 +356,9 @@ pub const _STRING_H: u32 = 1;
pub const _STRINGS_H: u32 = 1;
pub const NDB_PACKED_STR: u32 = 1;
pub const NDB_PACKED_ID: u32 = 2;
+pub const NDB_NOTE_FLAG_DELETED: u32 = 1;
+pub const NDB_NOTE_FLAG_RUMOR: u32 = 2;
+pub const NDB_NOTE_FLAG_UNWRAPPED: u32 = 4;
pub const NDB_FLAG_NOMIGRATE: u32 = 1;
pub const NDB_FLAG_SKIP_NOTE_VERIFY: u32 = 2;
pub const NDB_FLAG_NO_FULLTEXT: u32 = 4;
@@ -2360,6 +2363,140 @@ pub const ndb_metadata_type_NDB_NOTE_META_RESERVED: ndb_metadata_type = 0;
pub const ndb_metadata_type_NDB_NOTE_META_COUNTS: ndb_metadata_type = 100;
pub const ndb_metadata_type_NDB_NOTE_META_REACTION: ndb_metadata_type = 200;
pub type ndb_metadata_type = ::std::os::raw::c_uint;
+pub const ndb_decrypt_result_NIP44_OK: ndb_decrypt_result = 0;
+pub const ndb_decrypt_result_NIP44_ERR_UNSUPPORTED_ENCODING: ndb_decrypt_result = 1;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_PAYLOAD: ndb_decrypt_result = 2;
+pub const ndb_decrypt_result_NIP44_ERR_BASE64_DECODE: ndb_decrypt_result = 3;
+pub const ndb_decrypt_result_NIP44_ERR_SECKEY_VERIFY_FAILED: ndb_decrypt_result = 4;
+pub const ndb_decrypt_result_NIP44_ERR_PUBKEY_PARSE_FAILED: ndb_decrypt_result = 5;
+pub const ndb_decrypt_result_NIP44_ERR_ECDH_FAILED: ndb_decrypt_result = 6;
+pub const ndb_decrypt_result_NIP44_ERR_FILL_RANDOM_FAILED: ndb_decrypt_result = 7;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_MAC: ndb_decrypt_result = 8;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_PADDING: ndb_decrypt_result = 9;
+pub const ndb_decrypt_result_NIP44_ERR_BUFFER_TOO_SMALL: ndb_decrypt_result = 10;
+pub type ndb_decrypt_result = ::std::os::raw::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct nip44_payload {
+ pub version: ::std::os::raw::c_uchar,
+ pub nonce: *mut ::std::os::raw::c_uchar,
+ pub ciphertext: *mut ::std::os::raw::c_uchar,
+ pub ciphertext_len: usize,
+ pub mac: *mut ::std::os::raw::c_uchar,
+}
+#[test]
+fn bindgen_test_layout_nip44_payload() {
+ const UNINIT: ::std::mem::MaybeUninit<nip44_payload> = ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<nip44_payload>(),
+ 40usize,
+ concat!("Size of: ", stringify!(nip44_payload))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<nip44_payload>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(nip44_payload))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(version)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).nonce) as usize - ptr as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(nonce)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).ciphertext) as usize - ptr as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(ciphertext)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).ciphertext_len) as usize - ptr as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(ciphertext_len)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).mac) as usize - ptr as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(mac)
+ )
+ );
+}
+extern "C" {
+ pub fn nip44_decrypt(
+ secp_context: *mut ::std::os::raw::c_void,
+ sender_pubkey: *const ::std::os::raw::c_uchar,
+ receiver_seckey: *const ::std::os::raw::c_uchar,
+ payload: *const ::std::os::raw::c_char,
+ payload_len: ::std::os::raw::c_int,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ decrypted: *mut *mut ::std::os::raw::c_uchar,
+ decrypted_len: *mut u16,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_encrypt(
+ secp: *mut ::std::os::raw::c_void,
+ sender_seckey: *const ::std::os::raw::c_uchar,
+ receiver_pubkey: *const ::std::os::raw::c_uchar,
+ plaintext: *const ::std::os::raw::c_uchar,
+ plaintext_size: u16,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ out: *mut *mut ::std::os::raw::c_char,
+ out_len: *mut isize,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_decrypt_raw(
+ secp: *mut ::std::os::raw::c_void,
+ sender_pubkey: *const ::std::os::raw::c_uchar,
+ receiver_seckey: *const ::std::os::raw::c_uchar,
+ decoded: *mut nip44_payload,
+ decrypted: *mut *mut ::std::os::raw::c_uchar,
+ decrypted_len: *mut u16,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_decode_payload(
+ decoded: *mut nip44_payload,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ payload: *const ::std::os::raw::c_char,
+ payload_len: usize,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_err_msg(res: ndb_decrypt_result) -> *const ::std::os::raw::c_char;
+}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ndb_tag_ptr {
@@ -5295,6 +5432,9 @@ extern "C" {
pub fn ndb_db_version(txn: *mut ndb_txn) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_add_key(ndb: *mut ndb, key: *mut ::std::os::raw::c_uchar) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_process_event(
arg1: *mut ndb,
json: *const ::std::os::raw::c_char,
@@ -5324,6 +5464,9 @@ extern "C" {
) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_process_giftwraps(arg1: *mut ndb, arg2: *mut ndb_txn) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_process_events_with(
ndb: *mut ndb,
ldjson: *const ::std::os::raw::c_char,
@@ -5461,6 +5604,16 @@ extern "C" {
) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_note_from_json_custom(
+ json: *const ::std::os::raw::c_char,
+ len: ::std::os::raw::c_int,
+ arg1: *mut *mut ndb_note,
+ buf: *mut ::std::os::raw::c_uchar,
+ buflen: ::std::os::raw::c_int,
+ parse_cond: ::std::os::raw::c_int,
+ ) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_builder_init(
builder: *mut ndb_builder,
buf: *mut ::std::os::raw::c_uchar,
@@ -5880,6 +6033,18 @@ extern "C" {
pub fn ndb_str_len(str_: *mut ndb_str) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_note_flags(arg1: *mut ndb_note) -> *mut u16;
+}
+extern "C" {
+ pub fn ndb_note_is_rumor(note: *mut ndb_note) -> ::std::os::raw::c_int;
+}
+extern "C" {
+ pub fn ndb_note_rumor_receiver_pubkey(note: *mut ndb_note) -> *mut ::std::os::raw::c_uchar;
+}
+extern "C" {
+ pub fn ndb_note_rumor_giftwrap_id(note: *mut ndb_note) -> *mut ::std::os::raw::c_uchar;
+}
+extern "C" {
#[doc = " write the note as json to a buffer"]
pub fn ndb_note_json(
arg1: *mut ndb_note,
@@ -6403,6 +6568,9 @@ fn bindgen_test_layout_ndb_note_meta() {
)
);
}
+pub const ndb_note_meta_flags_NDB_NOTE_META_FLAG_DELETED: ndb_note_meta_flags = 0;
+pub const ndb_note_meta_flags_NDB_NOTE_META_FLAG_SEEN: ndb_note_meta_flags = 2;
+pub type ndb_note_meta_flags = ::std::os::raw::c_uint;
pub type __builtin_va_list = [__va_list_tag; 1usize];
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/src/bindings_win.rs b/src/bindings_win.rs
@@ -353,6 +353,9 @@ pub const EWOULDBLOCK: u32 = 140;
pub const _NLSCMPERROR: u32 = 2147483647;
pub const NDB_PACKED_STR: u32 = 1;
pub const NDB_PACKED_ID: u32 = 2;
+pub const NDB_NOTE_FLAG_DELETED: u32 = 1;
+pub const NDB_NOTE_FLAG_RUMOR: u32 = 2;
+pub const NDB_NOTE_FLAG_UNWRAPPED: u32 = 4;
pub const NDB_FLAG_NOMIGRATE: u32 = 1;
pub const NDB_FLAG_SKIP_NOTE_VERIFY: u32 = 2;
pub const NDB_FLAG_NO_FULLTEXT: u32 = 4;
@@ -2505,6 +2508,140 @@ pub const ndb_metadata_type_NDB_NOTE_META_RESERVED: ndb_metadata_type = 0;
pub const ndb_metadata_type_NDB_NOTE_META_COUNTS: ndb_metadata_type = 100;
pub const ndb_metadata_type_NDB_NOTE_META_REACTION: ndb_metadata_type = 200;
pub type ndb_metadata_type = ::std::os::raw::c_int;
+pub const ndb_decrypt_result_NIP44_OK: ndb_decrypt_result = 0;
+pub const ndb_decrypt_result_NIP44_ERR_UNSUPPORTED_ENCODING: ndb_decrypt_result = 1;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_PAYLOAD: ndb_decrypt_result = 2;
+pub const ndb_decrypt_result_NIP44_ERR_BASE64_DECODE: ndb_decrypt_result = 3;
+pub const ndb_decrypt_result_NIP44_ERR_SECKEY_VERIFY_FAILED: ndb_decrypt_result = 4;
+pub const ndb_decrypt_result_NIP44_ERR_PUBKEY_PARSE_FAILED: ndb_decrypt_result = 5;
+pub const ndb_decrypt_result_NIP44_ERR_ECDH_FAILED: ndb_decrypt_result = 6;
+pub const ndb_decrypt_result_NIP44_ERR_FILL_RANDOM_FAILED: ndb_decrypt_result = 7;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_MAC: ndb_decrypt_result = 8;
+pub const ndb_decrypt_result_NIP44_ERR_INVALID_PADDING: ndb_decrypt_result = 9;
+pub const ndb_decrypt_result_NIP44_ERR_BUFFER_TOO_SMALL: ndb_decrypt_result = 10;
+pub type ndb_decrypt_result = ::std::os::raw::c_int;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct nip44_payload {
+ pub version: ::std::os::raw::c_uchar,
+ pub nonce: *mut ::std::os::raw::c_uchar,
+ pub ciphertext: *mut ::std::os::raw::c_uchar,
+ pub ciphertext_len: usize,
+ pub mac: *mut ::std::os::raw::c_uchar,
+}
+#[test]
+fn bindgen_test_layout_nip44_payload() {
+ const UNINIT: ::std::mem::MaybeUninit<nip44_payload> = ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<nip44_payload>(),
+ 40usize,
+ concat!("Size of: ", stringify!(nip44_payload))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<nip44_payload>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(nip44_payload))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(version)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).nonce) as usize - ptr as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(nonce)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).ciphertext) as usize - ptr as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(ciphertext)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).ciphertext_len) as usize - ptr as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(ciphertext_len)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).mac) as usize - ptr as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(nip44_payload),
+ "::",
+ stringify!(mac)
+ )
+ );
+}
+extern "C" {
+ pub fn nip44_decrypt(
+ secp_context: *mut ::std::os::raw::c_void,
+ sender_pubkey: *const ::std::os::raw::c_uchar,
+ receiver_seckey: *const ::std::os::raw::c_uchar,
+ payload: *const ::std::os::raw::c_char,
+ payload_len: ::std::os::raw::c_int,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ decrypted: *mut *mut ::std::os::raw::c_uchar,
+ decrypted_len: *mut u16,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_encrypt(
+ secp: *mut ::std::os::raw::c_void,
+ sender_seckey: *const ::std::os::raw::c_uchar,
+ receiver_pubkey: *const ::std::os::raw::c_uchar,
+ plaintext: *const ::std::os::raw::c_uchar,
+ plaintext_size: u16,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ out: *mut *mut ::std::os::raw::c_char,
+ out_len: *mut isize,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_decrypt_raw(
+ secp: *mut ::std::os::raw::c_void,
+ sender_pubkey: *const ::std::os::raw::c_uchar,
+ receiver_seckey: *const ::std::os::raw::c_uchar,
+ decoded: *mut nip44_payload,
+ decrypted: *mut *mut ::std::os::raw::c_uchar,
+ decrypted_len: *mut u16,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_decode_payload(
+ decoded: *mut nip44_payload,
+ buf: *mut ::std::os::raw::c_uchar,
+ bufsize: usize,
+ payload: *const ::std::os::raw::c_char,
+ payload_len: usize,
+ ) -> ndb_decrypt_result;
+}
+extern "C" {
+ pub fn nip44_err_msg(res: ndb_decrypt_result) -> *const ::std::os::raw::c_char;
+}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ndb_tag_ptr {
@@ -5439,6 +5576,9 @@ extern "C" {
pub fn ndb_db_version(txn: *mut ndb_txn) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_add_key(ndb: *mut ndb, key: *mut ::std::os::raw::c_uchar) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_process_event(
arg1: *mut ndb,
json: *const ::std::os::raw::c_char,
@@ -5468,6 +5608,9 @@ extern "C" {
) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_process_giftwraps(arg1: *mut ndb, arg2: *mut ndb_txn) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_process_events_with(
ndb: *mut ndb,
ldjson: *const ::std::os::raw::c_char,
@@ -5602,6 +5745,16 @@ extern "C" {
) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_note_from_json_custom(
+ json: *const ::std::os::raw::c_char,
+ len: ::std::os::raw::c_int,
+ arg1: *mut *mut ndb_note,
+ buf: *mut ::std::os::raw::c_uchar,
+ buflen: ::std::os::raw::c_int,
+ parse_cond: ::std::os::raw::c_int,
+ ) -> ::std::os::raw::c_int;
+}
+extern "C" {
pub fn ndb_builder_init(
builder: *mut ndb_builder,
buf: *mut ::std::os::raw::c_uchar,
@@ -6021,6 +6174,18 @@ extern "C" {
pub fn ndb_str_len(str_: *mut ndb_str) -> ::std::os::raw::c_int;
}
extern "C" {
+ pub fn ndb_note_flags(arg1: *mut ndb_note) -> *mut u16;
+}
+extern "C" {
+ pub fn ndb_note_is_rumor(note: *mut ndb_note) -> ::std::os::raw::c_int;
+}
+extern "C" {
+ pub fn ndb_note_rumor_receiver_pubkey(note: *mut ndb_note) -> *mut ::std::os::raw::c_uchar;
+}
+extern "C" {
+ pub fn ndb_note_rumor_giftwrap_id(note: *mut ndb_note) -> *mut ::std::os::raw::c_uchar;
+}
+extern "C" {
#[doc = " write the note as json to a buffer"]
pub fn ndb_note_json(
arg1: *mut ndb_note,
@@ -6543,6 +6708,9 @@ fn bindgen_test_layout_ndb_note_meta() {
)
);
}
+pub const ndb_note_meta_flags_NDB_NOTE_META_FLAG_DELETED: ndb_note_meta_flags = 0;
+pub const ndb_note_meta_flags_NDB_NOTE_META_FLAG_SEEN: ndb_note_meta_flags = 2;
+pub type ndb_note_meta_flags = ::std::os::raw::c_int;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __crt_locale_data {
diff --git a/src/ndb.rs b/src/ndb.rs
@@ -159,6 +159,19 @@ impl Ndb {
self.process_event_with(json, IngestMetadata::new().client(true))
}
+ /// Attempt to unwrap any unprocessed giftwraps
+ pub fn process_giftwraps(&self, txn: &Transaction) {
+ unsafe {
+ bindings::ndb_process_giftwraps(self.as_ptr(), txn.as_mut_ptr());
+ }
+ }
+
+ /// Add a secret key to nostrdb's note ingester threads so that
+ /// nostrdb can unwrap incoming giftwraps.
+ pub fn add_key(&self, key: &[u8; 32]) -> bool {
+ unsafe { bindings::ndb_add_key(self.as_ptr(), key as *const u8 as *mut u8) != 0 }
+ }
+
pub fn query<'a>(
&self,
txn: &'a Transaction,
diff --git a/src/note.rs b/src/note.rs
@@ -189,6 +189,43 @@ impl<'a> Note<'a> {
}
#[inline]
+ pub fn flags(&self) -> u16 {
+ unsafe { *bindings::ndb_note_flags(self.as_ptr()) }
+ }
+
+ #[inline]
+ pub fn is_rumor(&self) -> bool {
+ (self.flags() & (bindings::NDB_NOTE_FLAG_RUMOR as u16))
+ == bindings::NDB_NOTE_FLAG_RUMOR as u16
+ }
+
+ #[inline]
+ pub fn rumor_giftwrap_id(&self) -> Option<&'a [u8; 32]> {
+ unsafe {
+ let ptr = bindings::ndb_note_rumor_giftwrap_id(self.as_ptr());
+
+ if ptr.is_null() {
+ return None;
+ }
+
+ Some(&*(ptr as *const [u8; 32]))
+ }
+ }
+
+ #[inline]
+ pub fn rumor_receiver_pubkey(&self) -> Option<&'a [u8; 32]> {
+ unsafe {
+ let ptr = bindings::ndb_note_rumor_receiver_pubkey(self.as_ptr());
+
+ if ptr.is_null() {
+ return None;
+ }
+
+ Some(&*(ptr as *const [u8; 32]))
+ }
+ }
+
+ #[inline]
pub fn as_ptr(&self) -> *mut bindings::ndb_note {
match self {
Note::Owned { ptr, .. } => *ptr,
@@ -623,6 +660,9 @@ mod tests {
let json = note.json().expect("note json");
// the signature changes so 267 is everything up until the signature
- assert_eq!(&json[..267], "{\"id\":\"fb165be22c7b2518b749aabb7140c73f0887fe84475c82785700663be85ba859\",\"pubkey\":\"6c540ed060bfc2b0c5b6f09cd3ebedf980ef7bc836d69582361d20f2ad124f23\",\"created_at\":42,\"kind\":1,\"tags\":[[\"comment\",\"this is a comment\"],[\"blah\",\"something\"]],\"content\":\"this is the content\"");
+ assert_eq!(
+ &json[..267],
+ "{\"id\":\"fb165be22c7b2518b749aabb7140c73f0887fe84475c82785700663be85ba859\",\"pubkey\":\"6c540ed060bfc2b0c5b6f09cd3ebedf980ef7bc836d69582361d20f2ad124f23\",\"created_at\":42,\"kind\":1,\"tags\":[[\"comment\",\"this is a comment\"],[\"blah\",\"something\"]],\"content\":\"this is the content\""
+ );
}
}