Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format nostr submodule #347

Merged
merged 1 commit into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ ruff-check:
poetry run ruff check .

black:
poetry run black . --exclude cashu/nostr
poetry run black .

black-check:
poetry run black . --exclude cashu/nostr --check
poetry run black . --check

mypy:
poetry run mypy cashu --ignore-missing
Expand Down
33 changes: 23 additions & 10 deletions cashu/nostr/bech32.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,25 @@

from enum import Enum


class Encoding(Enum):
"""Enumeration type to list the various supported encodings."""

BECH32 = 1
BECH32M = 2


CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
BECH32M_CONST = 0x2bc830a3
BECH32M_CONST = 0x2BC830A3


def bech32_polymod(values):
"""Internal function that computes the Bech32 checksum."""
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
generator = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3]
chk = 1
for value in values:
top = chk >> 25
chk = (chk & 0x1ffffff) << 5 ^ value
chk = (chk & 0x1FFFFFF) << 5 ^ value
for i in range(5):
chk ^= generator[i] if ((top >> i) & 1) else 0
return chk
Expand All @@ -57,6 +61,7 @@ def bech32_verify_checksum(hrp, data):
return Encoding.BECH32M
return None


def bech32_create_checksum(hrp, data, spec):
"""Compute the checksum values given HRP and data."""
values = bech32_hrp_expand(hrp) + data
Expand All @@ -68,26 +73,29 @@ def bech32_create_checksum(hrp, data, spec):
def bech32_encode(hrp, data, spec):
"""Compute a Bech32 string given HRP and data values."""
combined = data + bech32_create_checksum(hrp, data, spec)
return hrp + '1' + ''.join([CHARSET[d] for d in combined])
return hrp + "1" + "".join([CHARSET[d] for d in combined])


def bech32_decode(bech):
"""Validate a Bech32/Bech32m string, and determine HRP and data."""
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
(bech.lower() != bech and bech.upper() != bech)):
if (any(ord(x) < 33 or ord(x) > 126 for x in bech)) or (
bech.lower() != bech and bech.upper() != bech
):
return (None, None, None)
bech = bech.lower()
pos = bech.rfind('1')
pos = bech.rfind("1")
if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
return (None, None, None)
if not all(x in CHARSET for x in bech[pos+1:]):
if not all(x in CHARSET for x in bech[pos + 1 :]):
return (None, None, None)
hrp = bech[:pos]
data = [CHARSET.find(x) for x in bech[pos+1:]]
data = [CHARSET.find(x) for x in bech[pos + 1 :]]
spec = bech32_verify_checksum(hrp, data)
if spec is None:
return (None, None, None)
return (hrp, data[:-6], spec)


def convertbits(data, frombits, tobits, pad=True):
"""General power-of-2 base conversion."""
acc = 0
Expand Down Expand Up @@ -123,7 +131,12 @@ def decode(hrp, addr):
return (None, None)
if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
return (None, None)
if data[0] == 0 and spec != Encoding.BECH32 or data[0] != 0 and spec != Encoding.BECH32M:
if (
data[0] == 0
and spec != Encoding.BECH32
or data[0] != 0
and spec != Encoding.BECH32M
):
return (None, None)
return (data[0], decoded)

Expand Down
10 changes: 5 additions & 5 deletions cashu/nostr/client/cbc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from Cryptodome import Random
from Cryptodome.Cipher import AES

Expand All @@ -11,10 +10,10 @@

BLOCK_SIZE = 16


class AESCipher(object):
"""This class is compatible with crypto.createCipheriv('aes-256-cbc')
"""This class is compatible with crypto.createCipheriv('aes-256-cbc')"""

"""
def __init__(self, key=None):
self.key = key

Expand All @@ -33,9 +32,10 @@ def encrypt(self, plain_text):
def decrypt(self, iv, enc_text):
cipher = AES.new(self.key, AES.MODE_CBC, iv=iv)
return self.unpad(cipher.decrypt(enc_text).decode("UTF-8"))



