From 87d3955676c62ea7d195bf1ff05ca7495bcc52e0 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 27 Jun 2024 17:48:51 +0200 Subject: [PATCH 1/3] feat: rename aleph.sdk.chains.sol to aleph.sdk.chains.solana Co-authored-by: Laurent Peuch --- src/aleph/sdk/chains/sol.py | 98 +++------------------------------ src/aleph/sdk/chains/solana.py | 93 +++++++++++++++++++++++++++++++ tests/unit/conftest.py | 2 +- tests/unit/test_chain_solana.py | 2 +- 4 files changed, 102 insertions(+), 93 deletions(-) create mode 100644 src/aleph/sdk/chains/solana.py diff --git a/src/aleph/sdk/chains/sol.py b/src/aleph/sdk/chains/sol.py index ff870a4d..b8e85962 100644 --- a/src/aleph/sdk/chains/sol.py +++ b/src/aleph/sdk/chains/sol.py @@ -1,93 +1,9 @@ -import json -from pathlib import Path -from typing import Dict, Optional, Union +import warnings -import base58 -from nacl.exceptions import BadSignatureError as NaclBadSignatureError -from nacl.public import PrivateKey, SealedBox -from nacl.signing import SigningKey, VerifyKey +from aleph.sdk.chains.solana import * # noqa -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 +warnings.warn( + "aleph.sdk.chains.sol is deprecated, use aleph.sdk.chains.solana instead", + DeprecationWarning, + stacklevel=1, +) 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/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 aeae275a5a5fd9fa6de2a31205eb17a9f3730fb4 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 27 Jun 2024 17:49:17 +0200 Subject: [PATCH 2/3] feat: rename polkadot extra to substrate Co-authored-by: Laurent Peuch --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bd4ce56c..c073e689 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ mqtt = [ nuls2 = [ "aleph-nuls2", ] -polkadot = [ +substrate = [ "py-sr25519-bindings", "substrate-interface", ] @@ -71,7 +71,7 @@ encryption = [ "eciespy>=0.3.13; python_version>=\"3.11\"", ] all = [ - "aleph-sdk-python[cosmos,dns,docs,ledger,mqtt,nuls2,polkadot,solana,tezos,encryption]", + "aleph-sdk-python[cosmos,dns,docs,ledger,mqtt,nuls2,substrate,solana,tezos,encryption]", ] [tool.hatch.metadata] @@ -112,7 +112,7 @@ features = [ "dns", "ledger", "nuls2", - "polkadot", + "substrate", "solana", "tezos", "encryption", From 9c5ec6ee2e57bcaaf2848ebf540fc0c6043cfc41 Mon Sep 17 00:00:00 2001 From: mhh Date: Thu, 27 Jun 2024 17:49:46 +0200 Subject: [PATCH 3/3] refactor: remove unused dependency typer Co-authored-by: Laurent Peuch --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c073e689..22423e85 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", ]