diff --git a/aries_cloudagent/connections/base_manager.py b/aries_cloudagent/connections/base_manager.py index f1d2ce9fa8..bdbe1dd00e 100644 --- a/aries_cloudagent/connections/base_manager.py +++ b/aries_cloudagent/connections/base_manager.py @@ -6,7 +6,6 @@ import logging from typing import List, Optional, Sequence, Text, Tuple, Union -from multiformats import multibase, multicodec from pydid import ( BaseDIDDocument as ResolvedDocument, DIDCommService, @@ -18,6 +17,7 @@ Ed25519VerificationKey2020, JsonWebKey2020, ) + from ..cache.base import BaseCache from ..config.base import InjectionError from ..config.logging import get_logger_inst @@ -41,6 +41,7 @@ from ..storage.error import StorageDuplicateError, StorageError, StorageNotFoundError from ..storage.record import StorageRecord from ..transport.inbound.receipt import MessageReceipt +from ..utils.multiformats import multibase, multicodec from ..wallet.base import BaseWallet from ..wallet.crypto import create_keypair, seed_to_did from ..wallet.did_info import DIDInfo diff --git a/aries_cloudagent/connections/tests/test_base_manager.py b/aries_cloudagent/connections/tests/test_base_manager.py index 20d3d21f0e..61ff118cd2 100644 --- a/aries_cloudagent/connections/tests/test_base_manager.py +++ b/aries_cloudagent/connections/tests/test_base_manager.py @@ -3,7 +3,6 @@ from unittest.mock import call from asynctest import TestCase as AsyncTestCase, mock as async_mock -from multiformats import multibase, multicodec from pydid import DID, DIDDocument, DIDDocumentBuilder from pydid.doc.builder import ServiceBuilder from pydid.verification_method import ( @@ -41,6 +40,7 @@ from ...storage.error import StorageNotFoundError from ...storage.record import StorageRecord from ...transport.inbound.receipt import MessageReceipt +from ...utils.multiformats import multibase, multicodec from ...wallet.base import DIDInfo from ...wallet.did_method import DIDMethods, SOV from ...wallet.error import WalletNotFoundError diff --git a/aries_cloudagent/resolver/default/peer3.py b/aries_cloudagent/resolver/default/peer3.py index bfe79ce15c..4f97716462 100644 --- a/aries_cloudagent/resolver/default/peer3.py +++ b/aries_cloudagent/resolver/default/peer3.py @@ -6,27 +6,22 @@ the did:peer:2 has been replaced with the did:peer:3. """ -import re from copy import deepcopy from hashlib import sha256 +import re from typing import Optional, Pattern, Sequence, Text -from multiformats import multibase, multicodec - -from peerdid.dids import ( - DID, - MalformedPeerDIDError, - DIDDocument, -) -from peerdid.keys import to_multibase, MultibaseFormat -from ...wallet.util import bytes_to_b58 -from ...connections.base_manager import BaseConnectionManager +from peerdid.dids import DID, DIDDocument, MalformedPeerDIDError +from peerdid.keys import MultibaseFormat, to_multibase + from ...config.injection_context import InjectionContext +from ...connections.base_manager import BaseConnectionManager from ...core.profile import Profile from ...storage.base import BaseStorage from ...storage.error import StorageNotFoundError from ...storage.record import StorageRecord - +from ...utils.multiformats import multibase, multicodec +from ...wallet.util import bytes_to_b58 from ..base import BaseDIDResolver, DIDNotFound, ResolverType RECORD_TYPE_DID_DOCUMENT = "did_document" # pydid DIDDocument diff --git a/aries_cloudagent/utils/multiformats/__init__.py b/aries_cloudagent/utils/multiformats/__init__.py new file mode 100644 index 0000000000..b3aec34c53 --- /dev/null +++ b/aries_cloudagent/utils/multiformats/__init__.py @@ -0,0 +1 @@ +"""Multiformats utility functions.""" diff --git a/aries_cloudagent/utils/multiformats/multibase.py b/aries_cloudagent/utils/multiformats/multibase.py new file mode 100644 index 0000000000..5f9ee5c0ff --- /dev/null +++ b/aries_cloudagent/utils/multiformats/multibase.py @@ -0,0 +1,104 @@ +"""MultiBase encoding and decoding utilities.""" + +from abc import ABC, abstractmethod +from enum import Enum +from typing import ClassVar, Literal, Union + + +class MultibaseEncoder(ABC): + """Encoding details.""" + + name: ClassVar[str] + character: ClassVar[str] + + @abstractmethod + def encode(self, value: bytes) -> str: + """Encode a byte string using this encoding.""" + + @abstractmethod + def decode(self, value: str) -> bytes: + """Decode a string using this encoding.""" + + +class Base58BtcEncoder(MultibaseEncoder): + """Base58BTC encoding.""" + + name = "base58btc" + character = "z" + + def encode(self, value: bytes) -> str: + """Encode a byte string using the base58btc encoding.""" + import base58 + + return base58.b58encode(value).decode() + + def decode(self, value: str) -> bytes: + """Decode a multibase encoded string.""" + import base58 + + return base58.b58decode(value) + + +class Encoding(Enum): + """Enum for supported encodings.""" + + base58btc = Base58BtcEncoder() + # Insert additional encodings here + + @classmethod + def from_name(cls, name: str) -> MultibaseEncoder: + """Get encoding from name.""" + for encoding in cls: + if encoding.value.name == name: + return encoding.value + raise ValueError(f"Unsupported encoding: {name}") + + @classmethod + def from_character(cls, character: str) -> MultibaseEncoder: + """Get encoding from character.""" + for encoding in cls: + if encoding.value.character == character: + return encoding.value + raise ValueError(f"Unsupported encoding: {character}") + + +EncodingStr = Literal[ + "base58btc", + # Insert additional encoding names here +] + + +def encode(value: bytes, encoding: Union[Encoding, EncodingStr]) -> str: + """Encode a byte string using the given encoding. + + Args: + value: The byte string to encode + encoding: The encoding to use + + Returns: + The encoded string + """ + if isinstance(encoding, str): + encoder = Encoding.from_name(encoding) + elif isinstance(encoding, Encoding): + encoder = encoding.value + else: + raise TypeError("encoding must be an Encoding or EncodingStr") + + return encoder.character + encoder.encode(value) + + +def decode(value: str) -> bytes: + """Decode a multibase encoded string. + + Args: + value: The string to decode + + Returns: + The decoded byte string + """ + encoding = value[0] + encoded = value[1:] + encoder = Encoding.from_character(encoding) + + return encoder.decode(encoded) diff --git a/aries_cloudagent/utils/multiformats/multicodec.py b/aries_cloudagent/utils/multiformats/multicodec.py new file mode 100644 index 0000000000..465d5b3ea2 --- /dev/null +++ b/aries_cloudagent/utils/multiformats/multicodec.py @@ -0,0 +1,72 @@ +"""Multicodec wrap and unwrap functions.""" + +from enum import Enum +from typing import Literal, NamedTuple, Optional, Union + + +class Multicodec(NamedTuple): + """Multicodec base class.""" + + name: str + code: bytes + + +class SupportedCodecs(Enum): + """Enumeration of supported multicodecs.""" + + ed25519_pub = Multicodec("ed25519-pub", b"\xed\x01") + x25519_pub = Multicodec("x25519-pub", b"\xec\x01") + bls12381g1 = Multicodec("bls12_381-g1-pub", b"\xea\x01") + bls12381g2 = Multicodec("bls12_381-g2-pub", b"\xeb\x01") + bls12381g1g2 = Multicodec("bls12_381-g1g2-pub", b"\xee\x01") + secp256k1_pub = Multicodec("secp256k1-pub", b"\xe7\x01") + + @classmethod + def by_name(cls, name: str) -> Multicodec: + """Get multicodec by name.""" + for codec in cls: + if codec.value.name == name: + return codec.value + raise ValueError(f"Unsupported multicodec: {name}") + + @classmethod + def for_data(cls, data: bytes) -> Multicodec: + """Get multicodec by data.""" + for codec in cls: + if data.startswith(codec.value.code): + return codec.value + raise ValueError("Unsupported multicodec") + + +MulticodecStr = Literal[ + "ed25519-pub", + "x25519-pub", + "bls12_381-g1-pub", + "bls12_381-g2-pub", + "bls12_381-g1g2-pub", + "secp256k1-pub", +] + + +def multicodec(name: str) -> Multicodec: + """Get multicodec by name.""" + return SupportedCodecs.by_name(name) + + +def wrap(multicodec: Union[Multicodec, MulticodecStr], data: bytes) -> bytes: + """Wrap data with multicodec prefix.""" + if isinstance(multicodec, str): + multicodec = SupportedCodecs.by_name(multicodec) + elif isinstance(multicodec, Multicodec): + pass + else: + raise TypeError("multicodec must be Multicodec or MulticodecStr") + + return multicodec.code + data + + +def unwrap(data: bytes, codec: Optional[Multicodec] = None) -> tuple[Multicodec, bytes]: + """Unwrap data with multicodec prefix.""" + if not codec: + codec = SupportedCodecs.for_data(data) + return codec, data[len(codec.code) :] diff --git a/aries_cloudagent/utils/tests/test_multiformats.py b/aries_cloudagent/utils/tests/test_multiformats.py new file mode 100644 index 0000000000..5ef8ce4308 --- /dev/null +++ b/aries_cloudagent/utils/tests/test_multiformats.py @@ -0,0 +1,73 @@ +import pytest +from ..multiformats import multibase, multicodec + + +def test_encode_decode(): + value = b"Hello World!" + encoded = multibase.encode(value, "base58btc") + assert encoded == "z2NEpo7TZRRrLZSi2U" + decoded = multibase.decode(encoded) + assert decoded == value + + +def test_encode_decode_by_encoding(): + value = b"Hello World!" + encoded = multibase.encode(value, multibase.Encoding.base58btc) + assert encoded == "z2NEpo7TZRRrLZSi2U" + decoded = multibase.decode(encoded) + assert decoded == value + + +def test_x_unknown_encoding(): + with pytest.raises(ValueError): + multibase.encode(b"Hello World!", "fancy-encoding") + + +def test_x_unknown_character(): + with pytest.raises(ValueError): + multibase.decode("fHello World!") + + +def test_x_invalid_encoding(): + with pytest.raises(TypeError): + multibase.encode(b"Hello World!", 123) + + +def test_wrap_unwrap(): + value = b"Hello World!" + wrapped = multicodec.wrap("ed25519-pub", value) + codec, unwrapped = multicodec.unwrap(wrapped) + assert codec == multicodec.multicodec("ed25519-pub") + assert unwrapped == value + + +def test_wrap_unwrap_custom(): + value = b"Hello World!" + my_codec = multicodec.Multicodec("my-codec", b"\x00\x01") + wrapped = multicodec.wrap(my_codec, value) + codec, unwrapped = multicodec.unwrap(wrapped, my_codec) + assert codec == my_codec + assert unwrapped == value + + +def test_wrap_unwrap_by_codec(): + value = b"Hello World!" + wrapped = multicodec.wrap(multicodec.multicodec("ed25519-pub"), value) + codec, unwrapped = multicodec.unwrap(wrapped, multicodec.multicodec("ed25519-pub")) + assert codec == multicodec.multicodec("ed25519-pub") + assert unwrapped == value + + +def test_x_unknown_multicodec(): + with pytest.raises(ValueError): + multicodec.wrap("fancy-multicodec", b"Hello World!") + + +def test_x_invalid_multicodec(): + with pytest.raises(TypeError): + multicodec.wrap(123, b"Hello World!") + + +def test_x_invalid_multicodec_unwrap(): + with pytest.raises(ValueError): + multicodec.unwrap(b"Hello World!") diff --git a/aries_cloudagent/vc/ld_proofs/suites/ed25519_signature_2020.py b/aries_cloudagent/vc/ld_proofs/suites/ed25519_signature_2020.py index b1b823d5c9..fee9c89084 100644 --- a/aries_cloudagent/vc/ld_proofs/suites/ed25519_signature_2020.py +++ b/aries_cloudagent/vc/ld_proofs/suites/ed25519_signature_2020.py @@ -1,14 +1,13 @@ """Ed25519Signature2018 suite.""" from datetime import datetime -from typing import Union, List +from typing import List, Union -from multiformats import multibase - -from .linked_data_signature import LinkedDataSignature +from ....utils.multiformats import multibase from ..crypto import _KeyPair as KeyPair from ..document_loader import DocumentLoaderMethod from ..error import LinkedDataProofException +from .linked_data_signature import LinkedDataSignature class Ed25519Signature2020(LinkedDataSignature): diff --git a/poetry.lock b/poetry.lock index c4aa757abe..3cebc6e7c3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -265,24 +265,6 @@ files = [ [package.extras] tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", "pytest-cov", "pytest-flake8"] -[[package]] -name = "bases" -version = "0.2.1" -description = "Python library for general Base-N encodings." -optional = false -python-versions = ">=3.7" -files = [ - {file = "bases-0.2.1-py3-none-any.whl", hash = "sha256:d030b5e349773ad2a067bfaaf3a9794b70d23a1f923033c15c2e0ce869854f6d"}, - {file = "bases-0.2.1.tar.gz", hash = "sha256:b0999e14725b59bff38974b00e918629e0e29f3d80a40e022c6f0f8d5cdff9d4"}, -] - -[package.dependencies] -typing-extensions = "*" -typing-validation = "*" - -[package.extras] -dev = ["base58", "mypy", "pylint", "pytest", "pytest-cov"] - [[package]] name = "black" version = "23.7.0" @@ -1528,44 +1510,6 @@ files = [ {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, ] -[[package]] -name = "multiformats" -version = "0.2.1" -description = "Python implementation of multiformats protocols." -optional = false -python-versions = ">=3.7" -files = [ - {file = "multiformats-0.2.1-py3-none-any.whl", hash = "sha256:0655fad05cff4cb9eaae3a0f61c4cf8189857fef5a5d0ade6aa25d6b8439e204"}, - {file = "multiformats-0.2.1.tar.gz", hash = "sha256:4aee6eb5289c3cd00315e3f2b97e36b60db6af9bcec91d65f32d7155942dbef9"}, -] - -[package.dependencies] -bases = "*" -multiformats-config = "*" -typing-extensions = "*" -typing-validation = "*" - -[package.extras] -dev = ["blake3", "mmh3", "mypy", "pycryptodomex", "pylint", "pysha3", "pyskein", "pytest", "pytest-cov"] -full = ["blake3", "mmh3", "pycryptodomex", "pysha3", "pyskein"] - -[[package]] -name = "multiformats-config" -version = "0.2.0.post4" -description = "Pre-loading configuration module for the 'multiformats' package." -optional = false -python-versions = ">=3.7" -files = [ - {file = "multiformats-config-0.2.0.post4.tar.gz", hash = "sha256:3b5d0be63211681edbcf887abe149fc17b43a79d0c009fb44232af9addf7a309"}, - {file = "multiformats_config-0.2.0.post4-py3-none-any.whl", hash = "sha256:221a630732f7bb2cd6cb708b94a85da683e29618e4a2055eea1bf4f980feefce"}, -] - -[package.dependencies] -multiformats = "*" - -[package.extras] -dev = ["mypy", "pylint", "pytest", "pytest-cov"] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2182,7 +2126,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2190,15 +2133,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2215,7 +2151,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2223,7 +2158,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2582,20 +2516,6 @@ files = [ {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, ] -[[package]] -name = "typing-validation" -version = "1.0.0.post2" -description = "A simple library for runtime type-checking." -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing-validation-1.0.0.post2.tar.gz", hash = "sha256:6a30dec74373f9dca29db6f79ef65eb765a6934c09d87639cf422288933b2aa4"}, - {file = "typing_validation-1.0.0.post2-py3-none-any.whl", hash = "sha256:c9f5cb42435ee59fcf5a1a69dc88ccd5dc6f904436e61b5b8c276906a1c9e454"}, -] - -[package.extras] -dev = ["mypy", "pylint", "pytest", "pytest-cov", "rich"] - [[package]] name = "unflatten" version = "0.1.1" @@ -2879,4 +2799,4 @@ indy = ["python3-indy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "2192fc079ef7dbcf69ea617b81e6d1f74328ac130d2979d9d51cc4ab7561b375" +content-hash = "98923c33a560d59e549895d86258aa5b0228ea7b08bd387586612bff5825a6e2" diff --git a/pyproject.toml b/pyproject.toml index 94f6685fcf..e53446ec24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ jsonpath_ng="1.5.2" Markdown="~3.1.1" markupsafe="2.0.1" marshmallow="~3.20.1" -multiformats="~0.2.1" nest_asyncio="~1.5.5" packaging="~23.1" portalocker="~2.7.0"