if __name__ == "__main__":
aes = AESCipher(key=key)
iv, enc_text = aes.encrypt(plain_text)
dec_text = aes.decrypt(iv, enc_text)
print(dec_text)
print(dec_text)
8 changes: 4 additions & 4 deletions cashu/nostr/delegation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@ class Delegation:
delegator_pubkey: str
delegatee_pubkey: str
event_kind: int
duration_secs: int = 30*24*60 # default to 30 days
duration_secs: int = 30 * 24 * 60 # default to 30 days
signature: str = None # set in PrivateKey.sign_delegation

@property
def expires(self) -> int:
return int(time.time()) + self.duration_secs

@property
def conditions(self) -> str:
return f"kind={self.event_kind}&created_at<{self.expires}"

@property
def delegation_token(self) -> str:
return f"nostr:delegation:{self.delegatee_pubkey}:{self.conditions}"

def get_tag(self) -> list[str]:
""" Called by Event """
"""Called by Event"""
return [
"delegation",
self.delegator_pubkey,
Expand Down
3 changes: 2 additions & 1 deletion cashu/nostr/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def __post_init__(self):
def id(self) -> str:
if self.content is None:
raise Exception(
"EncryptedDirectMessage `id` is undefined until its message is encrypted and stored in the `content` field"
"EncryptedDirectMessage `id` is undefined until its message is"
" encrypted and stored in the `content` field"
)
return super().id
9 changes: 7 additions & 2 deletions cashu/nostr/message_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ class ClientMessageType:
REQUEST = "REQ"
CLOSE = "CLOSE"


class RelayMessageType:
EVENT = "EVENT"
NOTICE = "NOTICE"
END_OF_STORED_EVENTS = "EOSE"

@staticmethod
def is_valid(type: str) -> bool:
if type == RelayMessageType.EVENT or type == RelayMessageType.NOTICE or type == RelayMessageType.END_OF_STORED_EVENTS:
if (
type == RelayMessageType.EVENT
or type == RelayMessageType.NOTICE
or type == RelayMessageType.END_OF_STORED_EVENTS
):
return True
return False
return False
10 changes: 8 additions & 2 deletions cashu/nostr/pow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .event import Event
from .key import PrivateKey


def zero_bits(b: int) -> int:
n = 0

Expand All @@ -14,18 +15,22 @@ def zero_bits(b: int) -> int:

return 7 - n


def count_leading_zero_bits(hex_str: str) -> int:
total = 0
for i in range(0, len(hex_str) - 2, 2):
bits = zero_bits(int(hex_str[i:i+2], 16))
bits = zero_bits(int(hex_str[i : i + 2], 16))
total += bits

if bits != 8:
break

return total

def mine_event(content: str, difficulty: int, public_key: str, kind: int, tags: list=[]) -> Event:

def mine_event(
content: str, difficulty: int, public_key: str, kind: int, tags: list = []
) -> Event:
all_tags = [["nonce", "1", str(difficulty)]]
all_tags.extend(tags)

Expand All @@ -43,6 +48,7 @@ def mine_event(content: str, difficulty: int, public_key: str, kind: int, tags:

return Event(public_key, content, created_at, kind, all_tags, event_id)


def mine_key(difficulty: int) -> PrivateKey:
sk = PrivateKey()
num_leading_zero_bits = count_leading_zero_bits(sk.public_key.hex())
Expand Down
3 changes: 2 additions & 1 deletion cashu/nostr/relay_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def publish_event(self, event: Event):

if not event.verify():
raise RelayException(
f"Could not publish {event.id}: failed to verify signature {event.signature}"
f"Could not publish {event.id}: failed to verify signature"
f" {event.signature}"
)
self.publish_message(event.to_message())
8 changes: 3 additions & 5 deletions cashu/nostr/subscription.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from .filter import Filters


class Subscription:
def __init__(self, id: str, filters: Filters=None) -> None:
def __init__(self, id: str, filters: Filters = None) -> None:
self.id = id
self.filters = filters

def to_json_object(self):
return {
"id": self.id,
"filters": self.filters.to_json_array()
}
return {"id": self.id, "filters": self.filters.to_json_array()}
Loading