Nostr Compass #27
今週はsigner関連、P2P取引protocol、主要クライアントのリリースが目立ちました。Amethyst v1.12.0は170件超のPRをまとめ、NIP-60 Cashu wallet、NIP-61 nutzap、NIP-82 software-appフィード、NIP-F4 podcast対応、CLINKによるon-chain zap検証、KMPフェーズ1・2のiOS移行、Tor自己修復ドライバーを追加しました。Clave v1.0.0(build 102)はApp Storeへ提出され、pushで起動するバックグラウンド署名と受信署名の検証をiOSにもたらします。Mostro Core v0.13.0はProtocol v2を出荷し、relay経由の注文通信をNIP-44 gift-wrapped DMへ置き換えました。Mostro v0.17.5ではオペレーター側の不正防止bondが任意かつ設定可能になりました。Signet v1.11.0は、公開情報だけでkill-switchコマンドを偽造できたNIP-17(gift-wrapped private DM)の管理コマンド署名バイパスを修正しました。Chamaは6日間で7件のescrowリリースを出し、取引ルームを操作の壁から各参加者向けの対話型画面へ変えました。signer側ではAmber v6.2.1、Claveのbuild 100、101、102、Nostur 1.29.0が、今週マージされたNIP-46の新しいlogoutメソッド(PR #2373)を実装しました。Zeus v13.1.0-rc1とAmethystはいずれも、Nostr鍵向け共通Lightningインターフェース案であるCLINK nofferに対応します。NIP-29 relayグループには、banner tag、招待コード、メッセージのpin留め、NIP-17 DMによるグループ報告、role-based access controlを扱う5件の提案が出ました。
トップストーリー
Amethyst v1.12.0はCashu wallet、nutzap、CLINKドライバー、Tor自己修復を出荷
AmethystはVitor Pamplonaによる主要なAndroid Nostrクライアントです。v1.12.0は、Newsletter #25で未リリース作業として扱った93件のPR(NIP-32 hashtagラベル、NIP-F4 podcast画面、音楽トラック、一時的signer、NIP-05フィルター付きon-chain zap)とNewsletter #26の続き(NIP-F4、Tor watchdogの基盤)に、今週の大規模な追加作業をまとめています。新作業の中心はCashu・nutzap画面、CLINK on-chain zapドライバー、Tor自己修復群、KMPのiOS移行です。
NIP-60 Cashu wallet対応とNIP-61 nutzap描画はPR #3075で入り、mint別残高画面(PR #3115)と統合支払いカードUI(PR #3191)がLightning address、on-chain zap、Cashu mint、NWCを1つのプロフィール支払い画面へまとめます(PR #3185)。on-chain zap検証用CLINKドライバーはPR #3039、PR #3177、PR #3182で出荷されました。CLINKはCommon Lightning Interface for Nostr Keysで、今週Zeus v13.1.0-rc1も同じnofferインターフェースを搭載し、Amethystは検証state machine、再検証ドライバー、on-chain zapの最低額を追加します(PR #3030)。PR #3201はNIP-17に従い、p-tag付きユーザーへのkind 1返信をgift wrapする非公開ノートを導入しました。宛先に応じてcomposerが公開ノートまたは封印されたグループ返信を生成します。
Torの信頼性改善は完全な自己修復stackとして入ります。PR #3053はArtiをv2.3.0へ更新しwatchdogと統合テストを追加、PR #3223はTorの準備完了までTor経由relayへのdialを抑止、PR #3224は敵対的ネットワークがloopを停止させないようArti bootstrapを60秒でtimeout、PR #3231はTorがActiveでも全circuitが停止している場合に自己修復します。その結果、ネットワーク変更やsleep・resume後にも手動操作なしで復旧します。KMP iOS移行のフェーズ1と2はPR #3047とPR #3050で出荷され、quartzとcommons moduleのiOS CIを動かし、iOS版Amethystの基盤を整えます。
Mostro Core v0.13.0はProtocol v2でrelayの仲介を削減
Mostroは、Nostrをorder bookおよび取引通信層に使いLightningで決済するP2P Bitcoin取引所です。wire protocolを定義するRustライブラリmostro-core v0.13.0は、relay経由のmessagingモデルをchangelogがProtocol v2と呼ぶ仕組みに置き換えます。これはkind 14 event上で動くNIP-44 direct transportです。取引固有のactionはNIP-44でwrapされ、注文作成時に参加者が生成した取引別keyへ結び付けられたkind 14 messageとして流れ、公開addressable eventを介して会話を往復させません。
旧モデルでは、取引会話の全体がeventを運ぶすべてのrelayに露出していました。direct kind 14 transportでは注文設定、紛争処理、決済metadataが両当事者とMostro daemonの間に留まり、relayが見るのは暗号化envelopeだけです。v0.13.0はtransport変更に加え、v2 identity proofを取引keyへ結び付け(commit log)、新protocolに対するreplay riskの一種を閉じます。daemon側ではMostro v0.17.5が不正防止bondを任意かつオペレーター設定可能にしました。特定の取引を始める前に双方が少額のbondをlockし、正常完了時には返還、停滞、欠席、妨害時には没収される場合があります。bondはネットワーク全体ではなくnodeオペレーター単位で有効になるため、Mostroはnon-custodialを保ち、各オペレーターが取引摩擦と不正耐性の均衡を選べます。クライアント側のMostro Mobile v1.2.8は新経路を支える17機能を追加しました。固定既定relayに代わるbootstrap relay discovery(PR #610)、bond展開フェーズ5として注文作成時のmaker不正防止bond(PR #608)、文脈付き注文キャンセルの通知履歴への永続化(PR #602)などです。2日後のv1.2.9はnode info eventの不正防止bond方針を表示し、注文前にそのMostro instanceのbond規則を確認できるようにしました(PR #617)。
Signet v1.11.0はNIP-17管理コマンドの署名バイパスを修正
Signetはremote bunker signerで、管理者がhost machineへ触れずNostr経由でsignerをpanic、復旧、状態確認できるkill-switchを備えます。v1.11.0は、そのNIP-17 gift-wrap管理コマンド経路が署名済みsealを検証せず、未署名の内側のrumorが主張する作者だけを確認していた脆弱性を修正します。NIP-44 conversation keyは対称なので、signer pubkey、管理者npub、管理用relayという公開情報だけを持つ攻撃者が外部からgift wrapを偽造し、panic、resumeall、aliveを含む任意のkill-switchコマンドを実行できました。修正はsealにverifyEventを適用し、rumor作者をseal署名へ結び付けるため、未署名の偽造は入口で拒否されます。仕様と修正前コードから再現手順を明確に組み立てられるため、Signetオペレーターは速やかに更新すべきです。
Chama v3.2.0からv3.5.0は取引ルームを刷新し資金経路を強化
ChamaはFedimint ecashと2-of-3 Shamir秘密分散を組み合わせ、serverlessな取引決済を実現するNostr-native P2P escrowクライアントです。Newsletter #26ではstandalone app化とseller別storefrontを追加したv2.0.0からv3.1.0を扱いました。今週の6件の後続リリースはv3.2.0から始まり、6月15日のv3.5.0まで続きます。取引ルームUIを「今、自分は何をすべきか」という各参加者向けの問いを中心に再構成し、部分障害から資金経路を守ります。v3.2.0はbuyer、seller、arbiterごとに色分けしたaction promptを追加し、全取引状態で各役割の次の行動を示します。v3.3.0は取引engineの2つのconsensus ruleを厳格化し、効果を得るにはクライアントの協調更新を必須にしました。v3.3.1は価格と支払い方法をtraderのcommunity currencyへlocalizeします。v3.4.0は一時障害、race、tab終了でsatsを失わないよう資金経路へ5件のhardeningを追加しました。v3.5.0は、取引を密かに偏らせ得るarbiter役に2つのクライアント側guardrailを加えます。
Clave 1.0はpush起動バックグラウンド署名とともにApp Storeへ
ClaveはユーザーのNostr秘密鍵をiPhone Keychainに保持するiOS向けNIP-46 remote signerです。アプリはend-to-end暗号化channelで署名を要求し、鍵自体は受け取りません。v1.0.0 build 102は今週App Storeへ提出され、8か月のTestFlight betaを経て1.0 milestoneへ到達しました。このリリースはpush起動バックグラウンド署名を搭載します。Claveはアプリ終了中でもrequestを復号し、権限を確認し、署名して応答できるため、従来signerの応答性を制限していたiOS foreground要件がなくなります。受信署名はBIP-340 Schnorrと標準NIP-01 event serialization形式(署名済みNostr eventのhash方法を定義する基本仕様)で検証され、replay freshness guardも適用されるため、悪意あるアプリが再署名eventをresponse channelへ紛れ込ませることはできません。
このリリースはkind単位の権限モデルと3段階の機密度を持つ更新版NIP-44暗号化層も導入します。「毎回確認」のrequestがユーザーの承認前にerrorを返していた低信頼署名のedge caseを修正し、1つのアプリpairingから複数identityを使えるmulti-account pairingを追加しました。bunker pairingはNIP-46 connect metadata拡張を通じて実際のアプリidentityを表示します。この拡張はClaveがPR #2381で提案しました。正常な切断には新しいNIP-46 logoutメソッドを使います。このメソッドはPR #2373でマージされ、paired appは手動unpairなしでsessionを終えられます。アプリ別の信頼level(Full、Medium、Low)とevent kind別override、全署名のactivity log、任意のpush proxyにも対応します。proxy stackはMIT licenseで、クライアント別interop matrixはdocs/nip46-compatibility.mdにあります。
リリース
Amber v6.2.1はNIP-46 logoutを追加しsignerのbattery消費を削減
Amberは主要なAndroid Nostr signerです。v6.2.1はrelay再接続とWebSocket pingによるbattery消費を減らし、停止relayをsubscription poolから除き、relay通知更新時に端末を起こさなくしました。今週仕様にマージされたものと同じNIP-46 logoutにも対応し(PR #2373)、クライアントがremote signer sessionを正常終了できます。event kind 39701(公開web bookmark)のparseも追加され、Amberからbookmark eventへ直接署名できます。SettingsはMaterial 3 cardと個別iconで再構築され、アプリ権限画面のnavigation crashを修正し、databaseをatomicに構築してaccount別connection leakを閉じました。
Nostur 1.29.0は匿名返信とremote signer logoutを出荷
NosturはFabianによるiOS Nostrクライアントです。1.29.0-desktopはzap receiptへの返信と匿名返信を追加します。signer側ではremote bunker接続を改善し、account logout時にremote signerへNIP-46 logoutを送り、remote signer接続失敗時にspinnerが止まらない問題を修正しました。DM relayとアプリrelayの競合によるDM読み込み問題、返信へ移動して戻った際の重複投稿も修正し、通知行にmedia thumbnailを表示します。
Citrine v3.0.0はNegentropy、NIP-42 AUTH、onion relay filterを出荷
CitrineはAndroidのlocal relay aggregatorです。v3.0.0はmajor version更新で、set reconciliation同期用NIP-77 Negentropy、aggregatorでのexternal signerとNIP-42 AUTH、aggregator取得でのNIP-51 mute list尊重を追加します。作者ごとの取得を3 relayに制限しsource relayとindexer relayを設定可能にし、follow、mute、metadataのcacheを再起動やnetwork変更後も再利用します。制限networkではpauseし、outbound proxy無効時にはonion relay URLを除外します。保護eventを埋め込むrepostを拒否し、mute listは既定で経年削除から保護されます。
FIPS v0.4.0-rc1はNym mixnet transportとmDNS LAN discoveryを追加
FIPSはFIPS mesh sync protocolの実装です。v0.4.0-rc1はv0.3.0とwire互換で、混在meshも相互運用でき一斉更新は不要です。node間の発見と接続方法として、single-container demoとmixnet relay例を備えたNym mixnet outbound transport、および任意のlocal-link mDNS / DNS-SD discoveryを追加します。counterのみの新しいshow_metrics queryによりhot pathへ負荷を加えずPrometheus scraperを使え、FMPとFSPのrekeyは双方向packet loss時にも途切れないよう強化されました。
Calendar by Formstr v1.6.1とv1.6.2はevent別通知を追加
Calendar by FormstrはNIP-52 calendarクライアントです。v1.6.1はevent別の通知設定(PR #109)を追加し、個々のcalendar eventごとにreminderを有効・無効にできます。v1.6.2はAmberでのlogin(PR #185)を修正し、Amber 6.2.xの新しいNIP-46 handshakeがend-to-endで動作します。
Bitchat v1.5.2とv1.5.3はNostr・BLE transportを強化
BitchatはBluetoothとNostrを使うmesh chatクライアントです。v1.5.2はflood防止のためiOS peer通知をrate limitし(PR #972)、Nostr検証とBLE announce確認を強化して(PR #1012)、relay側のNostr ingest経路が不正messageをlocal mesh handlerへ届く前に拒否します。v1.5.3はNostrRelayManagerとNetworkActivationService間の再帰的dispatch_onceによる起動crashのhotfixです(PR #1343)。
Keep v1.0.5はsigner方針を監査済みRust coreへ移行
Keepはkeep Rust coreを包むAndroid signerです。v1.0.5はkeep v0.4.8へ固定し、高負荷時にhandshakeの最初のeventを落とさないbunker初期化race修正(PR #296)、bunkerのonConnect callbackからAuthorized Clients画面を埋める変更(PR #291)、keep-mobileのkill switchを単一の正へ統合する変更(PR #284)を出荷します。上流Rust coreは6月13日にv0.4.9を公開しました。NIP-55とNIP-46のsigner方針(権限判断、機密kindの期間上限、期限、keyed-HMAC改ざん検知audit chain、callerのtrust-on-first-use、永続署名rate limiter)をKotlinとの重複実装から監査済みRust coreへ移し、NIP-44 v3 cipherも追加します。このcoreは次のkeep-mobile更新に入ります。
ants v0.4.5は記事portal linkを追加しportal群にHablaを復帰
antsはdergigiによるNostr検索・reader toolです。v0.4.5はlong-form postの記事cardに、article portal link、記事固有naddr共有、nevent copy、raw JSON表示を追加します。Hablaを復帰させ、停止destinationを交換し、imwald portalを削除してarticle portal群を更新しました。記事footnoteの描画と記事内anchor navigationも復元し、login復元時にはrelay接続後にprofileを取得することでheader avatarを正しく解決します。
Morganite v0.0.3はTorを必要時に使うAndroid向けlocal Blossom cacheを出荷
MorganiteはAmberとCitrineの作者greenart7c3による新しいAndroid local Blossom cacheです。BUD-08 local mirrorとして動き、1GBを超えると利用頻度の低いblobから削除します。v0.0.3は必要時にTorを起動し、idle時に停止してbatteryを節約します。作者検索後にNostr relayを切断してbackground消費を止め、filterなしlogcat streamとleakしたHTTP clientによるbattery消費を修正し、交換済みOkHttp clientをmain thread外で解放します。Blossom server list検索前にユーザーのinbox relayを取得してblob discoveryをoutbox modelに従わせ、local cacheにないblobへのHEAD requestでは実体をdownloadするため、cache warmupが実際の需要に結び付きます。
Coracle 0.6.34と0.6.35はNIP-46 login、古いfeed、返信toggleを修正
CoracleはhodlbodによるNostr webクライアントです。0.6.34はNIP-46 login、view切替後にhome timelineが更新されない古いfeed状態、有効にすると全件を除外する返信toggleを修正します。feedとlist viewも再構築し、toast safe-area insetを修正、画像読み込みを改善しました。0.6.35は返信無効時にrepostまで隠れる問題を修正し、reply filterの過剰適用を止めます。
Zeus v13.1.0-rc1はCLINK nofferとqueueなしNWCを出荷
Zeusはwallet connectとnoffer支払いにNostrを使うself-custody Bitcoin・Lightning walletです。v13.1.0-rc1はPrimalとの協力でiOSにqueueなしNIP-47 Nostr Wallet Connect支払いを追加し、支払い済みNWC invoiceがbackground queueで待たなくなります。Zeus Payが全account向けCLINK nofferを生成するため、senderはNostr鍵だけで任意のZeusユーザーへ支払えます。Zeus PayのNostr Zapを無効化するoptionも追加し、受取人はNWCを無効にせずkind 9735 receipt経路だけを止められます。
Alby Extension v3.14.3はNIP-07 signerが使うnoble・scure crypto stackを移行
Alby ExtensionはLightning機能とともにNIP-07署名とNostr Wallet Connectを提供するbrowser extensionです。v3.14.3は@noble/curves、@noble/hashes、@noble/ciphers、@noble/secp256k1、@scure/bip32、@scure/base stackをv2・v3 majorへ移行します。これらはNIP-07 signer経路がevent署名とNIP-44暗号化に使うcrypto libraryであり、major更新はNostr webクライアントからの全署名requestについてextensionが生成するwire formatに関わります。
Mostro Mobile v1.2.8とv1.2.9はProtocol v2を支援しbond方針を表示
Mostro MobileはMostroのmobileクライアントです。v1.2.8は上のトップストーリーで扱ったmostro-core v0.13.0 Protocol v2のクライアント側対応を導入し、計17機能を追加します。PR #608のmaker不正防止bond、PR #610のbootstrap relay discovery、PR #602の通知履歴に残る注文キャンセル、PR #605の注文作成画面におけるfiat金額上限などです。v1.2.9はnode info eventの不正防止bond方針を表示し(PR #617)、注文前にMostro instanceのbond規則を確認できます。
ZapBook build 4から27はmulti-account、Marmot key公開、circle再招待を出荷
ZapBookはcodeswotによるiOS・Android向けNostr-native social readingアプリで、1人から100人のreading circle内でmilestoneを共有し、励ましとして互いにsatsをzapします。6月11日のbuild 4から6月15日のbuild 27までに17件のtag付きbuildと7件のmerged PRを出荷しました。滑らかなaccount切替を持つmulti-account対応はPR #25で入り、複数Nostr identityの保持とsession移行が可能です。初期Marmot key package(kind 443)の公開はonboarding完了時に自動実行され(PR #20)、reading circleでinvite-only group messagingを使う前提を満たします。circleから削除されたmemberの処理は新しい再招待を正しく扱い(PR #24)、再追加したmemberにinviteが届かない問題を解消しました。ONNX embedding inferenceをbackground isolateへ移してreader内semantic検索を支え(PR #19)、環境別設定用APP_ID_SUFFIXとともにNWC serviceを統合し、1つのhubで複数ZapBook buildを扱えます。
Alby Hub v1.23.0は削除済みアプリのNIP-47公開を修正しBitrefillをNWCへ移行
Alby Hubはself-hosted Lightning・Nostr hubです。v1.23.0のNostr以外の変更(Just-in-Time channel、debit card top-up用Cards page、実験的Ark payment backend、stories home page)はCompassの範囲外です。NIP-47側では、削除済みアプリのNIP-47 info公開を再試行しないため、削除したconnectionがkind 13194 info eventを再公開し続けなくなり(PR #2391)、Bitrefill独自app entryを標準NWC connectionへ置き換えます(PR #2420)。app storeアプリ向けreadonly option(PR #2415)はhub内store経由で公開されるNWCアプリの権限scopeを絞ります。
その他のリリース
今週の小規模なリリースのうち、Nostrに関連するものの各リリース単体の内容が限られるものです。Nostria v3.1.48からv3.1.50はWeb Bookmark展開を継続し、v3.1.50で通知の信頼性とevent thread databaseを最適化。Deepmarks v0.7.0からv0.7.5はNIP-B0 social bookmarkクライアントを反復し、今週PR #96でwebsite linkも追加。Keep v1.1.1からv1.1.4は上で扱ったv1.0.5 signerリリースに4件のF-Droid reproducible build修正を追加。NoorNote v0.11.1、v0.12.0、v0.13.0、v0.13.1はdesktop noteクライアント、Boris v0.12.2はBoris reader、Nostr Mail Client v0.13.0、Feeder 2.21.1、nak v0.19.13はNostr CLIの内容なしmaintenance更新、Hashtree v0.2.68からv0.2.71はhash tree address型release publisherのgateway mutable-root cacheを更新、NYM v3.72.501とv3.72.502はNostrifyベースrelay実装を更新、swift-nostr-client 0.3.0、0.4.0、0.5.0は85件のmerged PRを背景にiOS Nostrクライアントで3件のminor release、lawallet-nwc v0.11.0はLaWallet Nostr Wallet Connect bridgeで18件のmerged PR、Astraea v5.35.59からv5.35.62はAstraea Nostrクライアントを更新しました。また、BTC RechargeとgiftcardshopのNIP-05検証済みNostr DM botが新しいShops categoryでproject directoryへ追加されました。
未リリースの変更
diVineは次のshort-form videoリリースへ向け119件のPRをマージ
diVineはVine archiveをNostr基盤上で復元するNostr-native short-form looping videoクライアントです。今週、tag付きreleaseなしで119件のPRをマージしました。Nostrに関わる主要作業は、relayのOKが欠けても失敗として表示しないREST優先video公開経路(PR #5221とPR #5220)、広域blocklist変更時にcurated・liked gridを再filter(PR #5208)、再install regression後のDM会話list復旧(PR #5202)、profile上のNostr badge表示復元(PR #5218)、comment引用内nostr:参照のlink化(PR #5225)です。video editor stackはclipのmulti-select結合・削除、zoom追従letterbox scrim付きpinch-to-zoom canvas、clipのcrop・rotate・flipも追加しました。
Polleramaはsigner再構築と機能群を含む15件のPRをマージ
Pollerama(repo formstr-hq/nostr-polls)はForm*系のNostr-native poll・feedクライアントで、今週v1.6.2を出したCalendar by Form*の姉妹projectです。nostr-pollsの最新tagは3月のv1.6.4なので期間内作業は次のtag待ちで未出荷ですが、6月9日から16日にabh3po、geralt-debugs、SIDDHANTCOOKIEの貢献を含む15件のPRがマージされました。signer側ではPR #198で既存署名面を置換し、PR #201で更新しました。PR #200はlogin時のkind 0 metadata更新を止め、新規sign-inが要求していないprofile eventを公開しないようにします。機能群にはprofile viewから投稿できるprofile editor(PR #205)、改善したrepost flow(PR #209)、topic discoveryを容易にする経路(PR #202)があります。次のtag付きreleaseにこれらが入ります。
Libraryとtooling
NDK PR #375とrust-nostr、nostr-tools repoのmerged workは今週静かで、各1、2件のmerged PR、tag付きreleaseなしでした。ContextVM SDK(merged PR 1件)、mesh-llm(merged 37件、open 8件)、Zap Cooking(merged 26件)、Routstrd(merged 2件)の活動は期間内にrelease tagなしで続きました。
NIP更新とprotocol仕様作業
今週のprotocol作業はsigner hardeningとNIP-29 group governanceの2領域に集中しました。
今週マージ:
- NIP-46(Nostr Connect)。 PR #2373はクライアントがremote signer sessionを正常終了できる
logoutメソッドを追加しました。Amber、Clave、Nosturが同じ週に対応を出荷しました。 - NIP-CC(Community Chat)。 PR #2365はclient側の仕組みについて現行のNIP-GC(Group Chat)仕様を参照するようNIP-CCを更新し、community room仕様を標準group chat primitiveへ合わせます。
Open NIP-29群(relay-based group governance):
- Banner tag。 PR #2383はgroup metadata kind 39000 eventへ
bannertagを追加します。 - 招待コードsuffix。 PR #2380はgroup identifierへinvite code suffixを導入し、one-shot inviteをgroup ID自体へencodeできるようにします。
- Message pin留め。 PR #2379はupdate-pin-list moderation actionと、pin済み集合をbroadcastするkind 39005 eventを追加します。
- NIP-17 DMによるgroup報告。 PR #2377はmemberがgroup abuseをrelayの管理連絡先へNIP-17 gift-wrapped DMで報告するflowを定義し、moderation trafficを公開group event streamから外します。
- Role-based access control。 PR #2376は既存のadmin・member分離の上にRBAC roleを追加します。
Open NIP-46 follow-up:
- Connect requestのclient metadata。 PR #2381は接続クライアントが任意の
name、url、iconfieldをconnect requestで送り、signerがpairing画面にアプリidentityを表示できるようにします。Clave build 101が提案を実装しています。 - Silent timeoutの回避。 PR #2375はユーザー入力が必要なsignerが判断までrequestをopenに保つよう仕様を厳格化し、Clave build 100が実装側で修正したfailure modeを解消します。
その他のopen work:
- NIP-100 Sovereign Agent Identity Network(SNIN)。 PR #2378はautonomous agentのidentityとcapability discoveryを担うagent-to-agent protocolを提案します。範囲が広く、reviewで小さな単位へ分割される可能性があります。
Blossom仕様。 BUD-00 PR #108は6月15日にマージされ、serverが実装しないBlossom blob上のクライアント側慣習とdata formatもBUD定義へ含めました。これまで帯域外extensionとして扱われていたBUD-10(blossom: URI scheme)やBUD-08(今週Morganiteが実装したlocal cache慣習)も標準番号体系へ入ります。
NIPディープダイブ: NIP-77(Negentropy)
NIP-77はNostr relay向けset reconciliation protocolを定義します。clientとrelay、またはbridge内の2つのrelayがfilterに一致するevent集合をそれぞれ持ち、全件を再送せず和集合へ収束させます。単純な方法は全event IDをwireへ流して差分を取りますが、busyなfilterでは差分量にかかわらず大きい側の集合sizeに比例したcostがかかります。NIP-77はcostを対称差に比例するまで削減します。
仕様はNEG-OPENとNEG-MSGという2つのrelay message上で動きます。clientは["NEG-OPEN", <subscription_id>, <filter>, <initial_message>]でreconciliation sessionを開きます。<initial_message>はclient側集合を記述するhex encode済みNegentropy payloadです。replyはNEG-MSG frameで届き、双方が固定点へ達するまでmessageを交換します。各NEG-MSGはrangeを固有fingerprint付きsub-rangeへ分割して不一致を絞るか、小rangeのIDを列挙してreceiverが直接diffを計算できるようleafを終端します。相手に自分が持たないeventがあると判断した側は通常のREQでIDを要求し、自分だけが持つeventのuploadは相手側への通常のEVENT publishに任せます。
下層data structureは順序付きMerkle treeの変種です。local集合の各eventは(created_at, id)をkeyとしてrangeへbucket化され、各rangeには含まれるIDから計算した小さなfingerprintが付きます。clientとrelayでfingerprintが一致すれば、そのrangeは収束済みとしてskipされます。異なればreply側がrangeを半分またはsub-rangeへ分割し、各fingerprintを送って不一致を再帰的に絞ります。小さなthreshold未満のleaf rangeはそのまま送られます。収束済みrangeは内部event数にかかわらず、ほぼcostなしで確認できる点が重要です。
created_at順のframeには2つの意味があります。第一に、既存のNostr paginationは同じtimestampにuntilとsinceを使うため、reconcilerは全archiveを再同期せずsessionをまたいで再開できます。上限をcacheし、次の同期をそこから始めます。第二に、sort済みkeyからのrange分割は決定論的なので、clientとrelayは追加negotiation messageなしで次のboundaryに合意できます。sync costはおよそO(d log n)です。dは対称差のsize、nは大きい側の集合sizeで、単純なID dumpのO(n)やN件のREQを発行するO(n) round tripを大幅に下回ります。
実装には3つのtradeoffがあります。fingerprint sizeはcollision確率とbandwidthの均衡で、仕様はrangeごとに32 byteを使います。小さくすればbyteを節約できますが、誤一致でeventを欠落させる可能性が上がります。leaf threshold、すなわち分割を止めてIDを直接送る境界はround tripとmessage帯域の均衡で、小さいthresholdはroundを増やし、大きいthresholdはleaf messageを大きくします。またprotocolは双方が同じrangeから同じfingerprintを計算できることを前提とし、両実装が合意する安定した(created_at, id) pair serializationが必要です。そのため仕様はfingerprint構築時のbyte orderを厳密に定めています。
NIP-11のsupported_nipsでNIP-77を広告するrelayに対し、clientは通常のREQ同期の代わり、または併用でreconciliationできます。clientは用途でprotocolを選びます。過去stateのない新規subscriptionでtail trafficを求めるならREQ、長時間停止後に追い付くmirrorならarchiveに対して対称差が小さいためNEG-OPENを使います。両経路は異なるdeployment contextで補完関係にあります。
NEG-OPEN交換例:
→ ["NEG-OPEN", "sync-1", {"kinds":[1],"authors":["abc..."]}, "<hex initial Negentropy message>"]
← ["NEG-MSG", "sync-1", "<hex relay response>"]
→ ["NEG-MSG", "sync-1", "<hex client refinement>"]
← ["NEG-MSG", "sync-1", "<hex leaf with IDs the relay has and client lacks>"]
→ ["REQ", "fetch-1", {"ids":[...]}]
← [...EVENT messages...]
← ["EOSE", "fetch-1"]
→ ["CLOSE", "sync-1"]
Citrine v3.0.0は今週relay aggregatorへNIP-77対応を出荷し、Android local relayからbulk REQ取得の代わりにexternal relayとreconciliationできるようにしました。
NIPディープダイブ: NIP-61(Nutzap)
NIP-61はNostr eventとして配送されるpeer-to-peer Cashu ecash支払いを定義します。senderはrecipientのNostr由来公開鍵へlockしたCashu tokenを公開し、recipientは都合のよい時にmintからredeemします。支払い時点でreceiverがLightning経由でreachableである必要があるNIP-57 zapと異なり、nutzapはrecipientが自分の予定でredeemできる自己完結型ecash tokenです。
仕様はCashuのP2PK lock primitiveと3つのevent kindを組み合わせます。kind 10019はrecipientのmint推奨で、recipientがnutzapを受け入れる1つ以上のmintと、proofをlockするCashu公開鍵を載せるreplaceable eventです。この鍵はrecipientのNostr identity keyとは別で、identity keyがecash secretへ触れないようnutzap受取用にderiveしたwallet scoped keyです。senderは送金前にkind 10019を読み、recipientが既に信頼するmintでredeemできるtokenを作ります。
kind 9321が支払いeventです。1つ以上のCashu proof tag(それぞれkind 10019のrecipient nutzap pubkeyへ結び付いたP2PK lock済みproof)、mint URLを持つu tag、zap対象noteを示す任意のe・a tag、recipientのp tagを載せます。recipientは通常のNostr subscriptionでkind 9321を受け取り、proofが自分のkind 10019にあるmintで自分のnutzap pubkeyへlockされていることを検証し、対応する秘密鍵でunlockしてNIP-60 walletへ保持するかLightningへmeltします。kind 7375はredeem済みproofをrecipientのwallet event chainへ記録し、relayから再同期したwalletが同じ送信元のnutzap proofを重複計上しないようにします。
trust modelは設計が明示的に負う代償です。Cashu mintが裏付け価値を保持するため、悪意ある、または差し押さえられたmintはredeemを拒否できます。NIP-61はNIP-60からcustody riskを継承し、それを除去しません。代わりにoffline対応で即時finalityを持つmicropaymentを得ます。token自体が支払いなのでrecipientはLightning nodeを動かしたり、real timeにincoming HTLCを受けたりする必要がなく、同じmintのproofを持つsenderはcustodianへのnetwork hopなしで支払えます。kind 10019の広告がsocial layerのgateです。recipientのtrusted set外のmintを選ぶsenderはredeem不能tokenを送るriskを負い、recipientのredeem面を予測可能に保ちます。
NIP-57と比べ検証経路も単純です。NIP-57 zap receiptはrecipientのLNURL serviceが公開するkind 9735で、verifierはLNURL endpointを取得し、receipt署名鍵がendpointの宣言と一致することを確認する必要があります。nutzapは支払いのcryptographic proof、すなわちP2PK lock済みproof自体をinlineで運ぶため、mintの公開鍵を持つverifierなら第三者へのround tripなしでproofの妥当性を確認できます。代わりにnutzap検証はmint keysetの理解が必要ですが、NIP-57検証には標準LNURL infrastructureだけが必要です。
2つのzap形式は補完関係で共存します。Lightning routingを持つreceiverと、Lightning settlement semanticsでsats建て支払いを望むsenderにはNIP-57 zapが適します。offline receiver、Lightning feeが送金額を上回るmicropayment中心のflow、Lightning infrastructureを持たないユーザー向けクライアントにはNIP-61 zapが適します。
nutzap event例:
{
"id": "a5f87fe2d4c8b9a0e3f1c4d5e6a7b8c9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f",
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"created_at": 1750162800,
"kind": 9321,
"tags": [
["proof", "{\"amount\":21,\"secret\":\"...\",\"C\":\"...\",\"id\":\"...\"}"],
["u", "https://mint.example.com"],
["e", "8b39f4e5d6c7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3"],
["p", "c5d8a4e3b2a1f0e9d8c7b6a5949382716050403020100ffeeddccbbaa99887766"]
],
"content": "Great post!",
"sig": "f1e2d3c4b5a6978869504132c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5"
}
Amethyst v1.12.0は今週、NIP-60 wallet面とともにNIP-61 nutzapの描画を正式対応として出荷しました(PR #3075)。受信nutzapをtimelineへ描画し、walletでmint別残高を表示します。