Skip to content
Snippets Groups Projects
Commit 6cca1a8e authored by Johannes Hitzinger's avatar Johannes Hitzinger
Browse files

fixing git things?

parent b8dd47f2
No related branches found
No related tags found
No related merge requests found
@startuml
class Participant{
- secretKey
+ publicKey
+ publicIP
+ updateRemoteParticipants(new_rps)
+ findOffers(power, time)
+ findRequests(power, time)
}
class RemoteParticipant{
+ publicKey
+ publicIP
+ updateExchanges(new_exs)
}
abstract class Exchange{
power: Watt
pricePerWatt: Euro
}
class Trade
class Exchange
class Trade {
+ power: Watt
+ pricePerWatt: Euro
+ signature_offer
+ signature_request
+ verify_trade()
}
class Offer
class Request
Exchange <|-- Offer
Exchange <|-- Request
Exchange "1..n" - Trade
Participant "0..n" - RemoteParticipant
RemoteParticipant "0..n" - Exchange
Trade "1..1" - "n..1" Offer
Trade "1..1" - "n..1" Request
Trade "2" - Trade
@enduml
\ No newline at end of file
#from main import ureg,Q_
import locale
import time
from datetime import datetime,timedelta
class Trade:
pass
class Exchange:
def __init__(self, p: float, ppw: float):
self.__timestamp: time.time_ns()
def __init__(self,pk: bytes, p: float, ppw: float):
self.pubicKey: bytes = pk
self.timestamp: int = time.time_ns()
self.__isActive: bool = False
#self.__power = Q_(p, ureg.watt)
self.__pricePerWatt = locale.currency(ppw)
self.__trades: set[Trade] = set()
self.__sig: bytes #signed exchange hash when becoming active
\ No newline at end of file
self.__sig: bytes
def activate(self) -> None:
self.__isActive = True
def getActive(self) -> bool:
return self.__isActive
def is_min_now(self) -> bool:
now = datetime.now()
# Calculate the first second of the current minute
start_of_minute = datetime(now.year, now.month, now.day, now.hour, now.minute, 0)
start_of_minute_unix = int(start_of_minute.timestamp())
# Calculate the last second of the current minute
end_of_minute = start_of_minute + timedelta(seconds=59)
end_of_minute_unix = int(end_of_minute.timestamp())
if start_of_minute_unix <= self.timestamp <= end_of_minute_unix:
return True
else:
return False
def is_min_next(self) -> bool:
now = datetime.now()
# Calculate the first second of the next minute
start_of_minute = datetime(now.year, now.month, now.day, now.hour, now.minute, 0)
start_of_minute += timedelta(minutes=1)
start_of_minute_unix = int(start_of_minute.timestamp())
# Calculate the last second of the next minute
end_of_minute = start_of_minute + timedelta(seconds=59)
end_of_minute_unix = int(end_of_minute.timestamp())
if start_of_minute_unix <= self.timestamp <= end_of_minute_unix:
return True
else:
return False
\ No newline at end of file
import exchange
class Offer(exchange.Exchange):
def __init__(self, p: float, ppw: float):
exchange.Exchange.__init__(self, p, ppw)
def __init__(self,pk: bytes, p: float, ppw: float):
exchange.Exchange.__init__(self,pk, p, ppw)
# from main import ureg, Q_
import locale
import time
from datetime import datetime, timedelta
from random import randint
import ipaddress
import asyncio
import httpx
import jsonpickle
from dilithium import Dilithium
......@@ -24,10 +24,11 @@ from remoteparticipant import RemoteParticipant
from fastapi import APIRouter
import logging
logger = logging.getLogger(__name__)
import socket
def get_pub_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(0)
......@@ -45,8 +46,8 @@ def get_pub_ip():
class Participant:
def __init__(self, nid: str, dht_ep: set[ipaddress.IPv4Address],
ip: ipaddress = get_pub_ip()):
d1 = Dilithium(dilithium.dilithium.DEFAULT_PARAMETERS["dilithium3"])
self.__secretKey, self.__publicKey = d1.keygen(
self.dil = Dilithium(dilithium.dilithium.DEFAULT_PARAMETERS["dilithium3"])
self.__secretKey, self.__publicKey = self.dil.keygen(
[randint(0, numpy.iinfo('uint32').max), randint(0, numpy.iinfo('uint32').max),
randint(0, numpy.iinfo('uint32').max), randint(0, numpy.iinfo('uint32').max)])
self.fastRouter = APIRouter()
......@@ -55,10 +56,10 @@ class Participant:
self.publicIP: ipaddress.IPv4Address = ipaddress.IPv4Address(
ip) # set to current ipv4, confirm before each new round
self.knownIPs: set[ipaddress.IPv4Address] = set()
self.knownParticipants: set[RemoteParticipant] = set()
self.remoteParticipants: set[RemoteParticipant] = set()
self.availableExchanges: set[
Exchange] = set() # known available exchanges from other participants for next turns
self.nextExchanges: set[Exchange] = set() # own exchanges for next turn
self.nextExchange: Request|Offer # own exchange for next turn, either offering or requesting energy
self.activeTrades: set[Trade] = set() # own active trades for this turn
self.__tradeHistory: list[Trade] = [] # every own past trade
# self.__currentPower = Q_(0, ureg.watt) # real time power exchange with the grid
......@@ -68,7 +69,8 @@ class Participant:
# self.__projectedInhouseSupply = Q_(0, ureg.watt) # expected supply for next round
# register rest endpoints with fastapi
self.fastRouter.add_api_route("/get_remoteparticipants_asJSON", self.getremoteParticipants_asJSON, methods=["GET"])
self.fastRouter.add_api_route("/get_remoteparticipants_asJSON", self.getremoteParticipants_asJSON,
methods=["GET"])
self.fastRouter.add_api_route("/get_knownIPs", self.get_knownIPs, methods=["GET"])
# announce self on dht
asyncio.run(self.dht_startup())
......@@ -84,7 +86,8 @@ class Participant:
logger.info("dht_startup on " + self.publicIP.__str__())
for ip in self.dht_endpoints: # register participant on all dht endpoints
async with httpx.AsyncClient() as client:
await client.put("http://" + ip.__str__() + ":8000/addPeerTo/" + self.__dht_network_id + "?ip=" + self.publicIP.__str__())
await client.put(
"http://" + ip.__str__() + ":8000/addPeerTo/" + self.__dht_network_id + "?ip=" + self.publicIP.__str__())
async def dht_update_peers(self) -> None:
for ip in self.dht_endpoints:
......@@ -97,19 +100,37 @@ class Participant:
async def getremoteParticipants_asJSON(self):
all_remoteparticipants: set[RemoteParticipant] = set()
all_remoteparticipants.add(self.as_remoteParticipant())
all_remoteparticipants.update(self.knownParticipants)
all_remoteparticipants.update(self.remoteParticipants)
return jsonpickle.encode(all_remoteparticipants)
def update_remoteparticipants(self, new_rps: set[RemoteParticipant], target_rps: set[RemoteParticipant]):
for new_rp in new_rps:
for rp in target_rps:
if new_rp.publicKey == rp.publicKey: # found same participant
rp.
async def requestremoteParticipants(self) -> None:
all_remoteparticipants: set[RemoteParticipant] = set()
for ip in self.knownIPs:
url = 'http://' + ip.__str__() + ':8000/get_remoteparticipants_asJSON'
async with httpx.AsyncClient() as client:
response = await client.get(url)
remoteparticipants: set[RemoteParticipant] = jsonpickle.decode(response.json())
# some validation of remoteparticipants should happen, not in scope of this thesis
all_remoteparticipants.update(remoteparticipants)
self.knownParticipants.update(all_remoteparticipants)
if len(self.remoteParticipants) == 0: # initial discovery via dht
await self.dht_update_peers()
for ip in self.knownIPs:
try:
url = 'http://' + ip.__str__() + ':8000/get_remoteparticipants_asJSON'
async with httpx.AsyncClient() as client:
response = await client.get(url)
remoteparticipants: set[RemoteParticipant] = jsonpickle.decode(response.json())
# some validation of remoteparticipants should happen, not in scope of this thesis
all_remoteparticipants.update(remoteparticipants)
except httpx.HTTPError as err:
logger.error("httpx Error: " + err.__str__())
continue
self.remoteParticipants.update(all_remoteparticipants)
self.knownIPs.clear()
return
else: # continued peer updates without dht, periodic dht discovery should still happen to discover new users
async def get_knownIPs(self):
return jsonpickle.encode(self.knownIPs)
import ipaddress
import time
from datetime import datetime,timedelta
from pydantic.dataclasses import dataclass
......@@ -6,13 +8,33 @@ import exchange
class RemoteParticipant:
def __init__(self, pk: bytes, ip: ipaddress.IPv4Address, nex: set[exchange.Exchange]):
self.__publicKey: bytes = pk
def __init__(self, pk: bytes, ip: ipaddress.IPv4Address, nex: list[exchange.Exchange]):
self.publicKey: bytes = pk
self.publicIP: ipaddress.IPv4Address = ip
self.__nextExchanges: set[exchange.Exchange] = nex
self.nextExchanges: list[exchange.Exchange] = nex
self.timestamp = time.time_ns()
def __eq__(self, other):
return self.__publicKey == other.__publicKey
def update_nextExchanges(self, exchanges: list[exchange.Exchange]):
for new_ex in exchanges:
for ex in self.nextExchanges:
# both exchanges origin from same participant and are within the next minute
if new_ex.pubicKey == ex.pubicKey and new_ex.is_min_next() and ex.is_min_next():
ex.
def __hash__(self):
return super.__hash__(self)
\ No newline at end of file
def is_min_now(self) -> bool:
now = datetime.now()
# Calculate the first second of the current minute
start_of_minute = datetime(now.year, now.month, now.day, now.hour, now.minute, 0)
start_of_minute_unix = int(start_of_minute.timestamp())
# Calculate the last second of the current minute
end_of_minute = start_of_minute + timedelta(seconds=59)
end_of_minute_unix = int(end_of_minute.timestamp())
if start_of_minute_unix <= self.timestamp <= end_of_minute_unix:
return True
else:
return False
import exchange
class Request(exchange.Exchange):
def __init__(self, p: float, ppw: float):
exchange.Exchange.__init__(self, p,ppw)
class Request(exchange.Exchange):
def __init__(self, pk: bytes, p: float, ppw: float):
exchange.Exchange.__init__(self, pk, p, ppw)
......@@ -12,4 +12,5 @@ class Trade:
self.__request: request.Request = r
#self.__power = Q_(p, ureg.watt)
self.__pricePerWatt = locale.currency(ppw)
self.__sig: bytes
\ No newline at end of file
self.sig_off: bytes
self.sig_req: bytes
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment