You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Add verify_batch_with_errors to log detailed verification failures
- Log errors to browser console instead of swallowing them
- Use serde_json for canonical event serialization in make_id
- Add tests for events with special characters and user's failing event
// Reuse a single String buffer across iterations to avoid repeated heap allocation.
21
-
letmut id_buf = String::with_capacity(512);
22
18
loop{
23
19
ev.tags[nonce_tag_idx][1] = ctr.to_string();
24
20
25
-
make_id_into(ev,&mut id_buf);
26
-
let digest = sha256::digest(id_buf.as_bytes());
21
+
let id_hex = make_id(ev);
22
+
let digest = sha256::digest(id_hex.as_bytes());
27
23
ifcount_leading_zeros(&digest) >= target {
28
24
ev.id = Some(digest);
29
25
break;
@@ -62,52 +58,10 @@ fn hex_nibble(c: u8) -> u8 {
62
58
}
63
59
}
64
60
65
-
/// Write the canonical Nostr event serialisation into `buf`, clearing it first.
66
-
/// Avoids allocating intermediate `Vec<String>` for the tags.
67
-
fnmake_id_into(ev:&Event,buf:&mutString){
68
-
buf.clear();
69
-
buf.push_str("[0,\"");
70
-
buf.push_str(&ev.pubkey);
71
-
buf.push_str("\",");
72
-
let _ = write!(buf,"{}", ev.created_at);
73
-
buf.push(',');
74
-
let _ = write!(buf,"{}", ev.kind);
75
-
buf.push_str(",[");
76
-
for(ti, tag)in ev.tags.iter().enumerate(){
77
-
if ti > 0{
78
-
buf.push(',');
79
-
}
80
-
buf.push('[');
81
-
for(vi, val)in tag.iter().enumerate(){
82
-
if vi > 0{
83
-
buf.push(',');
84
-
}
85
-
buf.push('"');
86
-
for ch in val.chars(){
87
-
match ch {
88
-
'"' => buf.push_str("\\\""),
89
-
'\\' => buf.push_str("\\\\"),
90
-
'\n' => buf.push_str("\\n"),
91
-
'\r' => buf.push_str("\\r"),
92
-
'\t' => buf.push_str("\\t"),
93
-
c => buf.push(c),
94
-
}
95
-
}
96
-
buf.push('"');
97
-
}
98
-
buf.push(']');
99
-
}
100
-
buf.push_str("],\"");
101
-
buf.push_str(&ev.content);
102
-
buf.push_str("\"]");
103
-
}
104
-
105
-
/// Compute the canonical Nostr event ID (SHA-256 hex of the serialised commitment).
106
-
/// Public so `verify.rs` and benchmarks can reuse it directly.
61
+
/// Write the canonical Nostr event serialisation using serde_json for correct escaping.
107
62
pubfnmake_id(ev:&Event) -> String{
108
-
letmut buf = String::with_capacity(512);
109
-
make_id_into(ev,&mut buf);
110
-
sha256::digest(buf.as_bytes())
63
+
let payload = serde_json::json!([0, ev.pubkey, ev.created_at, ev.kind, ev.tags, ev.content]);
64
+
sha256::digest(payload.to_string().as_bytes())
111
65
}
112
66
113
67
#[cfg(test)]
@@ -137,6 +91,36 @@ mod tests {
137
91
assert_eq!(super::make_id(&ev), ev.id.unwrap())
138
92
}
139
93
94
+
#[test]
95
+
fnmake_id_with_special_chars_in_content(){
96
+
let ev = Event::deserialize(json!({
97
+
"content":"{\"about\":\"mar - the main character, might be a girl\\n\\ncatoshi - the black cat, definitely a cat\",\"banner\":\"https://mar101xy.com/images/mar101xy-profile-cover.jpg\",\"bot\":false,\"display_name\":\"mar\",\"lud16\":\"mar101xy@walletofsatoshi.com\",\"nip05\":\"mar@mar101xy.com\",\"picture\":\"https://mar101xy.com/images/avatar.jpg\",\"displayName\":\"mar\",\"fields\":[[\"test\",\"testing ditto\"],[\"gender\",\"testing gender\"]],\"name\":\"mar\"}",
"content":"{\"name\":\"TheGrinder\",\"about\":\"Sovereign, creator of bitcoins, future owner of Mars and grinder of many things...\\n0863F34D0311FC550226F06A376B54D5650980FB\",\"picture\":\"https://i.nostr.build/TghNVYXqMe7knx7P.jpg\",\"banner\":\"https://nostr.build/i/094828ef504cb05424a9680db23d37db3cf02f05ede1d33528c5c5f9872db66e.jpg\",\"displayName\":\"TheGrinder\",\"lud16\":\"thegrinder@rizful.com\",\"display_name\":\"TheGrinder\",\"website\":\"https://zap.stream/thegrinder\",\"nip05\":\"thegrinder@nostrplebs.com\"}",
let profile_with_newlines = Event::deserialize(json!({
213
+
"content":"{\"about\":\"mar - the main character, might be a girl\\n\\ncatoshi - the black cat, definitely a cat\",\"banner\":\"https://mar101xy.com/images/mar101xy-profile-cover.jpg\",\"bot\":false,\"display_name\":\"mar\",\"lud16\":\"mar101xy@walletofsatoshi.com\",\"nip05\":\"mar@mar101xy.com\",\"picture\":\"https://mar101xy.com/images/avatar.jpg\",\"displayName\":\"mar\",\"fields\":[[\"test\",\"testing ditto\"],[\"gender\",\"testing gender\"]],\"name\":\"mar\"}",
let profile_with_escaped_backslash = Event::deserialize(json!({
223
+
"content":"{\"name\":\"TheGrinder\",\"about\":\"Sovereign, creator of bitcoins, future owner of Mars and grinder of many things...\\n0863F34D0311FC550226F06A376B54D5650980FB\",\"picture\":\"https://i.nostr.build/TghNVYXqMe7knx7P.jpg\",\"banner\":\"https://nostr.build/i/094828ef504cb05424a9680db23d37db3cf02f05ede1d33528c5c5f9872db66e.jpg\",\"displayName\":\"TheGrinder\",\"lud16\":\"thegrinder@rizful.com\",\"display_name\":\"TheGrinder\",\"website\":\"https://zap.stream/thegrinder\",\"nip05\":\"thegrinder@nostrplebs.com\"}",
0 commit comments