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 = Event(private_key.public_key.hex(), "Hello Nostr")
|
||||||
event.sign(private_key.hex())
|
event.sign(private_key.hex())
|
||||||
|
|
||||||
message = json.dumps([ClientMessageType.EVENT, event.to_json_object()])
|
relay_manager.publish_event(event)
|
||||||
relay_manager.publish_message(message)
|
|
||||||
time.sleep(1) # allow the messages to send
|
time.sleep(1) # allow the messages to send
|
||||||
|
|
||||||
relay_manager.close_connections()
|
relay_manager.close_connections()
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ from enum import IntEnum
|
|||||||
from secp256k1 import PrivateKey, PublicKey
|
from secp256k1 import PrivateKey, PublicKey
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
|
|
||||||
|
from nostr.message_type import ClientMessageType
|
||||||
|
|
||||||
|
|
||||||
class EventKind(IntEnum):
|
class EventKind(IntEnum):
|
||||||
SET_METADATA = 0
|
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)
|
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)
|
return pub_key.schnorr_verify(bytes.fromhex(event_id), bytes.fromhex(self.signature), None, raw=True)
|
||||||
|
|
||||||
def to_json_object(self) -> dict:
|
def to_message(self) -> str:
|
||||||
return {
|
return json.dumps(
|
||||||
"id": self.id,
|
[
|
||||||
"pubkey": self.public_key,
|
ClientMessageType.EVENT,
|
||||||
"created_at": self.created_at,
|
{
|
||||||
"kind": self.kind,
|
"id": self.id,
|
||||||
"tags": self.tags,
|
"pubkey": self.public_key,
|
||||||
"content": self.content,
|
"created_at": self.created_at,
|
||||||
"sig": self.signature
|
"kind": self.kind,
|
||||||
}
|
"tags": self.tags,
|
||||||
|
"content": self.content,
|
||||||
|
"sig": self.signature
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
|
import json
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from .event import Event
|
||||||
from .filter import Filters
|
from .filter import Filters
|
||||||
from .message_pool import MessagePool
|
from .message_pool import MessagePool
|
||||||
|
from .message_type import ClientMessageType
|
||||||
from .relay import Relay, RelayPolicy
|
from .relay import Relay, RelayPolicy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RelayException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RelayManager:
|
class RelayManager:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.relays: dict[str, Relay] = {}
|
self.relays: dict[str, Relay] = {}
|
||||||
@@ -40,4 +51,13 @@ class RelayManager:
|
|||||||
for relay in self.relays.values():
|
for relay in self.relays.values():
|
||||||
if relay.policy.should_write:
|
if relay.policy.should_write:
|
||||||
relay.publish(message)
|
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