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

Implementing logic #7

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0dbf21f
feat: implement enabling shield
Oct 30, 2024
9648ecb
fix: fixes after code review
Nov 5, 2024
6f321c7
feat: shield logic finished
Nov 7, 2024
23fccc4
fix: code review fixes
Nov 8, 2024
290fc3d
feat: add serialization logic
Nov 9, 2024
1c69b99
feat: logic finished
Nov 11, 2024
6b4abe1
feat: encryption manager refactored
Nov 11, 2024
34a9cf7
feat: add memory implementation for some managers
Nov 11, 2024
168de86
feat: finish memory implementations for all managers along with full …
Nov 12, 2024
8f975a7
fix: finish tests for shield with needed fixes (there is still proble…
Nov 12, 2024
7f1873c
feat: back to EncryptionManager using ECIES library
Nov 13, 2024
4d7fba3
fix: added hash to manifest file to verify if content is the same
Nov 13, 2024
9802e2d
feat: implemented Route53AddressManager
Nov 14, 2024
16603b6
feat: implemented SQLAlchemyMinerShieldStateManager
Nov 14, 2024
6b24602
feat: implemented S3ManifestManager
Nov 15, 2024
82e330c
feat: added integration test
Nov 15, 2024
968f045
feat: filling AwsAddressManager, work in progress
Nov 22, 2024
935c2e6
feat: added possibility of specyfing IP in AwsAddressManager
Nov 22, 2024
6ba1675
feat: filling AwsAddressManager - creating ELB is working
Nov 22, 2024
2ac5dd7
feat: filling AwsAddressManager - creating HostedZone during ELB crea…
Nov 24, 2024
097b2de
feat: filling AwsAddressManager - creating alias DNS entry in Route53
Nov 24, 2024
dc62a30
feat: finished AwsAddressManager - added creating firewall
Nov 25, 2024
c9d3b75
feat: back to passing hosted_zone_id to AwsAddressManager
Dec 5, 2024
845ec8a
fix: tiny code review fixes
Dec 6, 2024
44ebe33
Add AWSClientFactory
grzegorz-leszczynski-reef Dec 25, 2024
840941e
Use pytest fixture in TestAddressManager
grzegorz-leszczynski-reef Dec 25, 2024
54de75f
Simplify code after CR
grzegorz-leszczynski-reef Dec 25, 2024
d2bc4a4
Upgrade handling AWS API errors
grzegorz-leszczynski-reef Dec 26, 2024
030cba1
Add project dependencies
grzegorz-leszczynski-reef Dec 26, 2024
5e27248
Apply ruff linter fixes
grzegorz-leszczynski-reef Dec 26, 2024
78ad8f2
Add MinerShieldFactory
grzegorz-leszczynski-reef Dec 27, 2024
4af7d75
Implement Validator
grzegorz-leszczynski-reef Dec 31, 2024
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
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,26 @@ The goal of this project is to implement a distributed and decentralized system
- Validators can request the connection information of miners from the subtensor network. This information is validated and
decrypted locally using the validator's private key.

## Communication Flow
## Basic Communication Flow

<!--
@startuml ./assets/diagrams/CommunicationFlow
participant Validator
participant Miner
participant GitHub
participant Storage
participant Bittensor
participant AddressManager
database Storage
database Bittensor
Validator -> Validator: Generate Validator key-pair
Validator -> GitHub: Publish public key along with HotKey
GitHub -> Miner: Fetch Validator info
Miner -> Miner: Encrypt Miner IP/Domain with Validator public key
Miner -> Storage: Add/update file with encrypted IPs/Domains for Validators
Validator -> Bittensor: Publish public key along with HotKey
Bittensor -> Miner: Fetch new Validator info
Miner -> AddressManager: Generate new address
Miner -> Miner: Encrypt generated address with Validator public key
Miner -> Storage: Update file with encrypted addresses for Validators
Miner -> Bittensor: Publish file location
Bittensor -> Validator: Fetch file location
Storage -> Validator: Fetch Miner file
Validator -> Validator: Decrypt Miner file entry encrypted for given Validator
Validator -> Miner: Send request using decrypted Miner IP/Domain
Validator -> Miner: Send request using decrypted Miner address
@enduml
-->

Expand Down
19 changes: 10 additions & 9 deletions assets/diagrams/CommunicationFlow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
102 changes: 73 additions & 29 deletions bt_ddos_shield/address.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,98 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum


class AddressType(Enum):
"""
Possible types of address.
"""
IP = "ip" # IPv4 address
IPV6 = "ipv6" # IPv6 address
DOMAIN = "domain" # domain name
IP = "ip" # IPv4 address
IPV6 = "ipv6" # IPv6 address
DOMAIN = "domain" # domain name
S3 = "s3" # address identifies S3 object (id is object name)
EC2 = "ec2" # address identifies EC2 instance (id is instance id)


class Address(ABC):
@dataclass
class Address:
"""
Class describing address, which redirects to original miner's server.
Class describing some address - domain or IP.
"""

def __init__(self, address_id, address_type: AddressType, address: str, port: int):
"""
Args:
address_id: Identifier (used by AddressManager) of the address. Type depends on the implementation.
address_type: Type of the address.
address: Address.
port: Port of the address.
"""
self.address_id = address_id
self.address_type = address_type
self.address = address
self.port = port
address_id: str
""" identifier (used by AbstractAddressManager implementation) of the address """
address_type: AddressType
address: str
port: int

def __repr__(self):
return f"Address(id={self.address_id}, type={self.address_type}, address={self.address}:{self.port})"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return f"Address(id={self.address_id}, type={self.address_type}, address={self.address}:{self.port})"
return f"Address(id={self.address_id}, address={self.address}:{self.port})"



class AddressSerializerException(Exception):
pass


class AddressDeserializationException(AddressSerializerException):
"""
Exception thrown when deserialization of address data fails.
"""
pass


class AbstractAddressSerializer(ABC):
"""
Class used to serialize and deserialize addresses.
"""

@abstractmethod
def encrypt(self) -> bytes:
def serialize(self, address: Address) -> bytes:
"""
Encrypts address data.

Returns:
bytes: Encrypted address data.
Serialize address data. Output format depends on the implementation.
"""
pass

@classmethod
@abstractmethod
def decrypt(cls, encrypted_data: bytes) -> Address:
def deserialize(self, serialized_data: bytes) -> Address:
"""
Create address from encrypted address data.
Deserialize address data. Throws AddressDeserializationException if data format is not recognized.

Args:
encrypted_data: Encrypted address data.

Returns:
Address: Created address.
serialized_data: Data serialized before by serialize method.
"""
pass


class DefaultAddressSerializer(AbstractAddressSerializer):
"""
Address serializer implementation which serialize address to string.
"""

encoding: str

def __init__(self, encoding: str = "utf-8"):
"""
Args:
encoding: Encoding used for transforming generated address string to bytes.
"""
self.encoding = encoding

def serialize(self, address: Address) -> bytes:
assert address.address.find(":") == -1, "Address should not contain colon character"
address_str: str = f"{address.address_type.value}:{address.address}:{address.port}:{address.address_id}"
return address_str.encode(self.encoding)

def deserialize(self, serialized_data: bytes) -> Address:
try:
address_str: str = serialized_data.decode(self.encoding)
parts = address_str.split(":")
if len(parts) < 4:
raise AddressDeserializationException(f"Invalid number of parts, address_str='{address_str}'")
address_type: AddressType = AddressType(parts[0])
address: str = parts[1]
port: int = int(parts[2])
address_id: str = ":".join(parts[3:]) # there can possibly be some colons in address_id
return Address(address_id=address_id, address_type=address_type, address=address, port=port)
except Exception as e:
raise AddressDeserializationException(f"Failed to deserialize address, error='{e}'") from e
Loading