feat: schnorr check in wasm

This commit is contained in:
Kieran 2023-12-12 22:46:36 +00:00
parent 9431b294c6
commit 8d6cdb3868
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
10 changed files with 97 additions and 4 deletions

View File

@ -2,7 +2,15 @@ import "./index.css";
import "@szhsin/react-menu/dist/index.css";
import "./fonts/inter.css";
import { compress, expand_filter, flat_merge, get_diff, pow, default as wasmInit } from "@snort/system-wasm";
import {
compress,
expand_filter,
flat_merge,
get_diff,
pow,
schnorr_verify,
default as wasmInit,
} from "@snort/system-wasm";
import WasmPath from "@snort/system-wasm/pkg/system_wasm_bg.wasm";
import { StrictMode } from "react";
@ -76,6 +84,9 @@ const WasmQueryOptimizer = {
compress: (all: Array<ReqFilter>) => {
return compress(all) as Array<ReqFilter>;
},
schnorrVerify: (id, sig, pubkey) => {
return schnorr_verify(id, sig, pubkey);
},
} as QueryOptimizer;
export class WasmPowWorker implements PowMiner {

View File

@ -644,6 +644,24 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "secp256k1"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5"
dependencies = [
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83"
dependencies = [
"cc",
]
[[package]]
name = "serde"
version = "1.0.188"
@ -736,6 +754,7 @@ dependencies = [
"hex",
"itertools 0.11.0",
"rand",
"secp256k1",
"serde",
"serde-wasm-bindgen",
"serde_json",

View File

@ -12,6 +12,7 @@ argon2 = "0.5.2"
console_error_panic_hook = "0.1.7"
hex = { version = "0.4.3", features = [], default-features = false }
itertools = "0.11.0"
secp256k1 = "0.28.0"
serde = { version = "1.0.188", features = ["derive"], default-features = false }
serde-wasm-bindgen = "0.5.0"
sha256 = { version = "1.4.0", features = [], default-features = false }

View File

@ -39,6 +39,13 @@ export function pow(val: any, target: any): any;
* @returns {any}
*/
export function argon2(password: any, salt: any): any;
/**
* @param {any} hash
* @param {any} sig
* @param {any} pub_key
* @returns {boolean}
*/
export function schnorr_verify(hash: any, sig: any, pub_key: any): boolean;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@ -51,6 +58,11 @@ export interface InitOutput {
readonly compress: (a: number, b: number) => void;
readonly pow: (a: number, b: number, c: number) => void;
readonly argon2: (a: number, b: number, c: number) => void;
readonly schnorr_verify: (a: number, b: number, c: number, d: number) => void;
readonly rustsecp256k1_v0_9_1_context_create: (a: number) => number;
readonly rustsecp256k1_v0_9_1_context_destroy: (a: number) => void;
readonly rustsecp256k1_v0_9_1_default_illegal_callback_fn: (a: number, b: number) => void;
readonly rustsecp256k1_v0_9_1_default_error_callback_fn: (a: number, b: number) => void;
readonly __wbindgen_malloc: (a: number, b: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;

View File

@ -361,6 +361,28 @@ export function argon2(password, salt) {
}
}
/**
* @param {any} hash
* @param {any} sig
* @param {any} pub_key
* @returns {boolean}
*/
export function schnorr_verify(hash, sig, pub_key) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.schnorr_verify(retptr, addHeapObject(hash), addHeapObject(sig), addHeapObject(pub_key));
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r2 = getInt32Memory0()[retptr / 4 + 2];
if (r2) {
throw takeObject(r1);
}
return r0 !== 0;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
function handleError(f, args) {
try {
return f.apply(this, args);

View File

@ -8,6 +8,11 @@ export function flat_merge(a: number, b: number): void;
export function compress(a: number, b: number): void;
export function pow(a: number, b: number, c: number): void;
export function argon2(a: number, b: number, c: number): void;
export function schnorr_verify(a: number, b: number, c: number, d: number): void;
export function rustsecp256k1_v0_9_1_context_create(a: number): number;
export function rustsecp256k1_v0_9_1_context_destroy(a: number): void;
export function rustsecp256k1_v0_9_1_default_illegal_callback_fn(a: number, b: number): void;
export function rustsecp256k1_v0_9_1_default_error_callback_fn(a: number, b: number): void;
export function __wbindgen_malloc(a: number, b: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
export function __wbindgen_add_to_stack_pointer(a: number): number;

View File

@ -1,6 +1,7 @@
extern crate console_error_panic_hook;
use argon2::{Argon2};
use secp256k1::{Message, Secp256k1, XOnlyPublicKey};
use serde::{Deserialize, Serialize};
use crate::filter::{FlatReqFilter, ReqFilter};
use wasm_bindgen::prelude::*;
@ -98,6 +99,20 @@ pub fn argon2(password: JsValue, salt: JsValue) -> Result<JsValue, JsValue> {
Ok(serde_wasm_bindgen::to_value(&hex::encode(key))?)
}
#[wasm_bindgen]
pub fn schnorr_verify(hash: JsValue, sig: JsValue, pub_key: JsValue) -> Result<bool, JsValue> {
console_error_panic_hook::set_once();
let msg_hex: String = serde_wasm_bindgen::from_value(hash)?;
let sig_hex: String = serde_wasm_bindgen::from_value(sig)?;
let pub_key_hex: String = serde_wasm_bindgen::from_value(pub_key)?;
let secp = Secp256k1::new();
let msg = Message::from_digest_slice(&hex::decode(msg_hex).unwrap()).unwrap();
let key = XOnlyPublicKey::from_slice(&hex::decode(pub_key_hex).unwrap()).unwrap();
let sig = secp256k1::schnorr::Signature::from_slice(&hex::decode(sig_hex).unwrap()).unwrap();
Ok(secp.verify_schnorr(&sig, &msg, &key).is_ok())
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -199,9 +199,12 @@ export class NostrSystem extends EventEmitter<NostrSystemEvents> implements Syst
this.#log("Rejecting invalid event %O", ev);
return;
}
if (this.checkSigs && !EventExt.verify(ev)) {
this.#log("Invalid sig %O", ev);
return;
if (this.checkSigs) {
const id = EventExt.createId(ev);
if (!this.#queryOptimizer.schnorrVerify(id, ev.sig, ev.pubkey)) {
this.#log("Invalid sig %O", ev);
return;
}
}
for (const [, v] of this.Queries) {

View File

@ -1,3 +1,4 @@
import { schnorr } from "@noble/curves/secp256k1";
import { ReqFilter } from "../nostr";
import { expandFilter } from "./request-expander";
import { flatMerge, mergeSimilar } from "./request-merger";
@ -24,6 +25,7 @@ export interface QueryOptimizer {
getDiff(prev: Array<ReqFilter>, next: Array<ReqFilter>): Array<FlatReqFilter>;
flatMerge(all: Array<FlatReqFilter>): Array<ReqFilter>;
compress(all: Array<ReqFilter>): Array<ReqFilter>;
schnorrVerify(hash: string, sig: string, pubkey: string): boolean;
}
export const DefaultQueryOptimizer = {
@ -43,4 +45,7 @@ export const DefaultQueryOptimizer = {
compress: (all: Array<ReqFilter>) => {
return mergeSimilar(all);
},
schnorrVerify: (hash, sig, pubkey) => {
return schnorr.verify(sig, hash, pubkey);
},
} as QueryOptimizer;