导航栏

Home

  • wss://relay.damus.io
  • wss://nostr-pub.wellorder.net
  • wss://nostr.mom
  • wss://nostr.slothy.win
  • wss://relay.stoner.com
  • wss://nostr.einundzwanzig.space
  • wss://nos.lol
  • wss://relay.nostr.band
  • wss://no.str.cr
  • wss://nostr-relay.schnitzel.world
  • wss://relay.nostr.com.au
  • wss://knostr.neutrine.com
  • wss://nostr.nodeofsven.com
  • wss://nostr.vulpem.com
  • wss://nostr-verif.slothy.win
  • wss://relay.lexingtonbitcoin.org
  • wss://nostr-1.nbo.angani.co
  • wss://relay.wellorder.net
  • wss://nostr.easydns.ca
  • wss://relay.dwadziesciajeden.pl
  • wss://relay.orangepill.dev
  • wss://e.nos.lol
  • wss://ragnar-relay.com
  • wss://nostr.data.haus
  • wss://nostr.wine
  • wss://nostr.koning-degraaf.nl
  • wss://nostr.thank.eu
  • wss://relay.hamnet.io
  • wss://nostr.sidnlabs.nl
  • wss://nostr.inosta.cc
  • wss://nostr21.com
  • wss://nostr.ch3n2k.com
  • wss://relay.nostrview.com
  • wss://relay.nostromo.social
  • wss://offchain.pub
  • wss://relay.nostr.wirednet.jp
  • wss://nostr.l00p.org
  • wss://lightningrelay.com
  • wss://bitcoinmaximalists.online
  • wss://private.red.gb.net
  • wss://relay.nostrid.com
  • wss://relay.nostrcheck.me
  • wss://nostrelay.yeghro.site
  • wss://nostrue.com
  • wss://nostr.topeth.info
  • wss://nostr.bitcoiner.social
  • wss://nostr.spaceshell.xyz
  • wss://nostr.roundrockbitcoiners.com
  • wss://relay.nostrology.org
  • wss://nostr-dev.wellorder.net
  • wss://relay.snort.social
  • wss://nr.yay.so
  • wss://nostr.lu.ke
  • wss://atlas.nostr.land
  • wss://nostr.pjv.me
  • wss://brb.io
  • wss://eden.nostr.land
  • wss://nostr-verified.wellorder.net
  • wss://nostr.noones.com
  • wss://relay.nostr.nu
  • wss://nostr-relay.bitcoin.ninja
  • wss://paid.no.str.cr
  • wss://freespeech.casa
  • wss://bitcoiner.social
  • wss://nostr.1f52b.xyz
  • wss://nostr.sebastix.dev
  • wss://nostr.cizmar.net
  • wss://n.wingu.se
  • wss://nostr.bitcoinplebs.de
  • wss://nostr.corebreach.com
  • wss://nostr.tools.global.id
  • wss://xmr.usenostr.org
  • wss://at.nostrworks.com
  • wss://nostr.sovbit.host
  • wss://nostr.1sat.org
  • wss://mastodon.cloud/api/v1/streaming
  • wss://nostr.256k1.dev
  • wss://relay.beta.fogtype.com
  • wss://rsslay.ch3n2k.com
  • wss://relay.nostr.bg
  • wss://nostr.primz.org
  • wss://relay.johnnyasantos.com
  • wss://btc.klendazu.com
  • wss://slick.mjex.me
  • wss://nostr.yael.at
  • wss://nostr.lorentz.is
  • wss://relay.nostrified.org
  • wss://nostr.orangepill.dev
  • wss://relay.primal.net
  • wss://nostr.cercatrova.me
  • wss://nostr.swiss-enigma.ch
  • wss://nostr-relay.derekross.me
  • wss://puravida.nostr.land
  • wss://nostr.sectiontwo.org
  • wss://nostr.oxtr.dev
  • wss://relay.s3x.social
  • wss://relay.ryzizub.com
  • wss://nostr.liberty.fans
  • wss://nostr.frostr.xyz
  • wss://nostr.ginuerzh.xyz
  • wss://nostr.d11n.net
  • wss://nostr.semisol.dev
  • wss://misskey.io
  • wss://nostr.namek.link
  • wss://nostr.gruntwerk.org
  • wss://relay.nostr.wf
  • wss://nostr.land
  • wss://relay.mostr.pub
  • wss://relay.nostrplebs.com
  • wss://purplepag.es
  • wss://yestr.me
  • wss://relay.nostr.ai
  • wss://paid.nostrified.org
  • wss://nostr-02.dorafactory.org
  • wss://nostr.zbd.gg
  • wss://relay.hodl.ar
  • wss://relay.nostr.sc
  • wss://feeds.nostr.band/nostrhispano
  • wss://nostr.middling.mydns.jp
  • wss://nostr.portemonero.com
  • wss://search.nos.today
  • wss://relay.minds.com/nostr/v1/ws
  • wss://welcome.nostr.wine
  • wss://yabu.me
  • wss://nrelay.c-stellar.net
  • wss://nostrja-kari.heguro.com
  • wss://nostr-relay.app
  • wss://rly.nostrkid.com
  • wss://nostr.filmweb.pl
  • wss://relay.utxo.one
  • wss://nostr.strits.dk
  • wss://relay.poster.place
  • wss://nostr.mining.sc
  • wss://nostr.xmr.rocks
  • wss://ithurtswhenip.ee
  • wss://powrelay.xyz
  • wss://relay.vanderwarker.family
  • wss://wc1.current.ninja
  • wss://nostr.ingwie.me
  • wss://nostr.gleeze.com
  • wss://relay.nostrify.io
  • wss://relay2.nostrchat.io
  • wss://relay1.nostrchat.io
  • wss://relay.devstr.org
  • wss://relay.nostr.hu
  • wss://nostr.hifish.org
  • wss://nostr2.sanhauf.com
  • wss://nostrja-kari-nip50.heguro.com
  • wss://nostr.rikmeijer.nl
  • wss://nostrua.com
  • wss://relay.nsecbunker.com
  • wss://nostr.hekster.org
  • wss://nostr.schorsch.fans
  • wss://nostr.reelnetwork.eu
  • wss://nostr.hexhex.online
  • wss://relay.wavlake.com
  • wss://relay.nostr.lighting
  • wss://nostr.sagaciousd.com
  • wss://nostr.fbxl.net
  • wss://multiplextr.coracle.social
  • wss://nostril.cam
  • wss://nostr.btc-library.com
  • wss://relay.getalby.com/v1
  • wss://rss.nos.social
  • wss://nostr.overmind.lol
  • wss://relay.nostrcn.com
  • wss://nostr-01.yakihonne.com
  • wss://nostr.fort-btc.club
  • wss://relay.bitcoinpark.com
  • wss://nostr01.counterclockwise.io
  • wss://relap.orzv.workers.dev
  • wss://christpill.nostr1.com
  • wss://relay.verified-nostr.com
  • wss://nostr.sathoarder.com
  • wss://wbc.nostr1.com
  • wss://nostr.is-defs.fun
  • wss://nostr.heliodex.cf
  • wss://nostr.4liberty.one
  • wss://f7z.io
  • wss://relay.casualcrypto.date
  • wss://relay.notmandatory.org
  • wss://fiatjaf.com
  • wss://relay.despera.space
  • wss://bitstack.app
  • wss://nostr-relay.psfoundation.info
  • wss://purplerelay.com
  • wss://relay.orangepill.ovh
  • wss://nostr.rubberdoll.cc
  • wss://relay.ingwie.me
  • wss://soloco.nl
  • wss://nostr.dlsouza.lol
  • wss://relay.kamp.site
  • wss://nostr.heavyrubberslave.com
  • wss://relay.keychat.io
  • wss://relay.froth.zone
  • wss://nostr.bitcoinist.org
  • wss://nostr.cloud.vinney.xyz
  • wss://relay.momostr.pink
  • wss://nosdrive.app/relay
  • wss://nostrrelay.win
  • wss://nostr.8777.ch
  • wss://unhostedwallet.com
  • wss://21ideas.nostr1.com
  • wss://nostr.stakey.net
  • wss://nostr.sats.li
  • wss://relay.guggero.org
  • wss://relay.noswhere.com
  • wss://unostr.site
  • wss://pyramid.fiatjaf.com
  • wss://frens.nostr1.com
  • wss://creatr.nostr.wine
  • wss://140.f7z.io
  • wss://a.nos.lol
  • wss://directory.yabu.me
  • wss://hist.nostr.land
  • wss://nostr.dodge.me.uk
  • wss://privateisland.club
  • wss://relay.weloveit.info
  • wss://relay.magiccity.live
  • wss://nostr.notribe.net
  • wss://relay.westernbtc.com
  • wss://relay.siamstr.com
  • wss://groups.0xchat.com
  • wss://theforest.nostr1.com
  • wss://problematic.network
  • wss://us.purplerelay.com
  • wss://nostr1.daedaluslabs.io
  • wss://relay.noderunners.network
  • wss://relay.azzamo.net
  • wss://bevo.nostr1.com
  • wss://freelay.sovbit.host
  • wss://relay.sebdev.io
  • wss://inbox.nostr.wine
  • wss://ditto.puhcho.me/relay
  • wss://nostr.t-rg.ws
  • wss://multiplexer.huszonegy.world
  • wss://nostr.huszonegy.world
  • wss://nostr.jcloud.es
  • wss://nostr.thurk.org
  • wss://dev-relay.kube.b-n.space
  • wss://relay.nos.social
  • wss://ditto.slothy.win/relay
  • wss://nostr.hashi.sbs
  • wss://paid.relay.vanderwarker.family
  • wss://nostr.javi.space
  • wss://gleasonator.dev/relay
  • wss://bucket.coracle.social
  • wss://relay.nsec.app
  • wss://relay.sepiropht.me
  • wss://nostr.kungfu-g.rip
  • wss://hotrightnow.nostr1.com
  • wss://relay.artx.market
  • wss://nfrelay.app
  • wss://relay.notoshi.win
  • wss://relay.highlighter.com
  • wss://relay.geyser.fund
  • wss://relay.minibits.cash
  • wss://nostr.petrkr.net/strfry
  • wss://n.ok0.org
  • wss://greensoul.space
  • wss://nostr-02.yakihonne.com
  • wss://nostr-03.dorafactory.org
  • wss://vitor.nostr1.com
  • wss://relay.lax1dude.net
  • wss://relay.zhoushen929.com
  • wss://relay.oke.minds.io/nostr/v1/ws
  • wss://strfry.corebreach.com
  • wss://relay.bitdevs.tw
  • wss://nostr.btczh.tw
  • wss://nostrich.adagio.tw
  • wss://nostr.zoel.network
  • wss://nostr.lifeonbtc.xyz
  • wss://nostr.se7enz.com
  • wss://thecitadel.nostr1.com
  • wss://mleku.nostr1.com
  • wss://nostr2.daedaluslabs.io
  • wss://fiatjaf.nostr1.com
  • wss://nostr.daedaluslabs.io
  • wss://xmr.ithurtswhenip.ee
  • wss://cellar.nostr.wine
  • wss://rkgk.moe
  • wss://nostr.self-determined.de
  • wss://nostr.gerbils.online
  • wss://jingle.carlos-cdb.top
  • wss://carlos-cdb.top
  • wss://bostr.online
  • wss://relays.diggoo.com
  • wss://jp.purplerelay.com
  • wss://ir.purplerelay.com
  • wss://me.purplerelay.com
  • wss://nostr.0x7e.xyz
  • wss://nostr.reckless.dev
  • wss://relay.nostr.net
  • wss://relay.fountain.fm
  • wss://v1250.planz.io/nostr
  • wss://relay.13room.space
  • wss://relay.usefusion.ai
  • wss://ae.purplerelay.com
  • wss://njump.me
  • wss://au.purplerelay.com
  • wss://in.purplerelay.com
  • wss://nosflare.plebes.fans
  • wss://nostr.at
  • wss://bostr.bitcointxoko.com
  • wss://nostria.space
  • wss://nostr.searx.is
  • wss://test.nfrelay.app
  • wss://relay.fanfares.io
  • wss://relay.varke.eu
  • wss://relay.nostr.jabber.ch
  • wss://relay.nostpy.lol
  • wss://relay.camelus.app
  • wss://nostr.myshosholoza.co.za
  • wss://nostr.ussenterprise.xyz
  • wss://nostr.dbtc.link
  • wss://ftp.halifax.rwth-aachen.de/nostr
  • wss://tw.purplerelay.com
  • wss://eu.purplerelay.com
  • wss://relay.benthecarman.com
  • wss://fabian.nostr1.com
  • wss://staging.yabu.me
  • wss://nostr.dmgd.monster
  • wss://testnet.plebnet.dev/nostrrelay/1
  • wss://hivetalk.nostr1.com
  • wss://relay.lawallet.ar
  • wss://relay.piazza.today
  • wss://relay.pleb.to
  • wss://orangepiller.org
  • wss://nostr.lopp.social
  • wss://ch.purplerelay.com
  • wss://loli.church
  • wss://adre.su
  • wss://misskey.04.si
  • wss://cache2.primal.net/v1
  • wss://relay.sincensura.org
  • wss://relay.moinsen.com
  • wss://relay.freeplace.nl
  • wss://cache1.primal.net/v1
  • wss://nostr.openordex.org
  • wss://rly.bopln.com
  • wss://relay.0v0.social
  • wss://nostr.psychoet.nexus
  • wss://relay.nostrr.de
  • wss://us.nostr.land
  • wss://srtrelay.c-stellar.net
  • wss://lnbits.papersats.io/nostrclient/api/v1/relay
  • wss://strfry.chatbett.de
  • wss://relay.nquiz.io
  • wss://nostr.plantroon.com
  • wss://nostr.jfischer.org
  • wss://relay.corpum.com
  • wss://relay.bostr.online
  • wss://lunchbox.sandwich.farm
  • wss://nr.rosano.ca
  • wss://nostr.happytavern.co
  • wss://novoa.nagoya
  • wss://misskey.takehi.to
  • wss://relay.satoshidnc.com
  • wss://nostr.novacisko.cz
  • wss://nsrelay.assilvestrar.club
  • wss://nostr.atitlan.io
  • wss://relay.livefreebtc.dev
  • wss://nostr.tavux.tech
  • wss://nostr.girino.org
  • wss://merrcurrup.railway.app
  • wss://nostr-dev.zbd.gg
  • wss://submarin.online
  • wss://social.camph.net
  • wss://relay.nostrich.cc
  • wss://relay.lumina.rocks
  • wss://profiles.nostr1.com
  • wss://rebelbase.social/relay
  • wss://support.nostr1.com
  • wss://relay.dev.bdw.to
  • wss://ca.purplerelay.com
  • wss://nostr.bitcoinvn.io
  • wss://auth.nostr1.com
  • wss://custom.fiatjaf.com
  • wss://hub.nostr-relay.app
  • wss://nostr.babyshark.win
  • wss://echo.websocket.org
  • wss://nostr.kosmos.org
  • wss://polnostr.xyz
  • wss://relay.refinery.coracle.tools
  • wss://user.kindpag.es
  • wss://nostr.hashbang.nl
  • wss://czas.live
  • wss://chorus.pjv.me
  • wss://relay.agorist.space
  • wss://bostr.cx.ms
  • wss://relay.nostrhub.fr
  • wss://groups.fiatjaf.com
  • wss://hodlbod.coracle.tools
  • wss://hk.purplerelay.com
  • wss://lnbits.satoshibox.io/nostrclient/api/v1/relay
  • wss://relay.cosmicbolt.net
  • wss://nostr.drafted.pro
  • wss://nostr.a2x.pub
  • wss://bostr.lightningspore.com
  • wss://nostr.intrepid18.com
  • wss://de.purplerelay.com
  • wss://obiurgator.thewhall.com
  • wss://nostr.madco.me
  • wss://relay.braydon.com
  • wss://nostr-relay.algotech.io
  • wss://relay.unknown.cloud
  • wss://relay.gems.xyz
  • wss://longhorn.bgp.rodeo
  • wss://notes.miguelalmodo.com
  • wss://onlynotes.lol
  • wss://relay.tagayasu.xyz
  • wss://relay.zone667.com
  • wss://nostr-relay.sn-media.com
  • wss://relay.mostro.network
  • wss://nostr.polyserv.xyz
  • wss://n3r.xyz
  • wss://relay5.bitransfer.org
  • wss://brisceaux.com
  • wss://nostr.faust.duckdns.org
  • wss://satellite.hzrd149.com
  • wss://gnost.faust.duckdns.org
  • wss://relay.jerseyplebs.com
  • wss://nostr.cxplay.org
  • wss://nostr.polonkai.eu
  • wss://libretechsystems.nostr1.com
  • wss://nostr.pailakapo.com
  • wss://relay.alex71btc.com
  • wss://cfrelay.puhcho.workers.dev
  • wss://kiwibuilders.nostr21.net
  • wss://nostr3.daedaluslabs.io
  • wss://relay1.xfire.to:
  • wss://nostr.brackrat.com
  • wss://relay.satlantis.io
  • wss://relay.test.nquiz.io
  • wss://relay.illuminodes.com
  • wss://relay.arrakis.lat
  • wss://cfrelay.haorendashu.workers.dev
  • wss://core.btcmap.org/nostrrelay/relay
  • wss://junxingwang.org
  • wss://relay2.angor.io
  • wss://relaypag.es
  • wss://nostr.skitso.business
  • wss://history.nostr.watch
  • wss://relay.oh-happy-day.xyz
  • wss://invillage-outvillage.com
  • wss://nostr-relay.cbrx.io
  • wss://tigs.nostr1.com
  • wss://misskey.design
  • wss://relay.nostrainsley.coracle.tools
  • wss://relay.cxplay.org
  • wss://relay.angor.io
  • wss://nostr.tbai.me:592
  • wss://strfry.iris.to
  • wss://orangesync.tech
  • wss://nostr.chaima.info
  • wss://relay.minibolt.info
  • wss://jingle.nostrver.se
  • wss://kr.purplerelay.com
  • wss://fl.purplerelay.com
  • wss://relay.chontit.win
  • wss://nostr.bilthon.dev
  • wss://relay.vengeful.eu
  • wss://dtonon.nostr1.com
  • wss://relay.gasteazi.net
  • wss://us.nostr.wine
  • wss://frjosh.nostr1.com
  • wss://relay.staging.geyser.fund
  • wss://nostr.yuhr.org
  • wss://relay.mattybs.lol
  • wss://sushi.ski
  • wss://relay.unsupervised.online
  • wss://nostr.bit4use.com
  • wss://prl.plus
  • wss://news.nos.social
  • wss://airchat.nostr1.com
  • wss://nortis.nostr1.com
  • wss://adeptus.cwharton.com
  • wss://relay.mycelium.social
  • wss://node.coincreek.com/nostrclient/api/v1/relay
  • wss://nostr2.girino.org
  • wss://relay.s-w.art
  • wss://nerostr.girino.org
  • wss://uk.purplerelay.com
  • wss://bostr.erechorse.com
  • wss://eostagram.com
  • wss://relay.coinos.io
  • wss://sendit.nosflare.com
  • wss://relay.nostraddress.com
  • wss://nostrelites.org
  • wss://wot.nostr.party
  • wss://wot.utxo.one
  • wss://haven.cyberhornet.net
  • wss://relay.customkeys.de
  • wss://relay.groups.nip29.com
  • wss://relay29.notoshi.win
  • wss://nostr.2h2o.io
  • wss://relay.nostriot.com
  • wss://relay.lem0n.cc
  • wss://relay.b1t.beer
  • wss://rocky.nostr1.com
  • wss://wot.sovbit.host
  • wss://relay.sovereign.app
  • wss://zap.watch
  • wss://zorrelay.libretechsystems.xyz
  • wss://sorrelay.libretechsystems.xyz
  • wss://mailbox.mw.leastauthority.com/v1
  • wss://memrelay.girino.org
  • wss://relay.lnfi.network
  • wss://wot.girino.org
  • wss://labour.fiatjaf.com
  • wss://wot.codingarena.top
  • wss://relay.nostrdice.com
  • wss://nostr.azzamo.net
  • wss://wot.azzamo.net
  • wss://wot.nostr.sats4.life
  • wss://wot.nostr.net
  • wss://api.freefrom.space/v1/ws
  • wss://wheat.happytavern.co
  • wss://chorus.bonsai.com
  • wss://strfry.bonsai.com
  • wss://wot.sebastix.social
  • wss://inner.sebastix.social
  • wss://haven.accioly.social
  • wss://relay.notestack.com
  • wss://relay.sigit.io
  • wss://satsage.xyz
  • wss://nostr.noderunners.network
  • wss://chronicle.puhcho.me
  • wss://haven.puhcho.me
  • wss://haven.calva.dev/inbox
  • wss://dergigi.nostr1.com
  • wss://wons.calva.dev
  • wss://thebarn.nostr1.com
  • wss://nostr.grooveix.com
  • wss://relay.rodbishop.nz/inbox
  • wss://travis-shears-nostr-relay-v2.fly.dev
  • wss://nostr.sprovoost.nl
  • wss://nostr.x0f.org
  • wss://bostr.syobon.net
  • wss://art.nostrfreaks.com
  • wss://cobrafuma.com/relay
  • wss://alru07.nostr1.com
  • wss://relay.nostrfreedom.net/outbox
  • wss://aplaceinthesun.nostr1.com
  • wss://relay.flirtingwithbitcoin.com
  • wss://plebone.nostr1.com
  • wss://cfrelay.snowcait.workers.dev
  • wss://thewritingdesk.nostr1.com
  • wss://relay.botev.sv
  • wss://relay.degmods.com
  • wss://seth.nostr1.com
  • wss://untreu.me
  • wss://agentorange.nostr1.com
  • wss://reimagine.nostr1.com
  • wss://nostr.takasaki.dev
  • wss://nostr.coincrowd.fund
  • wss://bnc.netsec.vip
  • wss://nostr.community.ath.cx
  • wss://nostr.cltrrd.us
  • wss://relay.xeble.me
  • wss://no.netsec.vip
  • wss://strfry.shock.network
  • wss://relay.8333.space
  • wss://relay02.lnfi.network
  • wss://relay.lightning.gdn
  • wss://nostr.cypherpunk.today
  • wss://relay.nostrfreaks.com
  • wss://relay.shuymn.me
  • wss://haven.eternal.gdn
  • wss://cyberspace.nostr1.com
  • wss://nostr-rs-relay.dev.fedibtc.com
  • wss://relay.das.casa
  • wss://ursin.nostr1.com
  • wss://monitorlizard.nostr1.com
  • wss://wot.shaving.kiwi
  • wss://relay.cyphernomad.com
  • wss://nostr.extrabits.io
  • wss://relay.jellyfish.land
  • wss://wot.tealeaf.dev
  • wss://chorus.tealeaf.dev
  • wss://haven.tealeaf.dev/inbox
  • wss://h.codingarena.top/inbox
  • wss://relay.goodmorningbitcoin.com
  • wss://wot.zacoos.com
  • wss://relay.shawnyeager.com/chat
  • wss://proxy0.siamstr.com
  • wss://articles.layer3.news
  • wss://relay.hs.vc
  • wss://chronicle.dtonon.com
  • wss://wot.dtonon.com
  • wss://relay.stens.dev
  • wss://social.protest.net/relay
  • wss://relay.patrickulrich.com/inbox
  • wss://relay.davidebtc.me
  • wss://relay.dev.ntech.it
  • wss://chronicle.dev.ntech.it
  • wss://nostr.bitpunk.fm
  • wss://lnvoltz.com/nostrrelay/n49jzjytb
  • wss://ghost.dolu.dev
  • wss://thebarn.nostrfreaks.com
  • wss://niel.nostr1.com
  • wss://adoringcardinal1.lnbits.com/nostrrelay/test-relay
  • wss://nostr.thebiglake.org
  • wss://wot.relay.vanderwarker.family
  • wss://haven.girino.org
  • wss://pow.hzrd149.com
  • wss://nostr-news.nostr1.com
  • wss://thewildhustle.nostr1.com
  • wss://nostr.sats.coffee
  • wss://dikaios1517.nostr1.com
  • wss://nostr4.daedaluslabs.io
  • wss://relay.calders.us
  • wss://nostr.mikoshi.de
  • wss://relay.nuts.cash
  • wss://brightlights.nostr1.com
  • wss://darknights.nostr1.com
  • wss://relay.chrisatmachine.com
  • wss://nostr.agentcampfire.com
  • wss://nostr.me/relay
  • wss://relay.nostr.watch
  • wss://dwebcamp.nos.social
  • wss://nostr.1312.media
  • wss://nostr.phauna.org
  • wss://henhouse.social/relay
  • wss://nostr.neilalexander.dev
  • wss://nip13.girino.org
  • wss://tijl.xyz
  • wss://relay.rengel.org
  • wss://relay.stewlab.win
  • wss://relay.badgr.digital
  • wss://relay.crbl.io
  • wss://rl.baud.one
  • wss://relay.axeldolce.xyz
  • wss://nip85.nostr.band
  • wss://antisocial.nostr1.com
  • wss://relay.isphere.lol
  • wss://cl4.tnix.dev
  • wss://nostr.dl3.dedyn.io
  • wss://nostr.camalolo.com
  • wss://hayloo.nostr1.com
  • wss://nostr.schneimi.de
  • wss://wostr.hexhex.online
  • wss://pareto.nostr1.com
  • wss://nostr.pareto.space
  • wss://relay.utih.net
  • wss://relay.lifpay.me
  • wss://david.nostr1.com
  • wss://haven.ciori.net
  • wss://bonifatius.nostr1.com
  • wss://pay.thefockinfury.wtf/nostrrelay/1
  • wss://relay.xplbzx.uk
  • wss://nostr.tac.lol
  • wss://btcpay2.nisaba.solutions/nostr
  • wss://relay.bitcoinschool.nl
  • wss://dev-relay.lnfi.network
  • wss://relay.netstr.io
  • wss://freespeech.social/relay
  • wss://straylight.cafe/relay
  • wss://nostr-relay01.redscrypt.org:48443
  • wss://relay.devvul.com
  • wss://relay.bitcoinveneto.org
  • wss://relay.shop21.dk
  • wss://nostr.mtrj.cz
  • wss://relay.jthecodemonkey.xyz
  • wss://devapi.freefrom.space/v1/ws
  • wss://aaa-api.freefrom.space/v1/ws
  • wss://nostr.rosenbaum.se
  • wss://fido-news.z7.ai
  • wss://stratum.libretechsystems.xyz
  • wss://tamby.mjex.me
  • wss://nostr.cottongin.xyz
  • wss://wot.eminence.gdn
  • wss://hi.myvoiceourstory.org
  • wss://nostr.red5d.dev
  • wss://relay-testnet.k8s.layer3.news
  • wss://nostr.pistaum.com
  • wss://relay-nwc.rizful.com/v1
  • wss://nostrum.satoshinakamoto.win
  • wss://eupo43gj24.execute-api.us-east-1.amazonaws.com/test
  • wss://backup.keychat.io
  • wss://relay.openbalance.app
  • wss://nostr.jonmartins.com
  • wss://social.proxymana.net
  • wss://nostr-pr02.redscrypt.org
  • wss://nostr-pr03.redscrypt.org
  • wss://nostrelay.memory-art.xyz
  • wss://promenade.fiatjaf.com
  • wss://inbox.azzamo.net
  • wss://premium.primal.net
  • wss://nostr.timegate.co
  • wss://team-relay.pareto.space
  • wss://relay.dariccoin.me
  • wss://relay.dannymorabito.com/inbox
  • wss://nostr.lojong.info
  • wss://relay.transtoad.com
  • wss://cfrelay.royalgarter.workers.dev
  • wss://nostr-rs-relay-ishosta.phamthanh.me
  • wss://nostr.rblb.it:7777
  • wss://fiatrevelation.nostr1.com
  • wss://sources.nostr1.com
  • wss://nostr-pr04.redscrypt.org
  • wss://relay.nostronautti.fi
  • wss://moonboi.nostrfreaks.com
  • wss://mats-techno-gnome-ca.trycloudflare.com
  • wss://nostr.d3id.xyz/relay
  • wss://nostr.holbrook.no
  • wss://logen.btcforplebs.com
  • wss://relay.nostrtalk.org
  • wss://community.proxymana.net
  • wss://misskey.gothloli.club
  • wss://mleku.realy.lol
  • wss://relay.maiqr.app
  • wss://relay.tv-base.com
  • wss://relay.rkus.se
  • wss://relay.snotr.nl:49999
  • wss://relay.brightbolt.net/inbox
  • wss://magic.nostr1.com
  • wss://null.spdns.eu
  • wss://nostr.itdestro.cc
  • wss://nostrrelay.taylorperron.com
  • wss://nostr.tegila.com.br
  • wss://stage.mosavi.xyz/v1/ws
  • wss://eclipse.pub/relay
  • wss://relay.asthroughfire.com
  • wss://relay.nostrarabia.com
  • wss://news.utxo.one
  • wss://relay.stream.labs.h3.se
  • wss://mls.akdeniz.edu.tr/nostr
  • wss://asia.azzamo.net
  • wss://tollbooth.stens.dev
  • wss://nostrelay.yeghro.com
  • wss://nostrich.zonemix.tech
  • wss://relay.chakany.systems
  • wss://45.135.180.104
  • wss://relay.mwaters.net
  • wss://kitchen.zap.cooking
  • wss://basedpotato.nostr1.com
  • wss://nostr1.jpegslangah.com
  • wss://primus.nostr1.com
  • wss://wot.mwaters.net
  • wss://prod.mosavi.io/v1/ws
  • wss://bots.utxo.one
  • wss://nostr.caramboo.com
  • wss://9yo.punipoka.pink
  • wss://nostr.trepechov.com
  • wss://stg.nostpy.lol
  • wss://nostr.ovia.to
  • wss://riley.timegate.co
  • wss://willow.timegate.co
  • wss://relay.olas.app
  • wss://social.olsentribe.fyi
  • wss://relay.arx-ccn.com
  • wss://zaplab.nostr1.com
  • wss://hax.reliefcloud.com
  • wss://nostrrelay.blocktree.cc
  • wss://hole.v0l.io
  • wss://nostr.phuture.sk
  • wss://cc3d.nostr1.com
  • wss://coop.nostr1.com
  • wss://synalysis.nostr1.com
  • wss://nostr.luisschwab.net
  • wss://relay.fr13nd5.com
  • wss://relay.nostrfy.io
  • wss://relay.vaporware.network
  • wss://relay.mzm.app
  • wss://nostr.felixzieger.de
  • wss://nostr.spicyz.io
  • wss://relay.pre-alfa.iz-collaborator.com
  • wss://bunker.vanderwarker.family
  • wss://ltgnetwork.nostr1.com
  • wss://relay.bullishbounty.com
  • wss://dev.coracle.tools
  • wss://relay04.lnfi.network
  • wss://jellyfish.land
  • wss://relay03.lnfi.network
  • wss://rtson.onrender.com
  • wss://nostr.1sat.store
  • wss://v2.fly.dev
  • wss://communities.nos.social
  • wss://vidono.apps.slidestr.net
  • wss://nostrboss.com
  • wss://aegis.utxo.one
  • wss://data.relay.vanderwarker.family
  • wss://relay.marc26z.com
  • wss://relay-dev.netstr.io
  • wss://relay.danieldaquino.me
  • wss://aegis.relayted.de
  • wss://relay.nostrverified.fyi
  • wss://n.posto.us.kg
  • wss://relay.hook.cafe
  • wss://aegis.relaynostr.xyz
  • wss://nostrapps.com
  • wss://nostr.douglascruz.com.br
  • wss://wot.relayted.de
  • wss://inbox.mycelium.social
  • wss://relay.d11n.net
  • wss://haven.relayted.de
  • wss://free.relayted.de
  • wss://relay.zapstore.dev
  • wss://chat.mihhdu.org
  • wss://bridge.duozhutuan.com
  • wss://relay.evanverma.com
  • wss://relay.nostrdvm.com
  • wss://nostr.joomaen.top
  • wss://nostr.235421.xyz
  • wss://nostr.bitcoinsult.de
  • wss://nostrelay.circum.space
  • wss://relay1.plor.dev
  • wss://relayrs.notoshi.win
  • wss://fenrir-s.notoshi.win
  • wss://bostr.azzamo.net
  • wss://nos.zct-mrl.com
  • wss://skeme.vanderwarker.family
  • @ Cryptape
    2025-05-26 09:13:31

    This doc keeps track of my experience diagnosing CKB’s unstable tests. While the issue is unlikely to affect most application developers on CKB, it may be of interest to Rust developers working on complex multithreaded systems or those curious about advanced debugging techniques.

    A PR has been created in CKB to fix tests per discovery documented in this doc.


    Every now and then, when running CKB’s test, you might see errors like:

    • pthread lock: Invalid argument

    • terminate called without an active exception

    These failures occur randomly (~5% of test runs) and are difficult to reproduce. I suspected the issue might be related to ckb-sync, and this post documents the debugging journey, tools used, and eventual fix.

    Reproducing the Issue

    Testing with cargo nextest

    Cargo-nextest is a test runner for Rust projects. Based on the actual command executed by make test, I could piece together the following command:

    bash $ cargo nextest run --features with_sentry --no-fail-fast \ --hide-progress-bar --success-output immediate-final \ --failure-output immediate-final -p ckb-sync

    However, this command would fail to build. It seems that running the ckb-sync package alone, ckb-sync is missing a dev-time feature dependency, like the following line:

    toml ckb-tx-pool = { workspace = true, features = ["internal"] }

    After adding this line, the above command would succeed in building and proceed to run the tests from ckb-sync package.

    On my machine, the test fails after ~20 iterations (5% failure rate) with either pthread lock: Invalid argument or terminate called without an active exception.

    Deterministic Debugging with rr Multithreaded Failures

    rr is a lightweight debugging tool for recording, replaying and debugging execution of applications (trees of processes and threads)

    records a program’s execution once and allows deterministic replay of that exact run multiple times. By capturing all sources of nondeterminism (including thread scheduling), rr enables reliable debugging of multithreaded failures, making it especially useful for diagnosing flaky or intermittent test issues in complex systems like CKB.

    Installation

    Install rr per the instructions.

    Note: rr has specific requirements on OS and your CPU, refer to the docs for more details.

    To limit the traces generated by rr, I will focus on one particular test tests::sync_shared::test_insert_parent_unknown_block. From my local experiments, this test might throw the above mentioned errors.

    Set rr as the cargo runner

    bash $ export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="/home/ubuntu/rr-obj/bin/rr record"

    The rr binary on my machine is installed to /home/ubuntu/rr-obj/bin/rr, you might want to adjust this accordingly.

    Run the test repeatedly

    Then we can keep running this command until one of the errors shows up:

    bash $ cargo nextest run --features with_sentry --no-fail-fast \\ --hide-progress-bar --success-output immediate-final \\ --failure-output immediate-final -p ckb-sync \\ tests::sync_shared::test_insert_parent_unknown_block

    As each test run would accumulate rr traces and test data, you might use the following command between test runs to clean up all those data:

    bash $ rm -rf ~/.local/share/rr/ /tmp/ckb-tmp-* /tmp/.tmp*

    It’s not hard to write a script that keeps running the test until it fails:

    ```bash

    !/usr/bin/env bash

    set -x

    This script simply runs the test repeatedly until faliure happens

    unset CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER while true; do cargo nextest run --features with_sentry --no-fail-fast \ --hide-progress-bar --success-output immediate-final \ --failure-output immediate-final -p \ ckb-sync tests::sync_shared::test_insert_parent_unknown_block RETURN_CODE=$? rm -rf /tmp/ckb-tmp- /tmp/.tmp

    if [[ "$RETURN_CODE" -ne 0 ]]; then echo "Failed with $RETURN_CODE" exit $RETURN_CODE fi done ```

    Or try this one that takes rr into account:

    ```bash

    !/usr/bin/env bash

    set -x

    RR="${RR:-/home/ubuntu/rr-obj/bin/rr}"

    This script runs the test wrapped with rr, so when failure happens,

    you can replay the failed test using rr

    export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="$RR record" while true; do cargo nextest run --features with_sentry --no-fail-fast \ --hide-progress-bar --success-output immediate-final \ --failure-output immediate-final -p \ ckb-sync tests::sync_shared::test_insert_parent_unknown_block RETURN_CODE=$? rm -rf /tmp/ckb-tmp- /tmp/.tmp

    if [[ "$RETURN_CODE" -ne 0 ]]; then echo "Failed with $RETURN_CODE, use $RR replay to rerun the failure!" exit $RETURN_CODE fi

    rm -rf ~/.local/share/rr done ```

    For some reason, the test tends to fail more often running under rr on my machine, my guess is that rr alters the behavior of multi-thread scheduling. Or maybe rr picks a different execution path compared to what is normally tested in our daily development.

    Failures Observed

    Error Case: pthread lock: Invalid argument

    With enough runs, one of the test outputs might look like following:

    ``bash $ cargo nextest run --features with_sentry --no-fail-fast --hide-progress-bar --success-output immediate-final --failure-output immediate-final -p ckb-sync tests::sync_shared::test_insert_parent_unknown_block Finishedtestprofile [unoptimized + debuginfo] target(s) in 0.24s info: using target runner/home/ubuntu/rr-obj/bin/rr recorddefined by environment variableCARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER` ──────────── Nextest run ID d8f86415-500a-4b18-9093-cd21a656013a with nextest profile: default Starting 1 test across 1 binary (68 tests skipped) SIGABRT [ 2.098s] ckb-sync tests::sync_shared::test_insert_parent_unknown_block ──── STDOUT: ckb-sync tests::sync_shared::test_insert_parent_unknown_block

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.93s

    ──── STDERR: ckb-sync tests::sync_shared::test_insert_parent_unknown_block pthread lock: Invalid argument

    ──────────── Summary [ 2.099s] 1 test run: 0 passed, 1 failed, 68 skipped SIGABRT [ 2.098s] ckb-sync tests::sync_shared::test_insert_parent_unknown_block ──── STDOUT: ckb-sync tests::sync_shared::test_insert_parent_unknown_block

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.93s

    ──── STDERR: ckb-sync tests::sync_shared::test_insert_parent_unknown_block pthread lock: Invalid argument

    error: test run failed ```

    In this case, you can find that rr has generated traces:

    bash $ ls -lh ~/.local/share/rr/ total 12K drwxrwx--- 2 ubuntu ubuntu 4.0K Apr 27 05:55 ckb_sync-a645bdacec5c2bf3-0 drwxrwx--- 2 ubuntu ubuntu 4.0K Apr 27 05:55 ckb_sync-a645bdacec5c2bf3-1 drwxrwx--- 2 ubuntu ubuntu 4.0K Apr 27 05:55 ckb_sync-a645bdacec5c2bf3-2 -rw------- 1 ubuntu ubuntu 8 Apr 27 05:55 cpu_lock lrwxrwxrwx 1 ubuntu ubuntu 27 Apr 27 05:55 latest-trace -> ckb_sync-a645bdacec5c2bf3-2

    I run the clean command above between each run, so you’ll only see three traces here. The last one corresponds to the actual failing test, while the first two might be bookkeeping runs of nextest. If you didn’t run the clean command, there could be more traces.

    Now you can repeat the failed case:

    ```bash $ ~/rr-obj/bin/rr replay GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git Copyright (C) 2024 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: https://www.gnu.org/software/gdb/bugs/. Find the GDB manual and other documentation resources online at: http://www.gnu.org/software/gdb/documentation/.

    For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /home/ubuntu/.local/share/rr/ckb_sync-a645bdacec5c2bf3-2/mmap_hardlink_4_ckb_sync-a645bdacec5c2bf3... warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts of file /home/ubuntu/.local/share/rr/ckb_sync-a645bdacec5c2bf3-2/mmap_hardlink_4_ckb_sync-a645bdacec5c2bf3. Use `info auto-load python-scripts [REGEXP]' to list them. Remote debugging using 127.0.0.1:7932 Reading symbols from /lib64/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/1c/8db5f83bba514f8fd5f1fb6d7be975be1bb855.debug... BFD: warning: system-supplied DSO at 0x6fffd000 has a section extending past end of file

    This GDB supports auto-downloading debuginfo from the following URLs: https://debuginfod.ubuntu.com Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. Downloading separate debug info for system-supplied DSO at 0x6fffd000 0x00007ce375295540 in _start () from /lib64/ld-linux-x86-64.so.2 (rr) ```

    rr starts a gdb session for the ckb-sync test. We can use c to continue to run the test:

    ```bash (rr) c Continuing. Downloading separate debug info for /lib/x86_64-linux-gnu/libstdc++.so.6

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.93s

    pthread lock: Invalid argument [New Thread 72541.73153] [New Thread 72541.72544] [New Thread 72541.73028] [New Thread 72541.73029] [New Thread 72541.73082] [New Thread 72541.73109] [New Thread 72541.73111] [New Thread 72541.73113] [New Thread 72541.73114] [New Thread 72541.73115] [New Thread 72541.73118] [New Thread 72541.73119] [New Thread 72541.73152] [New Thread 72541.73156] [New Thread 72541.73157]

    Thread 2 received signal SIGABRT, Aborted. [Switching to Thread 72541.73153] Download failed: Invalid argument. Continuing without source file ./nptl/./nptl/pthread_kill.c. __pthread_kill_implementation (no_tid=0, signo=6, threadid=) at ./nptl/pthread_kill.c:44 warning: 44 ./nptl/pthread_kill.c: No such file or directory (rr) ```

    And use bt to print stack trace when the error happens:

    bash (rr) bt

    As the stack trace is quite long, I’m posting a screenshot instead:

    image

    We can track the failure to this line:

    rust ffi::rocksdb_optimistictransactiondb_close(self.inner);

    For some reason, closing an optimistic transaction DB triggers the failure. But the cause is unclear. Just a guess: what should a proper shutdown process in RocksDB look like? Is simply closing the DB instance enough?

    As long as you don’t run rr record ... or rerun the test, you can use rr replay to rerun the failed test as many times as needed. Or, you can use rr replay ~/.local/share/rr/ckb_sync-a645bdacec5c2bf3-2 to manually pick the trace of the failure test. This way, you can continue running more rr record ....

    Error Case: terminate called without an active exception

    Enough runs of the test also reveal another error:

    ``bash $ cargo nextest run --features with_sentry --no-fail-fast --hide-progress-bar --success-output immediate-final --failure-output immediate-final -p ckb-sync tests::sync_shared::test_insert_parent_unknown_block Finishedtestprofile [unoptimized + debuginfo] target(s) in 0.24s info: using target runner/home/ubuntu/rr-obj/bin/rr recorddefined by environment variableCARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER` ──────────── Nextest run ID 2aa60494-7933-4b99-9f5f-cdced260411a with nextest profile: default Starting 1 test across 1 binary (68 tests skipped) SIGABRT [ 2.083s] ckb-sync tests::sync_shared::test_insert_parent_unknown_block ──── STDOUT: ckb-sync tests::sync_shared::test_insert_parent_unknown_block

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.92s

    ──── STDERR: ckb-sync tests::sync_shared::test_insert_parent_unknown_block terminate called without an active exception

    ──────────── Summary [ 2.084s] 1 test run: 0 passed, 1 failed, 68 skipped SIGABRT [ 2.083s] ckb-sync tests::sync_shared::test_insert_parent_unknown_block ──── STDOUT: ckb-sync tests::sync_shared::test_insert_parent_unknown_block

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.92s

    ──── STDERR: ckb-sync tests::sync_shared::test_insert_parent_unknown_block terminate called without an active exception

    error: test run failed ```

    We can also use rr to jump into a gdb session:

    ```bash $ ~/rr-obj/bin/rr replay GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git Copyright (C) 2024 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: https://www.gnu.org/software/gdb/bugs/. Find the GDB manual and other documentation resources online at: http://www.gnu.org/software/gdb/documentation/.

    For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /home/ubuntu/.local/share/rr/ckb_sync-a645bdacec5c2bf3-2/mmap_hardlink_4_ckb_sync-a645bdacec5c2bf3... warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts of file /home/ubuntu/.local/share/rr/ckb_sync-a645bdacec5c2bf3-2/mmap_hardlink_4_ckb_sync-a645bdacec5c2bf3. Use `info auto-load python-scripts [REGEXP]' to list them. Remote debugging using 127.0.0.1:9252 Reading symbols from /lib64/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/1c/8db5f83bba514f8fd5f1fb6d7be975be1bb855.debug... BFD: warning: system-supplied DSO at 0x6fffd000 has a section extending past end of file

    This GDB supports auto-downloading debuginfo from the following URLs: https://debuginfod.ubuntu.com Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. 0x000072be440c4540 in _start () from /lib64/ld-linux-x86-64.so.2 (rr) ```

    We can also use c to continue with the test, and use bt to check out stack trace when failure happens:

    ```bash (rr) c Continuing.

    running 1 test test tests::sync_shared::test_insert_parent_unknown_block ... ok

    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 68 filtered out; finished in 0.92s

    terminate called without an active exception [New Thread 74722.74724] [New Thread 74722.74725] [New Thread 74722.74741] [New Thread 74722.74742] [New Thread 74722.74743] [New Thread 74722.74744] [New Thread 74722.74749] [New Thread 74722.74750] [New Thread 74722.74751] [New Thread 74722.74752] [New Thread 74722.74753] [New Thread 74722.74754] [New Thread 74722.74755] [New Thread 74722.74771] [New Thread 74722.74773] [New Thread 74722.74775] [New Thread 74722.74776]

    Thread 1 received signal SIGABRT, Aborted. Download failed: Invalid argument. Continuing without source file ./nptl/./nptl/pthread_kill.c. __pthread_kill_implementation (no_tid=0, signo=6, threadid=) at ./nptl/pthread_kill.c:44 warning: 44 ./nptl/pthread_kill.c: No such file or directory (rr) bt

    0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=) at ./nptl/pthread_kill.c:44

    1 __pthread_kill_internal (signo=6, threadid=) at ./nptl/pthread_kill.c:78

    2 __GI___pthread_kill (threadid=, signo=signo@entry=6) at ./nptl/pthread_kill.c:89

    3 0x000072be4384527e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26

    4 0x000072be438288ff in __GI_abort () at ./stdlib/abort.c:79

    5 0x000072be43ca5ff5 in __gnu_cxx::__verbose_terminate_handler () at ../../../../src/libstdc++-v3/libsupc++/vterminate.cc:95

    6 0x000072be43cbb0da in __cxxabiv1::__terminate (handler=) at ../../../../src/libstdc++-v3/libsupc++/eh_terminate.cc:48

    7 0x000072be43ca5a55 in std::terminate () at ../../../../src/libstdc++-v3/libsupc++/eh_terminate.cc:58

    8 0x00005f7ac4eab073 in std::__terminate () at /usr/include/x86_64-linux-gnu/c++/13/bits/c++config.h:322

    9 std::thread::~thread (this=0x72be3c170ea0, __in_chrg=) at /usr/include/c++/13/bits/std_thread.h:173

    10 0x00005f7ac4eefb68 in std::default_delete::operator() (this=0x5f7ac7268318 ,

    __ptr=0x72be3c170ea0) at /usr/include/c++/13/bits/unique_ptr.h:99
    

    11 0x00005f7ac4ede608 in std::unique_ptr >::~unique_ptr (

    this=0x5f7ac7268318 <rocksdb::PeriodicTaskScheduler::Default()::timer+152>, __in_chrg=<optimized out>) at /usr/include/c++/13/bits/unique_ptr.h:404
    

    12 0x00005f7ac505d876 in rocksdb::Timer::~Timer (this=0x5f7ac7268280 , __in_chrg=)

    at rocksdb/util/timer.h:48
    

    13 0x000072be43847a76 in __run_exit_handlers (status=0, listp=, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true)

    at ./stdlib/exit.c:108
    

    14 0x000072be43847bbe in __GI_exit (status=) at ./stdlib/exit.c:138

    15 0x000072be4382a1d1 in __libc_start_call_main (main=main@entry=0x5f7ac3eeaf40
    , argc=argc@entry=4, argv=argv@entry=0x7ffe436ca588)

    at ../sysdeps/nptl/libc_start_call_main.h:74
    

    16 0x000072be4382a28b in __libc_start_main_impl (main=0x5f7ac3eeaf40
    , argc=4, argv=0x7ffe436ca588, init=, fini=,

    rtld_fini=<optimized out>, stack_end=0x7ffe436ca578) at ../csu/libc-start.c:360
    

    17 0x00005f7ac3e1a4c5 in _start ()

    (rr) ```

    This is actually less obvious than the previous one, the error happens when C++ code destructs a timer instance.

    Just to take a guess: maybe there is a timer left unprocessed, when closing a RocksDB instance?

    Diving into the Code

    Once we had a reliable way to reproduce the failure and replay it in rr, it is time to figure out why it was happening.

    When diving into the code, the first thing I noticed is a redundant delete C++ call:

    rust ffi::rocksdb_optimistictransactiondb_close_base_db(self.base_db); ffi::rocksdb_optimistictransactiondb_close(self.inner);

    If we track down the code, both Line 152 and 153 here will eventually invoke ~StackableDB (Line 34-41):

    cpp ~StackableDB() override { if (shared_db_ptr_ == nullptr) { delete db_; } else { assert(shared_db_ptr_.get() == db_); } db_ = nullptr; }

    After the first invocation, db_ will become nullptr, and C++’s delete first checks if its operand is nullptr. If so, the delete call will just be a NOOP.

    So the extra delete C++ call is redundant, not a double-free. In fact, even if we remove one of the double delete calls, we could still run into failures. Here’s one possible stacktrace:

    image

    And now, it’s mostly just repeating the following loop:

    • Read the code.

    • Add println! in Rust code or printf lines in C++ code.

    • Use the above bash script to compile and repeatedly run the tests until a failure occurs.

    • Use rr to replay the failure in a gdb session, setting breakpoints to peek into memory data. If required, restart rr to begin another gdb session.

    Throughout this process, rr has been super reliable and helpful. As long as bash script captures a test failure, rr can deterministically rerun it as many times as you like.

    By the end, I had likely started over 100 gdb sessions using rr to replay the failures.

    Failure Workflow Analysis

    After enough trials, I’ve nailed down to the following workflow (I’m using tests::sync_shared::test_insert_parent_unknown_block as an example, I believe other tests could be fixed similarly):

    • At the very start, two shared structures and two chain_controllers are created (Line 83-94).

      The shared1 variable created at Line 83 and its discarded chain controller work as expected.

      The issue stems from the shared and chain variables created at Line 84.

    • As part of the block starting at 84, start_chain_services is invoked. It creates a bunch of threads, some of which might hold a copy of Shared structure, meaning each of those threads also holds Arc<RocksDB> instance.

    • A unit test might not use CKB’s full shutdown process like a normal CKB node does. When the test tests::sync_shared::test_insert_parent_unknown_block terminates, this thread (Line 59-73) is still running.

      • Note: By terminate, I mean you can see test tests::sync_shared::test_insert_parent_unknown_block ... ok generated by Rust’s test infrastructure; in other words, you can think that control flow for the main test thread has already exited the method test_insert_parent_unknown_block.

      When Rust initiates thread termination (or pthread determines to kill all still running threads), PreloadUnverifiedBlocksChannel still holds a copy of Shared structure, which maintains a copy of Arc<RocksDB>.

    • Then the Drop impl of the underlying OptimisticTransactionDB starts executing, which will invoke RocksDB’s destructor (Line 717):

      cpp DBImpl::~DBImpl() { ThreadStatus::OperationType cur_op_type = ThreadStatusUtil::GetThreadOperation(); ThreadStatusUtil::SetThreadOperation(ThreadStatus::OperationType::OP_UNKNOWN);

      which then invokes RocksDB’s global Timer’s Cancel method (Line 86):

      rust InstrumentedMutexLock l(&mutex_);

      This is when Timer::Cancel decides to acquire a mutex lock, and pthread signals an error, aborting the test program.

    This leads to a crash like pthread lock: Invalid argument or

    terminate called without an active exception.

    What Caused the Crash

    My best guess at what happened here is:

    • When test_insert_parent_unknown_block finishes, Rust decides that all the requested tests (in this case, just one) have finished, and starts terminating the process.

    • At this point, two threads are involved:

      1. The thread containing PreloadUnverifiedBlocksChannel runs Drop trait impl, which then calls RocksDB’s destructor, and eventually invokes RocksDB’s Timer::Cancel on the global Timer object.

      2. A cleanup thread (most likely the top running thread) runs cleanup hooks for RocksDB’s global Timer structure, which also target the same global timer.

      If Thread 1 finishes before 2, the termination shuts down cleanly and the test passes.

      However, if Thread 2 finishes first, the thread containing PreloadUnverifiedBlocksChannel will acquire a lock on a pthread mutex, which has already been cleaned up (in other words, this pthread mutex might not be properly initialized), and will trigger the aborting process, causing the process running the test to fail even when the Rust test itself succeeds.

    The Fix

    Based on the above assumption, I’ve prepared a fix in this commit, to ensure that all chain service’s threads are properly terminated before the testing function exits.

    Now when running the following test command, the test never fails:

    bash $ cargo nextest run --features with_sentry --no-fail-fast \\ --hide-progress-bar --success-output immediate-final \\ --failure-output immediate-final -p \\ ckb-sync tests::sync_shared::test_insert_parent_unknown_block

    You can also run this command including bash script indefinitely until a failure happens.

    With this fix, I could no longer reproduce the pthread error—even after running the command for over an hour.

    Additional Notes

    • Googling the Error led to this discussion. Unfortunately, the proposed fix does not work for us.

    • Different RocksDB Versions: Currently, CKB is running on ckb-rocksdb v0.21.1 using RocksDB 8.5.4. CKB also developed a newer version: ckb-rocksdb v0.22.0, with RocksDB 9.10.0. I’ve tried both and found the newer one has lower failure frequency, but the issue still occurs.


    ✍🏻 Written by Xuejie Xiao

    His previous posts include:

    • Against ROP Attacks: A Blockchain Architect’s Take on VM-Level Security

    • A Journey Optimizing CKB Smart Contract: Porting Bitcoin as an Example

    • Optimizing C++ Code for CKB-VM: Porting Bitcoin as an Example

    Find more in his personal website Less is More.

    yakihonne.com iris.to jumble.social