Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
23 changes: 23 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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",
Expand All @@ -88,6 +96,15 @@ fn main() {
//.flag("-Werror")
//.flag("-g")

// Provided by libsodium-sys-stable’s build script
let sodium_include = std::env::var("DEP_SODIUM_INCLUDE")
.expect("DEP_SODIUM_INCLUDE not set; is libsodium-sys-stable a dependency?");

// Optionally use DEP_SODIUM_LIB as well
let sodium_lib_dir = std::env::var("DEP_SODIUM_LIB").ok();

build.include(&sodium_include);

// Link Security framework on macOS
if !cfg!(target_os = "windows") {
build.files(bolt11_deps());
Expand Down Expand Up @@ -118,7 +135,13 @@ fn main() {

build.compile("libnostrdb.a");

// Make sure the linker knows where libsodium lives
if let Some(lib_dir) = sodium_lib_dir {
println!("cargo:rustc-link-search=native={lib_dir}");
}

println!("cargo:rustc-link-lib=static=nostrdb");
println!("cargo:rustc-link-lib=static=sodium");

// Re-run the build script if any of the C files or headers change
for file in &["nostrdb/src/nostrdb.c", "nostrdb/src/nostrdb.h"] {
Expand Down
2 changes: 1 addition & 1 deletion nostrdb
Submodule nostrdb updated 565 files
168 changes: 168 additions & 0 deletions src/bindings_posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -5294,6 +5431,9 @@ extern "C" {
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,
Expand Down Expand Up @@ -5323,6 +5463,9 @@ extern "C" {
len: usize,
) -> ::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,
Expand Down Expand Up @@ -5460,6 +5603,16 @@ extern "C" {
buflen: ::std::os::raw::c_int,
) -> ::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,
Expand Down Expand Up @@ -5879,6 +6032,18 @@ extern "C" {
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(
Expand Down Expand Up @@ -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)]
Expand Down
13 changes: 13 additions & 0 deletions src/ndb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
42 changes: 41 additions & 1 deletion src/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,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 {
Expand Down Expand Up @@ -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\""
);
}
}
Loading