mirror of
https://github.com/aljazceru/python-nostr.git
synced 2025-12-18 14:54:23 +01:00
Integrate Event and RelayManager w/validity checking (#30)
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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,8 +57,11 @@ 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 {
|
||||
def to_message(self) -> str:
|
||||
return json.dumps(
|
||||
[
|
||||
ClientMessageType.EVENT,
|
||||
{
|
||||
"id": self.id,
|
||||
"pubkey": self.public_key,
|
||||
"created_at": self.created_at,
|
||||
@@ -65,3 +70,5 @@ class Event():
|
||||
"content": self.content,
|
||||
"sig": self.signature
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
@@ -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] = {}
|
||||
@@ -41,3 +52,12 @@ class RelayManager:
|
||||
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())
|
||||
|
||||
30
test/test_relay_manager.py
Normal file
30
test/test_relay_manager.py
Normal 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)
|
||||
Reference in New Issue
Block a user