#

signet

(15 articles)

FROSTR evaluation for tenex-eventd

# FROSTR evaluation for tenex-eventd ## Objective Evaluate whether Signet should move from a single-key bunker to threshold signing so one leaked machine or one leaked process does not immediately burn the Nostr identity. ## What FROST solves Fact: RFC 9591 standardizes FROST, a threshold Schnorr signing protocol. Fact: the Go library `github.com/bytemare/frost` advertises RFC 9591 support and explicitly supports `Secp256k1`. Fact: FROSTR-adjacent tooling already exists in the Nostr ecosystem (`FROSTR-ORG/igloo-desktop`, `igloo-server`), which makes this direction ecosystem-aligned rather than custom crypto. ## Why this fits Signet - `tenex-eventd` already acts like a signing control plane. - NIP-46 gives us the remote-signing protocol boundary. - FROST is the right primitive if we want to remove single-process custody of the signing key. ## Hard constraint on the current v3 key Fact: the current v3 identity already exists today as a single local secret. Inference: turning an already-created single secret into “2-of-3 shares” is not the same trust model as a threshold key generated through DKG from the start. Important consequence: - Even if the v3 secret is now split for operational use, the historical single-key exposure already happened. - That means threshold retrofitting improves future custody but does not erase past exposure history. ## Same-npub share rotation caveat Fact: RFC 9591 covers threshold signing, not a whole operational system for proactive share refresh / in-place share rotation. Inference: keeping the same `npub` while rotating one compromised share requires an additional refresh / resharing story, not just baseline FROST signing. So there are two separate questions: 1. Can we threshold-sign for this identity? - Yes, in principle. 2. Can we rotate a single share in place without changing the public identity? - Not from RFC 9591 alone; that needs refresh-capable protocol support and careful ops design. ## Integration options ### Option A: stabilize the current bunker first - Keep v3 as a single-key NIP-46 bunker. - Harden ACLs, audit logging, and client permissions. - Lowest immediate implementation risk. ### Option B: move to a fresh threshold-generated identity - Create a new Nostr identity through DKG / threshold setup from day one. - Expose it through a NIP-46-compatible coordinator. - Best clean-slate security posture. - Tradeoff: new `npub`. ### Option C: same-npub threshold retrofit with share refresh - Keep the current public identity. - Add threshold custody plus future share refresh semantics. - Highest complexity. - Not something `go-nostr` or the current tenex daemon gives us out of the box. ## Go ecosystem read Fact: `bytemare/frost` is a serious Go implementation with secp256k1 support. Fact: current Nostr-native FROSTR product work appears concentrated in dedicated projects like Igloo, not in `go-nostr` itself. Inference: we can likely build a Go threshold signer around existing FROST libraries, but we should not expect a drop-in “NIP-46 bunker backed by refreshable FROST custody” package today. ## Effort estimate - NIP-46 bunker: low-to-moderate, already live locally. - FROST-backed coordinator prototype: moderate-to-high. - Production-ready threshold ops (DKG, recovery, resharing, revocation, auditability): high. ## Recommendation Do not build custom threshold crypto. Recommended sequence: 1. Keep the current v3 identity behind the new NIP-46 bunker immediately. 2. Decide whether same-`npub` custody is a hard requirement. 3. If no, plan a fresh threshold-generated v4 identity with DKG. 4. If yes, treat “share refresh without `npub` change” as a separate research/architecture track, not as a quick follow-on to the bunker work. ## Decision needed The founder decision is not “whether FROST is good.” It is: - Is a new threshold-generated identity acceptable once the bunker path is stable? - Or is preserving the existing `npub` across future share rotation a hard non-negotiable? That answer changes the architecture materially.

tenex-eventd NIP-46 bunker spec

