rust-nostr / nostr

Nostr protocol implementation, SDK and FFI
https://rust-nostr.org/
MIT License
417 stars 90 forks source link

Unable to get kind 3 events #209

Closed DanielUhlik closed 10 months ago

DanielUhlik commented 10 months ago

Describe the bug
Subscribing to kind 3 events does nothing or crashes without error message:

Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 24345 (Thread-6), pid 24268 (com.example.app)
Cmdline: com.example.app
pid: 24268, tid: 24345, name: Thread-6  >>> com.example.app <<<
      #01 pc 00000000006a038c  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #02 pc 00000000006a0380  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #03 pc 000000000069368c  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #04 pc 00000000006935f0  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #05 pc 0000000000693340  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #06 pc 0000000000692264  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #07 pc 000000000069309c  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #08 pc 00000000006b2af4  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #09 pc 0000000000343ca8  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #10 pc 00000000003d4c98  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #11 pc 0000000000353360  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #12 pc 0000000000357b50  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)
      #13 pc 0000000000695170  /data/app/~~Gc3wKV4pRoTy4oI36ohuaw==/com.example.app-zlyTtNmCyfh0i4084gdysA==/base.apk (offset 0xaff000)

To Reproduce

  1. start(): connect to relay, publish metadata event, subscribe to events
  2. addContact("any_npub"): create and publish kind 3 event

class NostrRepository @Inject constructor() : CoroutineScope { private val keys by lazy { Keys.generate() }

val TAG = "NostrRepository"

private val client by lazy {
    Client(keys)
}

fun getNpub(): String {
    return keys.publicKey().toBech32()
}

fun getPubKey(): PublicKey {
    return keys.publicKey()
}

var contacts = mutableListOf<Contact>()
val contactsChannel: Channel<List<Contact>> = Channel()

fun start() {
    client.addRelay(RELAY_URL)
    client.connect()
    listenEvents()
    subscribeContacts()

    val metadata = nostr_sdk.Metadata()
        .setName("Nostr user")
        .setDisplayName("Nostr user")
        .setAbout("Description")

     // Update metadata
    client.setMetadata(metadata)

    Log.i(TAG, "npub: ${getNpub()}")
}

fun listenEvents() {
    client.handleNotifications(object : HandleNotification {
        override fun handle(relayUrl: String, event: Event) {
            Log.i("NostrHandler", event.content())

            if (event.kind() == 3u.toULong()) {
                contacts.clear()
                contacts.addAll(event.tags().map {
                    val c = it.asEnum() as TagEnum.ContactList
                    Contact(PublicKey.fromHex(c.pk), c.relayUrl, c.alias)
                })

                launch {
                    contactsChannel.send(contacts)
                }
            }
        }

        override fun handleMsg(relayUrl: String, msg: RelayMessage) {
        }

    })
}

private fun subscribeContacts() {
    val filter = Filter().kind(3u).pubkey(getPubKey()
    client.subscribe(listOf(filter))    
}

fun addContact(npub: String) {
    val contact = Contact(PublicKey.fromBech32(npub))

    contacts.add(contact)

    val event = EventBuilder.setContactList(contacts).toEvent(keys)
    client.sendEvent(event)
}

private var job: Job = Job()
override val coroutineContext: CoroutineContext
    get() = Dispatchers.Default + job

}



**Expected behavior**  
1. After subscribing to existing user with follow list, trigger  callback `override fun handle(relayUrl: String, event: Event){}`.
2. After calling function `addContact("any_npub")` trigger callback `override fun handle(relayUrl: String, event: Event){}`.  

**Build environment**  
 - Library: io.github.rust-nostr:nostr-sdk
 - Version: 0.0.5
yukibtc commented 10 months ago

Hi, I'm not a kotlin dev but looking to the code seems that errors are not handled, so maybe the app crash for a malformed public key, timeouts or something else.

Are you able to add some try {} catch {} where needed? And log the errors to see what's wrong.

These are some of the methods that could return an error:

Currently there are 2 values in the TagEnum that can refer to p tag for contacts list: you have to check for both TagEnum.PubKey and TagEnum.ContactList. For next release I'll join them in a single one (TagEnum.PubKey).


At this line miss a parenthesis:

val filter = Filter().kind(3u).pubkey(getPubKey()

Filter().pubkey(..) search by p tag. If you need to filter by event author, use Filter().author(...).

client.getEventsOf subscribe and on EOSE close the subscription. If you need to keep open the subscription, use client.subscribe(). If you need to get events, but no need to wait for them, and handle them in client.handleNotifications, you can use reqEventsOf(...). It's like the getEventsOf (so close the subscription on EOSE) but spawn thread.


I started to write the book with all the docs for both kotlin and all the other supported langs. I hope to finish it soon.

DanielUhlik commented 10 months ago

Thank you, I can get follow list but I am still confused from some things. Kotlin docs will be helpful