From c2b28503ae288473fe1dcde991f60e6314e26b55 Mon Sep 17 00:00:00 2001 From: mhh Date: Wed, 13 Mar 2024 17:38:33 +0100 Subject: [PATCH 01/13] Add Flake8-pyproject plugin to enable flake8 configuration through pyproject.toml; Add ethereum deps to "testing" deps; Update workflows to only use `pip install -e .[testing]` --- src/aleph/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aleph/__init__.py b/src/aleph/__init__.py index e69de29b..8b137891 100644 --- a/src/aleph/__init__.py +++ b/src/aleph/__init__.py @@ -0,0 +1 @@ + From c870ee33fbf86f34908c82d5c56c6281176d57b0 Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 15 Mar 2024 17:26:42 +0100 Subject: [PATCH 02/13] Add `validate_message()` and security.py module; Rename sol module to solana; Rename polkadot extra to substrate; --- pyproject.toml | 5 +- src/aleph/sdk/chains/sol.py | 94 +-------------------------------- src/aleph/sdk/chains/solana.py | 93 ++++++++++++++++++++++++++++++++ src/aleph/sdk/security.py | 43 +++++++++++++++ tests/unit/conftest.py | 2 +- tests/unit/test_chain_solana.py | 2 +- 6 files changed, 141 insertions(+), 98 deletions(-) create mode 100644 src/aleph/sdk/chains/solana.py create mode 100644 src/aleph/sdk/security.py diff --git a/pyproject.toml b/pyproject.toml index bd4ce56c..ad81381b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ dependencies = [ "eth_abi>=4.0.0; python_version>=\"3.11\"", "eth_account>=0.4.0,<0.11.0", "python-magic", - "typer", "typing_extensions", ] @@ -54,7 +53,7 @@ mqtt = [ nuls2 = [ "aleph-nuls2", ] -polkadot = [ +substrate = [ "py-sr25519-bindings", "substrate-interface", ] @@ -112,7 +111,7 @@ features = [ "dns", "ledger", "nuls2", - "polkadot", + "substrate", "solana", "tezos", "encryption", diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index ff870a4d..98ca8dd8 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1,93 +1 @@ -import json -from pathlib import Path -from typing import Dict, Optional, Union - -import base58 -from nacl.exceptions import BadSignatureError as NaclBadSignatureError -from nacl.public import PrivateKey, SealedBox -from nacl.signing import SigningKey, VerifyKey - -from ..exceptions import BadSignatureError -from .common import BaseAccount, get_fallback_private_key, get_verification_buffer - - -def encode(item): - return base58.b58encode(bytes(item)).decode("ascii") - - -class SOLAccount(BaseAccount): - CHAIN = "SOL" - CURVE = "curve25519" - _signing_key: SigningKey - _private_key: PrivateKey - - def __init__(self, private_key: bytes): - self.private_key = private_key - self._signing_key = SigningKey(self.private_key) - self._private_key = self._signing_key.to_curve25519_private_key() - - async def sign_message(self, message: Dict) -> Dict: - """Sign a message inplace.""" - message = self._setup_sender(message) - verif = get_verification_buffer(message) - signature = await self.sign_raw(verif) - sig = { - "publicKey": self.get_address(), - "signature": encode(signature), - } - message["signature"] = json.dumps(sig) - return message - - async def sign_raw(self, buffer: bytes) -> bytes: - """Sign a raw buffer.""" - sig = self._signing_key.sign(buffer) - return sig.signature - - def get_address(self) -> str: - return encode(self._signing_key.verify_key) - - def get_public_key(self) -> str: - return bytes(self._signing_key.verify_key.to_curve25519_public_key()).hex() - - async def encrypt(self, content) -> bytes: - value: bytes = bytes(SealedBox(self._private_key.public_key).encrypt(content)) - return value - - async def decrypt(self, content) -> bytes: - value: bytes = SealedBox(self._private_key).decrypt(content) - return value - - -def get_fallback_account(path: Optional[Path] = None) -> SOLAccount: - return SOLAccount(private_key=get_fallback_private_key(path=path)) - - -def generate_key() -> bytes: - privkey = bytes(SigningKey.generate()) - return privkey - - -def verify_signature( - signature: Union[bytes, str], - public_key: Union[bytes, str], - message: Union[bytes, str], -): - """ - Verifies a signature. - Args: - signature: The signature to verify. Can be a base58 encoded string or bytes. - public_key: The public key to use for verification. Can be a base58 encoded string or bytes. - message: The message to verify. Can be an utf-8 string or bytes. - Raises: - BadSignatureError: If the signature is invalid. - """ - if isinstance(signature, str): - signature = base58.b58decode(signature) - if isinstance(message, str): - message = message.encode("utf-8") - if isinstance(public_key, str): - public_key = base58.b58decode(public_key) - try: - VerifyKey(public_key).verify(message, signature) - except NaclBadSignatureError as e: - raise BadSignatureError from e +from aleph.sdk.chains.solana import * diff --git a/src/aleph/sdk/chains/solana.py b/src/aleph/sdk/chains/solana.py new file mode 100644 index 00000000..ff870a4d --- /dev/null +++ b/src/aleph/sdk/chains/solana.py @@ -0,0 +1,93 @@ +import json +from pathlib import Path +from typing import Dict, Optional, Union + +import base58 +from nacl.exceptions import BadSignatureError as NaclBadSignatureError +from nacl.public import PrivateKey, SealedBox +from nacl.signing import SigningKey, VerifyKey + +from ..exceptions import BadSignatureError +from .common import BaseAccount, get_fallback_private_key, get_verification_buffer + + +def encode(item): + return base58.b58encode(bytes(item)).decode("ascii") + + +class SOLAccount(BaseAccount): + CHAIN = "SOL" + CURVE = "curve25519" + _signing_key: SigningKey + _private_key: PrivateKey + + def __init__(self, private_key: bytes): + self.private_key = private_key + self._signing_key = SigningKey(self.private_key) + self._private_key = self._signing_key.to_curve25519_private_key() + + async def sign_message(self, message: Dict) -> Dict: + """Sign a message inplace.""" + message = self._setup_sender(message) + verif = get_verification_buffer(message) + signature = await self.sign_raw(verif) + sig = { + "publicKey": self.get_address(), + "signature": encode(signature), + } + message["signature"] = json.dumps(sig) + return message + + async def sign_raw(self, buffer: bytes) -> bytes: + """Sign a raw buffer.""" + sig = self._signing_key.sign(buffer) + return sig.signature + + def get_address(self) -> str: + return encode(self._signing_key.verify_key) + + def get_public_key(self) -> str: + return bytes(self._signing_key.verify_key.to_curve25519_public_key()).hex() + + async def encrypt(self, content) -> bytes: + value: bytes = bytes(SealedBox(self._private_key.public_key).encrypt(content)) + return value + + async def decrypt(self, content) -> bytes: + value: bytes = SealedBox(self._private_key).decrypt(content) + return value + + +def get_fallback_account(path: Optional[Path] = None) -> SOLAccount: + return SOLAccount(private_key=get_fallback_private_key(path=path)) + + +def generate_key() -> bytes: + privkey = bytes(SigningKey.generate()) + return privkey + + +def verify_signature( + signature: Union[bytes, str], + public_key: Union[bytes, str], + message: Union[bytes, str], +): + """ + Verifies a signature. + Args: + signature: The signature to verify. Can be a base58 encoded string or bytes. + public_key: The public key to use for verification. Can be a base58 encoded string or bytes. + message: The message to verify. Can be an utf-8 string or bytes. + Raises: + BadSignatureError: If the signature is invalid. + """ + if isinstance(signature, str): + signature = base58.b58decode(signature) + if isinstance(message, str): + message = message.encode("utf-8") + if isinstance(public_key, str): + public_key = base58.b58decode(public_key) + try: + VerifyKey(public_key).verify(message, signature) + except NaclBadSignatureError as e: + raise BadSignatureError from e diff --git a/src/aleph/sdk/security.py b/src/aleph/sdk/security.py new file mode 100644 index 00000000..44cbb0e5 --- /dev/null +++ b/src/aleph/sdk/security.py @@ -0,0 +1,43 @@ +from typing import Any +from importlib import import_module + +from aleph_message.models import AlephMessage + +from aleph.sdk.chains.common import get_verification_buffer + +validator_chains_map = { + # TODO: Add AVAX + "ETH": "ethereum", + "SOL": "sol", + "CSDK": "cosmos", + "DOT": "substrate", + "NULS2": "nuls2", + "TEZOS": "tezos", +} + + +def try_import_verify_signature(chain: str) -> Any: + """Try to import a chain signature validator.""" + try: + return import_module(f"aleph.sdk.chains.{chain}").verify_signature + except (ImportError, AttributeError): + return None + + +validators = { + key: try_import_verify_signature(value) + for key, value in validator_chains_map.items() +} + + +def verify_signature(message: AlephMessage) -> None: + """Verify the signature of a message.""" + if message.chain not in validators: + raise ValueError(f"Chain {message.chain} is not supported.") + validator = validators[message.chain] + if validator is None: + raise ValueError(f"Chain {message.chain} is not installed. Install it with `aleph-sdk-python[{message.chain}]`.") + signature = message.signature + public_key = message.sender + message = get_verification_buffer(message.dict()) + validator(signature, public_key, message) diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 4b06c243..3c5c1fe8 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -11,7 +11,7 @@ from aleph_message.models import AggregateMessage, AlephMessage, PostMessage import aleph.sdk.chains.ethereum as ethereum -import aleph.sdk.chains.sol as solana +import aleph.sdk.chains.solana as solana import aleph.sdk.chains.substrate as substrate import aleph.sdk.chains.tezos as tezos from aleph.sdk import AlephHttpClient, AuthenticatedAlephHttpClient diff --git a/tests/unit/test_chain_solana.py b/tests/unit/test_chain_solana.py index 07b67602..ed2fff78 100644 --- a/tests/unit/test_chain_solana.py +++ b/tests/unit/test_chain_solana.py @@ -8,7 +8,7 @@ from nacl.signing import VerifyKey from aleph.sdk.chains.common import get_verification_buffer -from aleph.sdk.chains.sol import SOLAccount, get_fallback_account, verify_signature +from aleph.sdk.chains.solana import SOLAccount, get_fallback_account, verify_signature from aleph.sdk.exceptions import BadSignatureError From 3ca54088e0f1e208c501d560a2b011daf62c327b Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 15 Mar 2024 18:09:07 +0100 Subject: [PATCH 03/13] Add verify_signature parameter to fetch functions --- src/aleph/sdk/client/abstract.py | 26 ++++++++++++++++++++++++++ src/aleph/sdk/client/http.py | 19 +++++++++++++++++-- src/aleph/sdk/security.py | 9 ++++++--- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/aleph/sdk/client/abstract.py b/src/aleph/sdk/client/abstract.py index 9fce5469..ac62ff90 100644 --- a/src/aleph/sdk/client/abstract.py +++ b/src/aleph/sdk/client/abstract.py @@ -74,6 +74,7 @@ async def get_posts( post_filter: Optional[PostFilter] = None, ignore_invalid_messages: Optional[bool] = True, invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> PostsResponse: """ Fetch a list of posts from the network. @@ -83,18 +84,25 @@ async def get_posts( :param post_filter: Filter to apply to the posts (Default: None) :param ignore_invalid_messages: Ignore invalid messages (Default: True) :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) + :param verify_signatures: Whether to verify the signatures of the messages (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") async def get_posts_iterator( self, post_filter: Optional[PostFilter] = None, + ignore_invalid_messages: Optional[bool] = True, + invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> AsyncIterable[PostMessage]: """ Fetch all filtered posts, returning an async iterator and fetching them page by page. Might return duplicates but will always return all posts. :param post_filter: Filter to apply to the posts (Default: None) + :param ignore_invalid_messages: Ignore invalid messages (Default: True) + :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) + :param verify_signatures: Whether to verify the signatures of the messages (Default: False) """ page = 1 resp = None @@ -102,6 +110,9 @@ async def get_posts_iterator( resp = await self.get_posts( page=page, post_filter=post_filter, + ignore_invalid_messages=ignore_invalid_messages, + invalid_messages_log_level=invalid_messages_log_level, + verify_signatures=verify_signatures, ) page += 1 for post in resp.posts: @@ -178,6 +189,7 @@ async def get_messages( message_filter: Optional[MessageFilter] = None, ignore_invalid_messages: Optional[bool] = True, invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> MessagesResponse: """ Fetch a list of messages from the network. @@ -187,18 +199,25 @@ async def get_messages( :param message_filter: Filter to apply to the messages :param ignore_invalid_messages: Ignore invalid messages (Default: True) :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) + :param verify_signatures: Whether to verify the signatures of the messages (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") async def get_messages_iterator( self, message_filter: Optional[MessageFilter] = None, + ignore_invalid_messages: Optional[bool] = True, + invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> AsyncIterable[AlephMessage]: """ Fetch all filtered messages, returning an async iterator and fetching them page by page. Might return duplicates but will always return all messages. :param message_filter: Filter to apply to the messages + :param ignore_invalid_messages: Ignore invalid messages (Default: True) + :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) + :param verify_signatures: Whether to verify the signatures of the messages (Default: False) """ page = 1 resp = None @@ -206,6 +225,9 @@ async def get_messages_iterator( resp = await self.get_messages( page=page, message_filter=message_filter, + ignore_invalid_messages=ignore_invalid_messages, + invalid_messages_log_level=invalid_messages_log_level, + verify_signatures=verify_signatures, ) page += 1 for message in resp.messages: @@ -216,12 +238,14 @@ async def get_message( self, item_hash: str, message_type: Optional[Type[GenericMessage]] = None, + verify_signature: bool = False, ) -> GenericMessage: """ Get a single message from its `item_hash` and perform some basic validation. :param item_hash: Hash of the message to fetch :param message_type: Type of message to fetch + :param verify_signature: Whether to verify the signature of the message (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") @@ -229,11 +253,13 @@ async def get_message( def watch_messages( self, message_filter: Optional[MessageFilter] = None, + verify_signatures: bool = False, ) -> AsyncIterable[AlephMessage]: """ Iterate over current and future matching messages asynchronously. :param message_filter: Filter to apply to the messages + :param verify_signatures: Whether to verify the signatures of the messages (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") diff --git a/src/aleph/sdk/client/http.py b/src/aleph/sdk/client/http.py index ae98b0d1..9ded2bcd 100644 --- a/src/aleph/sdk/client/http.py +++ b/src/aleph/sdk/client/http.py @@ -15,6 +15,7 @@ from ..exceptions import FileTooLarge, ForgottenMessageError, MessageNotFoundError from ..query.filters import MessageFilter, PostFilter from ..query.responses import MessagesResponse, Post, PostsResponse +from ..security import verify_message_signature from ..types import GenericMessage from ..utils import ( Writable, @@ -117,6 +118,7 @@ async def get_posts( post_filter: Optional[PostFilter] = None, ignore_invalid_messages: Optional[bool] = True, invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> PostsResponse: ignore_invalid_messages = ( True if ignore_invalid_messages is None else ignore_invalid_messages @@ -145,12 +147,15 @@ async def get_posts( posts: List[Post] = [] for post_raw in posts_raw: try: - posts.append(Post.parse_obj(post_raw)) + post = Post.parse_obj(post_raw) + posts.append(post) except ValidationError as e: if not ignore_invalid_messages: raise e if invalid_messages_log_level: logger.log(level=invalid_messages_log_level, msg=e) + if verify_signatures: + verify_message_signature(post) return PostsResponse( posts=posts, pagination_page=response_json["pagination_page"], @@ -266,6 +271,7 @@ async def get_messages( message_filter: Optional[MessageFilter] = None, ignore_invalid_messages: Optional[bool] = True, invalid_messages_log_level: Optional[int] = logging.NOTSET, + verify_signatures: bool = False, ) -> MessagesResponse: ignore_invalid_messages = ( True if ignore_invalid_messages is None else ignore_invalid_messages @@ -312,6 +318,8 @@ async def get_messages( raise e if invalid_messages_log_level: logger.log(level=invalid_messages_log_level, msg=e) + if verify_signatures: + verify_message_signature(message) return MessagesResponse( messages=messages, @@ -325,6 +333,7 @@ async def get_message( self, item_hash: str, message_type: Optional[Type[GenericMessage]] = None, + verify_signature: bool = False, ) -> GenericMessage: async with self.http_session.get(f"/api/v0/messages/{item_hash}") as resp: try: @@ -339,6 +348,8 @@ async def get_message( f"The requested message {message_raw['item_hash']} has been forgotten by {', '.join(message_raw['forgotten_by'])}" ) message = parse_message(message_raw["message"]) + if verify_signature: + verify_message_signature(message) if message_type: expected_type = get_message_type_value(message_type) if message.type != expected_type: @@ -374,6 +385,7 @@ async def get_message_error( async def watch_messages( self, message_filter: Optional[MessageFilter] = None, + verify_signatures: bool = False, ) -> AsyncIterable[AlephMessage]: message_filter = message_filter or MessageFilter() params = message_filter.as_http_params() @@ -389,6 +401,9 @@ async def watch_messages( break else: data = json.loads(msg.data) - yield parse_message(data) + message = parse_message(data) + if verify_signatures: + verify_message_signature(message) + yield message elif msg.type == aiohttp.WSMsgType.ERROR: break diff --git a/src/aleph/sdk/security.py b/src/aleph/sdk/security.py index 44cbb0e5..b268f4f3 100644 --- a/src/aleph/sdk/security.py +++ b/src/aleph/sdk/security.py @@ -1,9 +1,10 @@ -from typing import Any from importlib import import_module +from typing import Any, Union from aleph_message.models import AlephMessage from aleph.sdk.chains.common import get_verification_buffer +from aleph.sdk.query.responses import Post validator_chains_map = { # TODO: Add AVAX @@ -30,13 +31,15 @@ def try_import_verify_signature(chain: str) -> Any: } -def verify_signature(message: AlephMessage) -> None: +def verify_message_signature(message: Union[AlephMessage, Post]) -> None: """Verify the signature of a message.""" if message.chain not in validators: raise ValueError(f"Chain {message.chain} is not supported.") validator = validators[message.chain] if validator is None: - raise ValueError(f"Chain {message.chain} is not installed. Install it with `aleph-sdk-python[{message.chain}]`.") + raise ValueError( + f"Chain {message.chain} is not installed. Install it with `aleph-sdk-python[{message.chain}]`." + ) signature = message.signature public_key = message.sender message = get_verification_buffer(message.dict()) From 3b6264cdb542bb57e7badc152d70efdbe4c601b2 Mon Sep 17 00:00:00 2001 From: Mike Hukiewitz <70762838+MHHukiewitz@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:13:29 +0100 Subject: [PATCH 04/13] Apply suggestions from code review Co-authored-by: Hugo Herter --- src/aleph/sdk/client/abstract.py | 6 +++--- src/aleph/sdk/security.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/aleph/sdk/client/abstract.py b/src/aleph/sdk/client/abstract.py index ac62ff90..301388ec 100644 --- a/src/aleph/sdk/client/abstract.py +++ b/src/aleph/sdk/client/abstract.py @@ -84,7 +84,7 @@ async def get_posts( :param post_filter: Filter to apply to the posts (Default: None) :param ignore_invalid_messages: Ignore invalid messages (Default: True) :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) - :param verify_signatures: Whether to verify the signatures of the messages (Default: False) + :param verify_signatures: Verify the signatures of the messages (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") @@ -102,7 +102,7 @@ async def get_posts_iterator( :param post_filter: Filter to apply to the posts (Default: None) :param ignore_invalid_messages: Ignore invalid messages (Default: True) :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) - :param verify_signatures: Whether to verify the signatures of the messages (Default: False) + :param verify_signatures: Verify the signatures of the messages (Default: False) """ page = 1 resp = None @@ -199,7 +199,7 @@ async def get_messages( :param message_filter: Filter to apply to the messages :param ignore_invalid_messages: Ignore invalid messages (Default: True) :param invalid_messages_log_level: Log level to use for invalid messages (Default: logging.NOTSET) - :param verify_signatures: Whether to verify the signatures of the messages (Default: False) + :param verify_signatures: Verify the signatures of the messages (Default: False) """ raise NotImplementedError("Did you mean to import `AlephHttpClient`?") diff --git a/src/aleph/sdk/security.py b/src/aleph/sdk/security.py index b268f4f3..e98622d7 100644 --- a/src/aleph/sdk/security.py +++ b/src/aleph/sdk/security.py @@ -32,7 +32,10 @@ def try_import_verify_signature(chain: str) -> Any: def verify_message_signature(message: Union[AlephMessage, Post]) -> None: - """Verify the signature of a message.""" + """Verify the signature of a message, raise an error if invalid or unsupported. + A BadSignatureError is raised when the signature is incorrect. + A ValueError is raised when the chain is not supported or required dependencies are missing. + """ if message.chain not in validators: raise ValueError(f"Chain {message.chain} is not supported.") validator = validators[message.chain] From 7a900b9a202380571081f7bcdcd895aa76c4acc3 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 28 Mar 2024 11:18:17 +0100 Subject: [PATCH 05/13] Replace validator keys with Chain enum; add validators loaded test --- src/aleph/sdk/security.py | 14 +++++++------- tests/unit/test_security.py | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 tests/unit/test_security.py diff --git a/src/aleph/sdk/security.py b/src/aleph/sdk/security.py index e98622d7..b63a11f0 100644 --- a/src/aleph/sdk/security.py +++ b/src/aleph/sdk/security.py @@ -1,19 +1,19 @@ from importlib import import_module from typing import Any, Union -from aleph_message.models import AlephMessage +from aleph_message.models import AlephMessage, Chain from aleph.sdk.chains.common import get_verification_buffer from aleph.sdk.query.responses import Post validator_chains_map = { # TODO: Add AVAX - "ETH": "ethereum", - "SOL": "sol", - "CSDK": "cosmos", - "DOT": "substrate", - "NULS2": "nuls2", - "TEZOS": "tezos", + Chain.ETH: "ethereum", + Chain.SOL: "sol", + Chain.CSDK: "cosmos", + Chain.DOT: "substrate", + Chain.NULS2: "nuls2", + Chain.TEZOS: "tezos", } diff --git a/tests/unit/test_security.py b/tests/unit/test_security.py new file mode 100644 index 00000000..1281a8cc --- /dev/null +++ b/tests/unit/test_security.py @@ -0,0 +1,3 @@ +def test_validators_loaded(): + import aleph.sdk.security as security + assert any([validator is not None for validator in security.validators.values()]) From ba5f3df23d23e2d8a6e07a952e37b8cb45028788 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 28 Mar 2024 11:19:43 +0100 Subject: [PATCH 06/13] Fix formatting --- tests/unit/test_security.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_security.py b/tests/unit/test_security.py index 1281a8cc..ed3ca32c 100644 --- a/tests/unit/test_security.py +++ b/tests/unit/test_security.py @@ -1,3 +1,4 @@ def test_validators_loaded(): import aleph.sdk.security as security + assert any([validator is not None for validator in security.validators.values()]) From 40cb9dd74fe98e67c979bdabb9291f74234f66c5 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 28 Mar 2024 11:22:06 +0100 Subject: [PATCH 07/13] Add validators explanation --- src/aleph/sdk/security.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/aleph/sdk/security.py b/src/aleph/sdk/security.py index b63a11f0..4d8f9a81 100644 --- a/src/aleph/sdk/security.py +++ b/src/aleph/sdk/security.py @@ -29,6 +29,11 @@ def try_import_verify_signature(chain: str) -> Any: key: try_import_verify_signature(value) for key, value in validator_chains_map.items() } +""" +This is a dict containing all currently available signature validators, indexed by their Chain abbreviation. + +Ex.: validators["SOL"] -> aleph.sdk.chains.solana.verify_signature() +""" def verify_message_signature(message: Union[AlephMessage, Post]) -> None: From 850a2cc83b3e2d8f25481f70a749d36750806917 Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 29 Mar 2024 15:41:14 +0100 Subject: [PATCH 08/13] Raise deprecation warning on importing aleph.sdk.chains.sol --- src/aleph/sdk/chains/sol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index 98ca8dd8..9ab80c69 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1 +1,2 @@ +raise DeprecationWarning("Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana") from aleph.sdk.chains.solana import * From c27b714dec158a68dec3957f07f0ef4eab97aee0 Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 29 Mar 2024 16:23:33 +0100 Subject: [PATCH 09/13] Fix formatting --- src/aleph/sdk/chains/sol.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index 9ab80c69..be9605fd 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1,2 +1,4 @@ -raise DeprecationWarning("Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana") +raise DeprecationWarning( + "Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana" +) from aleph.sdk.chains.solana import * From 3d76d2cd52fe20f63e3481758ee4694c2ddcdcf7 Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 29 Mar 2024 16:26:58 +0100 Subject: [PATCH 10/13] Fix deprecation warning --- src/aleph/sdk/chains/sol.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index be9605fd..c7affde3 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1,4 +1,4 @@ -raise DeprecationWarning( - "Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana" -) +from warnings import warn + +warn("Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana", DeprecationWarning, stacklevel=2) from aleph.sdk.chains.solana import * From 758da790d6a160aa2979d2086ccfed995926e4b5 Mon Sep 17 00:00:00 2001 From: mhh Date: Fri, 29 Mar 2024 16:28:31 +0100 Subject: [PATCH 11/13] Fix formatting, again. --- src/aleph/sdk/chains/sol.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index c7affde3..5ce9d0ca 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1,4 +1,8 @@ from warnings import warn -warn("Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana", DeprecationWarning, stacklevel=2) +warn( + "Module aleph.sdk.chains.sol is deprecated in favor of aleph.sdk.chains.solana", + DeprecationWarning, + stacklevel=2, +) from aleph.sdk.chains.solana import * From 36063e81e15b31a754ea7e73112394b6bd967b06 Mon Sep 17 00:00:00 2001 From: Olivier Le Thanh Duong Date: Wed, 11 Sep 2024 15:37:09 +0200 Subject: [PATCH 12/13] Wrong commit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3d2aea9c..2948e72d 100644 --- a/README.md +++ b/README.md @@ -115,3 +115,4 @@ Configure `hardware.ledger.enable = true`. See https://github.com/LedgerHQ/udev-rules +xx From 08dd817111062f1a0ae29edfce7f2d580d950826 Mon Sep 17 00:00:00 2001 From: Olivier Le Thanh Duong Date: Wed, 11 Sep 2024 15:39:35 +0200 Subject: [PATCH 13/13] bad commit 2 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2948e72d..c7c961dc 100644 --- a/README.md +++ b/README.md @@ -116,3 +116,4 @@ See https://github.com/LedgerHQ/udev-rules xx +xx