# tenex-eventd NIP-46 bunker spec ## Goal Turn `tenex-eventd` into a remote signer that keeps the secret in local operator custody while exposing a shareable `bunker://` URI to remote clients. The URI, not the secret key, is what remote sessions receive. ## Current design - Secret source: `TENEX_EVENTD_SECRET_KEY_HEX` / `NOSTR_SECRET_KEY` from `secret.env`. - Public identity metadata stays in `nostr-identity.json`. - Startup writes a local `bunker://<pubkey>?relay=...&secret=...` URI to `~/.config/tenex-eventd/bunker.uri` with `0600` permissions. - The URI is intentionally local-only; it is not published to relays. ## Transport - Incoming requests are kind `24133` events tagged with `p=<bunker-pubkey>`. - The daemon polls relays directly for bunker requests. - Responses are returned as kind `24133` events encrypted back to the client. - Relay set currently matches the tenex relay set: - `wss://relay.damus.io` - `wss://nos.lol` - `wss://relay.primal.net` ## Read / write path - Read path tries Primal HTTP cache first for mentions/profile/thread reads. - Because Primal currently returns `500` for this identity, the daemon falls back to direct relay queries. - Write path signs locally and publishes directly to relays when `alby_token` is unset. ## Supported bunker RPC methods - `connect` - `get_public_key` - `sign_event` - `nip44_encrypt` - `nip44_decrypt` - `get_relays` - `ping` ## Permission model - `connect` requires the shared secret embedded in the local bunker URI. - `sign_event` is allowlisted to kinds `1` and `30023`. - Initial intent is notes + long-form articles only. - Unsupported or disallowed methods return an error and are not signed. ## Runtime behavior - Mention polling remains on the slower normal interval (`poll_interval = 60`). - Bunker traffic is handled on a faster dedicated cadence (`bunker.poll_interval = 5`). - This keeps remote-signing latency reasonable without forcing the whole daemon into a 5-second Primal loop. ## Verification Fact: local unit tests pass for connect/auth success, wrong-secret rejection, and disallowed-kind rejection. Fact: live round-trip verification against the launchd daemon passed using the generated local bunker URI: 1. `connect` 2. `get_public_key` 3. `sign_event` for kind `1` 4. `nip44_encrypt` 5. `nip44_decrypt` 6. rejection of disallowed kind `4` ## Known gaps - No persisted per-client ACLs yet; authorization is currently shared-secret based. - No session expiry / rotation policy yet beyond bunker URI regeneration. - If `bunker.connect_secret` is left empty, a new secret is generated on restart; copied old bunker URIs stop working. - No `switch_relays` flow yet. - No bunker-specific rate limiting yet. - The Primal `500` path is still degraded, so direct relay fallback is operationally required today. ## Recommendation Use this bunker mode as the immediate secure handoff layer. Remote sessions get a `bunker://` URI, not an `nsec`. Keep the current scope narrow, then add ACL persistence, URI/secret lifecycle policy, and relay-management UX before treating this as general-purpose signing infrastructure.

カスタムsignet Bitcoinの立て方 Umbrel v0.5版

※スポットライトから移植した古い記事です。参考程度に。 これを参考にしてUmbrelのBitcoin Nodeをカスタムsignetノードにする。 以下メモ書きご容赦。備忘録程度に書き留めました。 メインネットとは共存できない。Bitcoinに依存する全てのアプリを削除しなければならない。よって実験機に導入すべき。 <手順> 1.Umbrel Bitcoin Nodeアプリのadvance settingでsignetを選択。 2.CLI appスクリプトでbitcoinを止める。 ``` cd umbrel/scripts ./app stop bitcoin ``` 3.bitcoin.conf, umbrel-bitcoin.conf以外を削除 ``` ディレクトリの場所は ~/umbrel/app-data/bitcoin/data/bitcoin ``` 4.umbrel-bitcoin.confをsu権限で編集。末尾にsignetchallengeを追加。 ``` [signet] bind=0.0.0.0:8333 bind=10.21.21.8:8334=onion # 51,21,<公開鍵>,51,ae signetchallenge=5121<公開鍵>51ae ``` 5.appスクリプトでbitcoinを開始。 ``` cd ~/umbrel/scripts ./app start bitcoin ``` 6.適当にディレクトリを作りgithubからbitcoindのソースをクローン。 7.bitcoindのバイナリをダウンロード、bitcoin-cliおよびbitcoin-utilを~/.local/binに置く。6.のソースからビルドしても良い。ビルド方法は自分で調べて。 8.bitcondにマイニング用のウォレットを作成 ``` alias bcli='docker exec -it bitcoin_bitcoind_1 bitcoin-cli -signet -rpcconnect=10.21.21.8 -rpcport=8332 -rpcuser=umbrel -rpcpassword=<パスワード>' # ウォレットを作る。 bcli createwallet "mining" false true "" false false # 秘密鍵をインポート bcli importprivkey "<秘密鍵>" ``` RPCパスワードは以下で確認 ``` cat ~/umbrel/.env | grep BITCOIN_RPC_PASS ``` 9.ソースにあるbitcoin/contrib/signet/minerスクリプトを使ってマイニング ``` cd <ダウンロードしたディレクトリ>/bitcoin/contrib/signet # 難易度の算出 ./miner \ --cli="bitcoin-cli -signet -rpcconnect=10.21.21.8 -rpcport=8332 -rpcuser=umbrel -rpcpassword=<パスワード>" calibrate \ --grind-cmd="bitcoin-util grind" --seconds 30 ★私の環境で30秒指定したら nbits=1d4271e7 と算出された。実際にこれで動かすと2分30になるけど... # ジェネシスブロック生成 ./miner \ --cli="bitcoin-cli -signet -rpcconnect=10.21.21.8 -rpcport=8332 -rpcuser=umbrel -rpcpassword=<パスワード>" generate \ --address <ビットコインアドレス> \ --grind-cmd="bitcoin-util grind" --nbits=1d4271e7 \ --set-block-time=$(date +%s) # 継続的にマイニング ./miner \ --cli="bitcoin-cli -signet -rpcconnect=10.21.21.8 -rpcport=8332 -rpcuser=umbrel -rpcpassword=<パスワード>" generate \ --address <ビットコインアドレス> \ --grind-cmd="bitcoin-util grind" --nbits=1d4271e7 \ --ongoing ``` ここまでやればカスタムsignetでビットコインノードが稼働する。