Integrate Event and RelayManager w/validity checking (#30)

This commit is contained in:
kdmukai
2023-01-19 17:28:57 -06:00
committed by GitHub
parent 3881bce9ec
commit d9fb70e8ed
4 changed files with 69 additions and 13 deletions

View File

@@ -51,8 +51,7 @@ private_key = PrivateKey()
event = Event(private_key.public_key.hex(), "Hello Nostr")
event.sign(private_key.hex())
message = json.dumps([ClientMessageType.EVENT, event.to_json_object()])
relay_manager.publish_message(message)
relay_manager.publish_event(event)
time.sleep(1) # allow the messages to send
relay_manager.close_connections()

View File

@@ -4,6 +4,8 @@ from enum import IntEnum
from secp256k1 import PrivateKey, PublicKey
from hashlib import sha256
from nostr.message_type import ClientMessageType
class EventKind(IntEnum):
SET_METADATA = 0
@@ -55,13 +57,18 @@ class Event():
event_id = Event.compute_id(self.public_key, self.created_at, self.kind, self.tags, self.content)
return pub_key.schnorr_verify(bytes.fromhex(event_id), bytes.fromhex(self.signature), None, raw=True)
def to_json_object(self) -> dict:
return {
"id": self.id,
"pubkey": self.public_key,
"created_at": self.created_at,
"kind": self.kind,
"tags": self.tags,
"content": self.content,
"sig": self.signature
}
def to_message(self) -> str:
return json.dumps(
[
ClientMessageType.EVENT,
{
"id": self.id,
"pubkey": self.public_key,
"created_at": self.created_at,
"kind": self.kind,
"tags": self.tags,
"content": self.content,
"sig": self.signature
}
]
)

View File

@@ -1,8 +1,19 @@
import json
import threading
from .event import Event
from .filter import Filters
from .message_pool import MessagePool
from .message_type import ClientMessageType
from .relay import Relay, RelayPolicy
class RelayException(Exception):
pass
class RelayManager:
def __init__(self) -> None:
self.relays: dict[str, Relay] = {}
@@ -40,4 +51,13 @@ class RelayManager:
for relay in self.relays.values():
if relay.policy.should_write:
relay.publish(message)
def publish_event(self, event: Event):
""" Verifies that the Event is publishable before submitting it to relays """
if event.signature is None:
raise RelayException(f"Could not publish {event.id}: must be signed")
if not event.verify():
raise RelayException(f"Could not publish {event.id}: failed to verify signature {event.signature}")
self.publish_message(event.to_message())

View File

@@ -0,0 +1,30 @@
import pytest
from nostr.event import Event
from nostr.key import PrivateKey
from nostr.relay_manager import RelayManager, RelayException
def test_only_relay_valid_events():
""" publish_event raise a RelayException if an Event fails verification """
pk = PrivateKey()
event = Event(
public_key=pk.public_key.hex(),
content="Hello, world!",
)
relay_manager = RelayManager()
# Deliberately forget to sign the Event
with pytest.raises(RelayException) as e:
relay_manager.publish_event(event)
assert "must be signed" in str(e)
# Attempt to relay with a nonsense signature
event.signature = '0' * 32
with pytest.raises(RelayException) as e:
relay_manager.publish_event(event)
assert "failed to verify" in str(e)
# Properly signed Event can be relayed
event.sign(pk.hex())
relay_manager.publish_event(event)