feat: fix NIP-07 signing to use node Nostr key, add test script

Added node.nostr-sign RPC that uses the node-level Nostr key (matching
getPublicKey), fixing pubkey mismatch where identity.nostr-sign used a
different key. Updated appLauncher to call node.nostr-sign. Added
nostr_sign_hash() to nostr_discovery.rs. Created test-nip07.sh with
11 automated checks (INSTALL-02).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-13 03:18:45 +00:00
co-authored by Claude Opus 4.6
parent a137c137a2
commit 540836f3d6
7 changed files with 242 additions and 15 deletions
+41
View File
@@ -114,6 +114,47 @@ impl RpcHandler {
}))
}
/// Sign a Nostr event with the node's Nostr key.
/// Accepts full event object, computes NIP-01 hash, returns signed event.
pub(super) async fn handle_node_nostr_sign(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.unwrap_or_default();
let identity_dir = self.config.data_dir.join("identity");
let pubkey_hex = nostr_discovery::get_nostr_pubkey(&identity_dir).await?;
let event = params.get("event")
.ok_or_else(|| anyhow::anyhow!("Missing 'event' parameter"))?;
let kind = event.get("kind").and_then(|v| v.as_u64()).unwrap_or(1);
let content = event.get("content").and_then(|v| v.as_str()).unwrap_or("");
let created_at = event.get("created_at").and_then(|v| v.as_u64())
.unwrap_or_else(|| std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs());
let tags = event.get("tags").cloned().unwrap_or_else(|| serde_json::json!([]));
// NIP-01 serialization: [0, pubkey, created_at, kind, tags, content]
let serialized = serde_json::json!([0, pubkey_hex, created_at, kind, tags, content]);
let serialized_str = serde_json::to_string(&serialized)?;
use sha2::{Sha256, Digest};
let hash = Sha256::digest(serialized_str.as_bytes());
let event_hash_hex = hex::encode(hash);
let signature = nostr_discovery::nostr_sign_hash(&identity_dir, &event_hash_hex).await?;
Ok(serde_json::json!({
"id": event_hash_hex,
"pubkey": pubkey_hex,
"created_at": created_at,
"kind": kind,
"tags": tags,
"content": content,
"sig": signature,
}))
}
pub(super) async fn handle_node_nostr_verify_revoked(&self) -> Result<serde_json::Value> {
let identity_dir = self.config.data_dir.join("identity");
let status = nostr_discovery::verify_revocation(