Commit Graph

150 Commits

Author SHA1 Message Date
Claude 034c1ab2d1 fix: replace ThreadLocal with KMP-compatible ScratchLocal expect/actual
ThreadLocal.withInitial is a JVM-only API that doesn't compile on
Kotlin/Native or iOS targets. Replace all usages in commonMain
(FieldP.kt, Point.kt) with a new ScratchLocal expect/actual:

- jvmMain/androidMain: delegates to java.lang.ThreadLocal (same behavior)
- nativeMain: holds value directly (Kotlin/Native coroutines are
  cooperative, scratch buffers don't need thread isolation)

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-06 21:06:44 +00:00
Vitor Pamplona b60a0bcae8 Reverts the use of our own Secp256K1 until faster than native 2026-04-06 16:31:38 -04:00
Claude e0fc42e955 perf: Android API-level-gated unsignedMultiplyHigh + eliminate per-call branch
Three Android-specific optimizations:

1. Use Math.unsignedMultiplyHigh on API 35+ (Android 15): single UMULH
   instruction, eliminates the 4-insn signed→unsigned correction that
   the fallback path requires. Same optimization as our JVM 18+ path.

2. Use Math.multiplyHigh + correction on API 31-34 (Android 12-14):
   avoids the pure-Kotlin 4×32-bit sub-product fallback entirely.

3. Resolve API level check ONCE at class load via static final fields
   (HAS_MULTIPLY_HIGH, HAS_UNSIGNED_MULTIPLY_HIGH) instead of checking
   Build.VERSION.SDK_INT on every call. These functions are called 16×
   per field multiply (~12,000× per signature verify), so eliminating
   the per-call branch matters.

Performance tiers on Android:
  API 35+ (Android 15):  ~same as JVM 18+ (UMULH intrinsic)
  API 31-34 (Android 12-14): SMULH + 3 correction insns per product
  API 26-30 (Android 8-11): pure-Kotlin fallback (4 sub-products)

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-06 20:14:45 +00:00
Claude 1b9706c23f perf: use Math.unsignedMultiplyHigh on Java 18+ — up to 61% faster
On Java 18+, Math.unsignedMultiplyHigh compiles to a single UMULH
instruction, eliminating the 4-instruction signed→unsigned correction
(multiplyHigh + 2 AND + 1 SHR + 2 ADD) per 64×64 product. With 16
products per field multiply, this saves ~64 instructions per mul/sqr.

Detection uses MethodHandle resolved once at class init. On older JVMs
and Android, falls back to the signed+correction path automatically.

Results on Java 21 (vs previous):
  pubkeyCreate:  23,400 → 37,700 ops/s (+61%, 2.2× → 1.6× native)
  sign (cached): 16,700 → 27,400 ops/s (+64%, 1.5× → 1.1× native)
  verify:         5,600 →  7,300 ops/s (+31%, 4.4× → 3.6× native)
  ECDH:           7,100 → 10,000 ops/s (+41%, 3.9× → 3.5× native)
  ecdhXOnly:      5,600 → 10,500 ops/s (+88%, 4.4× → 2.6× native)

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-06 17:58:02 +00:00
Claude 040b4ce02a feat: 4×64-bit limb representation with Math.multiplyHigh (WIP — breaks build)
Foundation layer for the 4×64-bit limb optimization. This commit rewrites
U256 from IntArray(8) to LongArray(4) and adds platform-specific
Math.multiplyHigh for 64×64→128-bit products:

- JVM: Math.multiplyHigh intrinsic (single IMULH/SMULH instruction)
- Android API 31+: Math.multiplyHigh, fallback to pure Kotlin on older
- Native: pure Kotlin fallback (4 sub-products per multiplyHigh call)

The 4×64 representation reduces inner products from 64 to 16 per field
multiply on JVM, a potential ~1.5-2× speedup on the critical path.

NOTE: This commit intentionally breaks the build — FieldP, ScalarN, Glv,
Point, KeyCodec, Secp256k1, and all tests still expect IntArray(8).
They will be updated in subsequent commits.

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-06 01:10:10 +00:00
Claude 4c3b31fe8e feat: replace fr.acinq.secp256k1 with pure-Kotlin secp256k1 implementation
Implements all secp256k1 operations used by Secp256k1Instance in pure Kotlin,
eliminating the dependency on native secp256k1 bindings (fr.acinq.secp256k1-kmp).

Implementation:
- Field.kt: 256-bit unsigned integer arithmetic, field mod p, scalar mod n
- Point.kt: EC point operations (Jacobian coords), point parsing/serialization
- Secp256k1.kt: Public API - pubkeyCreate, pubKeyCompress, secKeyVerify,
  signSchnorr/verifySchnorr (BIP-340), privKeyTweakAdd, pubKeyTweakMul

Tests (36 total):
- All 19 BIP-340 test vectors (signing vectors 0-3, 15-18; verify vectors 4-14)
- ACINQ test vectors for key creation, compression, secKeyVerify, privKeyTweakAdd,
  pubKeyTweakMul
- ECDH symmetry and sign/verify round-trip tests

Secp256k1Instance is now a concrete object in commonMain instead of expect/actual,
delegating to the pure-Kotlin implementation. All existing NIP-44 and BIP-32 tests
pass with the new implementation.

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-05 20:32:54 +00:00
greenart7c3 198e049873 Assign rejected based on the presence of the "rejected" key in intent extras rather than retrieving its specific boolean value 2026-03-30 17:18:02 -03:00
Claude 6e7f6eccf1 refactor: reorganize NIP-BE into subpackages and add README
Restructured nipBEBle/ into logical subpackages:
- Root: public API surface (BleNostrMesh, BleConfig, BlePeer, BleRole)
- protocol/: wire format (BleMessageChunker, BleChunkAssembler)
- transport/: platform BLE abstraction (BleTransport, AndroidBleTransport)
- relay/: Nostr protocol over BLE (BleNostrClient, BleNostrServer, BleMeshManager)

Added README.md with quick start guide, package structure overview,
advanced usage examples, and wire protocol reference.

https://claude.ai/code/session_01Tz5E73Rj7tL48A3qUGS5DT
2026-03-30 02:23:49 +00:00
Claude 28f68382dd feat: add BleNostrMesh facade for simpler developer API
Before (4 steps, manual wiring):
  val transport = AndroidBleTransport(context)
  val mesh = BleMeshManager(transport, object : BleMeshListener { ... })
  transport.setListener(mesh)
  mesh.start()

After (2 steps, auto-wired):
  val mesh = BleNostrMesh(AndroidBleTransport(context))
  mesh.onEvent { event, peer -> saveEvent(event) }
  mesh.start()

The facade uses lambda callbacks instead of interface implementation,
and auto-wires the transport listener via AndroidBleTransportContract.
BleMeshManager remains available for advanced use cases.

https://claude.ai/code/session_01Tz5E73Rj7tL48A3qUGS5DT
2026-03-30 02:18:24 +00:00
Claude 57aec95e8d fix: align NIP-BE chunk format with KoalaSat/samiz reference implementation
Reviewed the samiz BLE implementation and fixed compatibility issues:

- Chunk index: changed from 2 bytes to 1 byte (matching samiz/NIP-BE example)
- Chunk overhead: 2 bytes total (1 index + 1 total count), not 3
- chunkSize parameter now means payload size (500), not total chunk size
- Android: TX power HIGH, advertise timeout indefinite (matching samiz)
- Android: request MTU 512 and CONNECTION_PRIORITY_HIGH on connect
- Android: discover services after MTU negotiation (samiz flow)
- Android: set WRITE_TYPE_DEFAULT on write characteristic
- MTU-to-chunkSize: properly accounts for ATT overhead (3) + chunk overhead (2)

These changes ensure wire-level compatibility with samiz devices.

https://claude.ai/code/session_01Tz5E73Rj7tL48A3qUGS5DT
2026-03-30 02:12:52 +00:00
Claude fb78c1a4c4 feat: implement NIP-BE Nostr BLE Communications Protocol in Quartz
Adds full NIP-BE implementation for BLE-based Nostr peer-to-peer
messaging and synchronization with KMP support across all targets.

Protocol layer (commonMain):
- BleConfig: NIP-BE constants (service UUID, characteristic UUIDs)
- BleMessageChunker: DEFLATE compression + chunk splitting/joining
- BleRole/assignRole: Role assignment based on UUID comparison
- BleTransport: Platform-agnostic BLE transport interface
- BleNostrClient: IRelayClient implementation over BLE
- BleNostrServer: Relay server over BLE with notification support
- BleMeshManager: High-level mesh manager with auto-discovery,
  role assignment, and event broadcasting
- BleChunkAssembler: Thread-safe chunk reassembly

Platform support:
- Deflate expect/actual for jvmAndroid, apple, and linux targets
- AndroidBleTransport: Full Android BLE implementation using GATT
  server/client APIs with scanning, advertising, and MTU negotiation

Tests: Deflate compression, message chunking, role assignment,
and chunk assembly (25 tests passing).

https://claude.ai/code/session_01Tz5E73Rj7tL48A3qUGS5DT
2026-03-30 01:58:26 +00:00
davotoula 541b197a64 feat: add throwable support to Log.d/i and inline lambda overloads
- Add optional throwable parameter to d() and i() across all platforms
- Add inline lambda overloads for all log levels to defer message
  construction, avoiding string allocation when level is filtered
- Restore VoiceMessagePreview to pass throwable directly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 10:56:18 +02:00
davotoula 25b2cb42d0 feat: convert Log from expect/actual to filtered wrapper over PlatformLog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 10:56:18 +02:00
davotoula 65bc617222 feat: add PlatformLog actual implementations for all platforms
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 10:55:18 +02:00
Claude 610fcd7e0c fix: suppress deprecation and unchecked cast warnings in Quartz internal code
Deprecated APIs in Quartz are kept for library consumers but internal usages
now carry @Suppress annotations so the module builds warning-free. Also
replaces redundant .toInt() on hex Int literals in ChaCha20Core and migrates
deprecated java.net.URL to URI.resolve() in ServerInfoParser.

The spotless license header delimiter is updated to recognize @file: annotations.

https://claude.ai/code/session_01EwS56YAGGnnac5EuwhaUSs
2026-03-28 16:39:51 +00:00
Claude d586a0dc25 feat: replace libsodium with pure Kotlin ChaCha20/Poly1305 implementation
Remove LazySodium/JNA/libsodium native dependencies and replace with
pure Kotlin implementations of ChaCha20, HChaCha20, XChaCha20,
Poly1305 MAC, and XChaCha20-Poly1305 AEAD. This eliminates platform-
specific native binaries while maintaining full NIP-44 compatibility.

- Add ChaCha20Core with RFC 8439 block function, IETF stream XOR,
  HChaCha20, and XChaCha20
- Add Poly1305 MAC (RFC 8439 §2.5)
- Add XChaCha20Poly1305 AEAD encrypt/decrypt
- Convert LibSodiumInstance from expect/actual to commonMain object
- Delete platform-specific LibSodiumInstance actuals (android/jvm/ios)
- Remove iOS native interop (cinterop, linker opts, .a libraries)
- Remove lazysodium-java, lazysodium-android, JNA from build deps
- Clean up ProGuard rules (remove JNA/LazySodium keep rules)
- Add RFC 8439 + libsodium test vectors for ChaCha20 and XChaCha20
- Update benchmark to use simplified ChaCha20 API

https://claude.ai/code/session_01YHBwqnb3Z7Q7PX31tJ2G3i
2026-03-23 17:40:29 +00:00
Vitor Pamplona d431b12f94 Migrates EventStore from Android's SQLLite to KMP
Fixes testing of libsodium between java and android
2026-03-20 16:00:17 -04:00
Claude 883a2f995e style: apply ktlint formatting fixes
https://claude.ai/code/session_01HeWiRdKDTnMGfEBUegk3d1
2026-03-17 03:43:19 +00:00
Vitor Pamplona 6ffc902598 Unifies UriParser 2026-03-16 18:15:43 -04:00
Vitor Pamplona 7fabb6b554 Makes addresses serializable 2026-03-02 15:39:58 -05:00
Vitor Pamplona 64c8c0edfd Improves the name of the NIP01 Crypto object 2026-02-18 11:29:56 -05:00
Vitor Pamplona eb66182211 - Updates several libraries
- Reformats code to the newest Klint
- Fixes isEmpty bug on Filters
2026-02-09 14:06:07 -05:00
Vitor Pamplona 710f15f790 - Fixes copyright using KDoc patterns instead of simpler comments
- Moves spotless and git-hooks to hidden folders
2026-02-09 13:06:41 -05:00
Vitor Pamplona 92d4654b20 Removes the memory counter methods because they are not the best way to measure the size in memory of these objects, since we intern strings all the time. 2026-01-14 16:49:11 -05:00
Vitor Pamplona 3d0b0c01b9 Finishes editing quartz event store readme 2026-01-14 15:36:32 -05:00
Vitor Pamplona adb2f48fb5 Updates event store readme 2026-01-14 15:29:13 -05:00
Vitor Pamplona ce01e8f70c moves keystore to commons to avoid unnecessary dependencies on Quartz 2026-01-07 11:09:45 -05:00
Vitor Pamplona 41cb143e0d Merge branch 'main' into nrobi144/desktop-phase1 2026-01-07 09:23:57 -05:00
nrobi144 fd83560852 key storage implementation 2026-01-06 17:08:28 +02:00
nrobi144 df9d648988 key storage spotless 2026-01-06 06:50:31 +02:00
nrobi144 4339247815 key storage 2026-01-06 06:49:59 +02:00
davotoula 0d923b5caa optimise imports 2026-01-04 12:19:00 +01:00
Vitor Pamplona d7888c57fa Creating additional configuration options and amplifying tests to a combination of all those options 2026-01-03 18:18:36 -05:00
Vitor Pamplona 7a34b8480e Fixes count not working for LIMIT queries 2026-01-02 17:22:18 -05:00
Vitor Pamplona 51f9fdd58c Adds a simple query to the count filter 2026-01-02 16:58:59 -05:00
Vitor Pamplona 989c63a717 Expose query plans with the current hasher 2026-01-02 16:57:49 -05:00
Vitor Pamplona 48e791c634 removes logs 2026-01-02 16:17:58 -05:00
Vitor Pamplona 307cff87e7 Adds more settings to pick different ways to build the SQL database 2026-01-02 14:54:30 -05:00
Vitor Pamplona 7c63d654f2 Inverts the name of the isFilledFilter function 2026-01-01 21:29:20 -05:00
Vitor Pamplona 291db1f30b duplicates kinds and pubkey on the tags table to take complex queries under 100 microseconds 2026-01-01 14:57:48 -05:00
Vitor Pamplona 238d4e0004 No need for the fts module anymore 2026-01-01 14:52:11 -05:00
Vitor Pamplona aac880c575 Range queries are not effective as the first argument, switching to kind, key, created_at index, which also almost invalidates the need for the Replaceable idx and is only kept for the unique key consistency 2026-01-01 12:51:43 -05:00
Vitor Pamplona 8affb2564b explains the fk index on tags 2026-01-01 12:49:12 -05:00
Vitor Pamplona b7c7eabf2a Explains limit index 2026-01-01 12:48:48 -05:00
Vitor Pamplona f48eba6a8e No need for this index since it will be covered by addressable_idx 2026-01-01 12:48:22 -05:00
Vitor Pamplona 307703cbb7 Explains ID index 2026-01-01 12:47:35 -05:00
Vitor Pamplona 9d67d5d6dc Implements a raw add on to the query builder 2026-01-01 12:37:44 -05:00
Vitor Pamplona 1978c8e17e Faster way of coding equals to null in the sql builder 2026-01-01 12:37:13 -05:00
Vitor Pamplona 507256e0dd Fixes Or builder 2026-01-01 12:36:26 -05:00
Vitor Pamplona 393366d9cc Adds size of the DB as a function to the lib 2025-12-31 18:41:20 -05:00