Skip to content

Commit

Permalink
Wallet/fix_nostr_timeout (#376)
Browse files Browse the repository at this point in the history
* fix nostr receive

* split with amount pre 0.13

* drop 0.13.0 amount with split compatibility
  • Loading branch information
callebtc authored Dec 3, 2023
1 parent 74c9317 commit 6c8b1a8
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 61 deletions.
20 changes: 1 addition & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,7 @@ MINT_URL=https://8333.space:3338
```bash
cashu info
```

Returns:
```bash
Version: 0.14.0
Debug: False
Cashu dir: /home/user/.cashu
Wallet: wallet
Mint URL: https://8333.space:3338
```
This command shows information about your wallet.

#### Check balance
```bash
Expand Down Expand Up @@ -159,21 +151,11 @@ You should see the encoded token. Copy the token and send it to another user suc
cashuAeyJwcm9vZnMiOiBbey...
```

You can now see that your available balance has dropped by the amount that you reserved for sending if you enter `cashu balance`:
```bash
Balance: 420 sat
```

#### Receive tokens
To receive tokens, another user enters:
```bash
cashu receive cashuAeyJwcm9vZnMiOiBbey...
```
You should see the balance increase:
```bash
Balance: 0 sat
Balance: 69 sat
```

# Starting the wallet API daemon
Nutshell wallet can be used in daemon mode that can be controlled through a REST API:
Expand Down
6 changes: 6 additions & 0 deletions cashu/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,9 @@ def get_amount(self):
def get_keysets(self):
return list(set([p.id for p in self.get_proofs()]))

def get_mints(self):
return list(set([t.mint for t in self.token if t.mint]))

@classmethod
def deserialize(cls, tokenv3_serialized: str) -> "TokenV3":
"""
Expand All @@ -542,6 +545,9 @@ def deserialize(cls, tokenv3_serialized: str) -> "TokenV3":
f"Token prefix not valid. Expected {prefix}."
)
token_base64 = tokenv3_serialized[len(prefix) :]
# if base64 string is not a multiple of 4, pad it with "="
token_base64 += "=" * (4 - len(token_base64) % 4)

token = json.loads(base64.urlsafe_b64decode(token_base64))
return cls.parse_obj(token)

Expand Down
2 changes: 1 addition & 1 deletion cashu/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

env = Env()

VERSION = "0.14.0"
VERSION = "0.14.1"


def find_env_file():
Expand Down
4 changes: 2 additions & 2 deletions cashu/nostr/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def get_dm(self, sender_publickey: PublicKey, callback_func=None, filter_kwargs=
message = json.dumps(request)
self.relay_manager.publish_message(message)

while True:
while any([r.connected for r in self.relay_manager.relays.values()]):
while self.relay_manager.message_pool.has_events():
event_msg = self.relay_manager.message_pool.get_event()
if "?iv=" in event_msg.event.content:
Expand All @@ -143,7 +143,7 @@ def get_dm(self, sender_publickey: PublicKey, callback_func=None, filter_kwargs=
time.sleep(0.1)

def subscribe(self, callback_func=None):
while True:
while any([r.connected for r in self.relay_manager.relays.values()]):
while self.relay_manager.message_pool.has_events():
event_msg = self.relay_manager.message_pool.get_event()
if callback_func:
Expand Down
15 changes: 6 additions & 9 deletions cashu/wallet/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,13 @@ def deserialize_token_from_string(token: str) -> TokenV3:
except Exception:
pass

# ----- receive token -----
if token.startswith("cashu"):
tokenObj = TokenV3.deserialize(token)
assert len(tokenObj.token), Exception("no proofs in token")
assert len(tokenObj.token[0].proofs), Exception("no proofs in token")
return tokenObj

# deserialize token
# dtoken = json.loads(base64.urlsafe_b64decode(token))
tokenObj = TokenV3.deserialize(token)

# tokenObj = TokenV2.parse_obj(dtoken)
assert len(tokenObj.token), Exception("no proofs in token")
assert len(tokenObj.token[0].proofs), Exception("no proofs in token")
return tokenObj
raise Exception("Invalid token")


async def receive(
Expand Down
36 changes: 18 additions & 18 deletions cashu/wallet/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,24 @@ async def m007_nostr(db: Database):
"""
Stores timestamps of nostr operations.
"""
# async with db.connect() as conn:
# await conn.execute("""
# CREATE TABLE IF NOT EXISTS nostr (
# type TEXT NOT NULL,
# last TIMESTAMP DEFAULT NULL
# )
# """)
# await conn.execute(
# """
# INSERT INTO nostr
# (type, last)
# VALUES (?, ?)
# """,
# (
# "dm",
# None,
# ),
# )
async with db.connect() as conn:
await conn.execute("""
CREATE TABLE IF NOT EXISTS nostr (
type TEXT NOT NULL,
last TIMESTAMP DEFAULT NULL
)
""")
await conn.execute(
"""
INSERT INTO nostr
(type, last)
VALUES (?, ?)
""",
(
"dm",
None,
),
)


async def m008_keysets_add_public_keys(db: Database):
Expand Down
27 changes: 22 additions & 5 deletions cashu/wallet/nostr.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import asyncio
import datetime
import threading

import click
from httpx import ConnectError
from loguru import logger

from cashu.core.base import TokenV3

from ..core.settings import settings
from ..nostr.client.client import NostrClient
from ..nostr.event import Event
Expand Down Expand Up @@ -97,7 +100,7 @@ async def send_nostr(

async def receive_nostr(
wallet: Wallet,
):
) -> NostrClient:
if settings.nostr_private_key is None:
print(
"Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in"
Expand All @@ -113,18 +116,28 @@ async def receive_nostr(
await asyncio.sleep(2)

def get_token_callback(event: Event, decrypted_content: str):
date_str = datetime.datetime.fromtimestamp(event.created_at).strftime(
"%Y-%m-%d %H:%M:%S"
)
logger.debug(
f"From {event.public_key[:3]}..{event.public_key[-3:]}: {decrypted_content}"
f"From {event.public_key[:3]}..{event.public_key[-3:]} on {date_str}:"
f" {decrypted_content}"
)
# split the content into words
words = decrypted_content.split(" ")
for w in words:
try:
logger.trace(
f"Nostr: setting last check timestamp to {event.created_at}"
"Nostr: setting last check timestamp to"
f" {event.created_at} ({date_str})"
)
# call the receive method
tokenObj = deserialize_token_from_string(w)
tokenObj: TokenV3 = deserialize_token_from_string(w)
print(
f"Receiving {tokenObj.get_amount()} sat on mint"
f" {tokenObj.get_mints()[0]} from nostr user {event.public_key} at"
f" {date_str}"
)
asyncio.run(
receive(
wallet,
Expand All @@ -143,8 +156,11 @@ def get_token_callback(event: Event, decrypted_content: str):

# determine timestamp of last check so we don't scan all historical DMs
last_check = await get_nostr_last_check_timestamp(db=wallet.db)
logger.debug(f"Last check: {last_check}")
if last_check:
date_str = datetime.datetime.fromtimestamp(last_check).strftime(
"%Y-%m-%d %H:%M:%S"
)
logger.debug(f"Last check: {date_str}")
last_check -= 60 * 60 # 1 hour tolerance

logger.debug("Starting Nostr DM thread")
Expand All @@ -154,3 +170,4 @@ def get_token_callback(event: Event, decrypted_content: str):
name="Nostr DM",
)
t.start()
return client
11 changes: 5 additions & 6 deletions cashu/wallet/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ async def wrapper(self, *args, **kwargs):
proxies=proxies_dict, # type: ignore
headers=headers_dict,
base_url=self.url,
timeout=None if settings.debug else 5,
timeout=5,
)
return await func(self, *args, **kwargs)

Expand Down Expand Up @@ -198,9 +198,9 @@ async def _load_mint_keys(self, keyset_id: Optional[str] = None) -> None:

if keyset_id and keyset_id != keyset.id:
# NOTE: Because of the upcoming change of how to calculate keyset ids
# with version 0.14.0, we overwrite the calculated keyset id with the
# with version 0.15.0, we overwrite the calculated keyset id with the
# requested one. This is a temporary fix and should be removed once all
# ecash is transitioned to 0.14.0.
# ecash is transitioned to 0.15.0.
logger.debug(
f"Keyset ID mismatch: {keyset_id} != {keyset.id}. This can happen due"
" to a version upgrade."
Expand Down Expand Up @@ -732,9 +732,7 @@ async def redeem(
proofs (List[Proof]): Proofs to be redeemed.
"""
# verify DLEQ of incoming proofs
logger.debug("Verifying DLEQ of incoming proofs.")
self.verify_proofs_dleq(proofs)
logger.debug("DLEQ verified.")
return await self.split(proofs, sum_proofs(proofs))

async def split(
Expand Down Expand Up @@ -928,7 +926,8 @@ def verify_proofs_dleq(self, proofs: List[Proof]):
):
raise Exception("DLEQ proof invalid.")
else:
logger.debug("DLEQ proof valid.")
logger.trace("DLEQ proof valid.")
logger.debug("Verified incoming DLEQ proofs.")

async def _construct_proofs(
self,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setuptools.setup(
name="cashu",
version="0.14.0",
version="0.14.1",
description="Ecash wallet and mint for Bitcoin Lightning",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down

0 comments on commit 6c8b1a8

Please sign in to comment.