coinex-api 0.0.89__py3-none-any.whl → 0.0.110__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of coinex-api might be problematic. Click here for more details.
- coinex/ccxt/__init__.py +1 -1
- coinex/ccxt/async_support/__init__.py +1 -1
- coinex/ccxt/async_support/base/exchange.py +139 -10
- coinex/ccxt/async_support/base/throttler.py +1 -1
- coinex/ccxt/async_support/base/ws/cache.py +1 -0
- coinex/ccxt/async_support/base/ws/client.py +26 -4
- coinex/ccxt/async_support/coinex.py +2 -2
- coinex/ccxt/base/exchange.py +587 -91
- coinex/ccxt/base/types.py +11 -2
- coinex/ccxt/coinex.py +2 -2
- coinex/ccxt/pro/__init__.py +1 -1
- coinex/ccxt/pro/coinex.py +10 -7
- coinex/ccxt/static_dependencies/bip/__init__.py +6 -0
- coinex/ccxt/static_dependencies/bip/addr/P2PKH_addr.py +205 -0
- coinex/ccxt/static_dependencies/bip/addr/__init__.py +5 -0
- coinex/ccxt/static_dependencies/bip/addr/addr_dec_utils.py +125 -0
- coinex/ccxt/static_dependencies/bip/addr/addr_key_validator.py +162 -0
- coinex/ccxt/static_dependencies/bip/addr/iaddr_decoder.py +48 -0
- coinex/ccxt/static_dependencies/bip/addr/iaddr_encoder.py +50 -0
- coinex/ccxt/static_dependencies/bip/base58/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/base58/base58.py +207 -0
- coinex/ccxt/static_dependencies/bip/base58/base58_ex.py +25 -0
- coinex/ccxt/static_dependencies/bip/base58/base58_xmr.py +155 -0
- coinex/ccxt/static_dependencies/bip/bech32/__init__.py +4 -0
- coinex/ccxt/static_dependencies/bip/bech32/bch_bech32.py +220 -0
- coinex/ccxt/static_dependencies/bip/bech32/bech32.py +235 -0
- coinex/ccxt/static_dependencies/bip/bech32/bech32_base.py +246 -0
- coinex/ccxt/static_dependencies/bip/bech32/bech32_ex.py +25 -0
- coinex/ccxt/static_dependencies/bip/bech32/segwit_bech32.py +173 -0
- coinex/ccxt/static_dependencies/bip/bip32/__init__.py +14 -0
- coinex/ccxt/static_dependencies/bip/bip32/base/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/bip32/base/bip32_base.py +581 -0
- coinex/ccxt/static_dependencies/bip/bip32/base/ibip32_key_derivator.py +83 -0
- coinex/ccxt/static_dependencies/bip/bip32/base/ibip32_mst_key_generator.py +47 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_const.py +35 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_ex.py +29 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_key_data.py +500 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_key_net_ver.py +83 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_key_ser.py +294 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_keys.py +457 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_path.py +247 -0
- coinex/ccxt/static_dependencies/bip/bip32/bip32_utils.py +72 -0
- coinex/ccxt/static_dependencies/bip/bip32/kholaw/__init__.py +4 -0
- coinex/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_ed25519.py +82 -0
- coinex/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_ed25519_key_derivator.py +118 -0
- coinex/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_key_derivator_base.py +204 -0
- coinex/ccxt/static_dependencies/bip/bip32/kholaw/bip32_kholaw_mst_key_generator.py +119 -0
- coinex/ccxt/static_dependencies/bip/bip32/slip10/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_key_derivator.py +200 -0
- coinex/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_mst_key_generator.py +168 -0
- coinex/ccxt/static_dependencies/bip/bip32/slip10/bip32_slip10_secp256k1.py +82 -0
- coinex/ccxt/static_dependencies/bip/bip44/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/bip44/bip44.py +265 -0
- coinex/ccxt/static_dependencies/bip/bip44_base/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/bip44_base/bip44_base.py +624 -0
- coinex/ccxt/static_dependencies/bip/bip44_base/bip44_base_ex.py +25 -0
- coinex/ccxt/static_dependencies/bip/bip44_base/bip44_keys.py +225 -0
- coinex/ccxt/static_dependencies/bip/coin_conf/__init__.py +2 -0
- coinex/ccxt/static_dependencies/bip/coin_conf/coin_conf.py +68 -0
- coinex/ccxt/static_dependencies/bip/coin_conf/coins_conf.py +890 -0
- coinex/ccxt/static_dependencies/bip/conf/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/conf/bip44/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/conf/bip44/bip44_coins.py +126 -0
- coinex/ccxt/static_dependencies/bip/conf/bip44/bip44_conf.py +1360 -0
- coinex/ccxt/static_dependencies/bip/conf/bip44/bip44_conf_getter.py +153 -0
- coinex/ccxt/static_dependencies/bip/conf/bip49/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/conf/bip49/bip49_coins.py +53 -0
- coinex/ccxt/static_dependencies/bip/conf/bip49/bip49_conf.py +366 -0
- coinex/ccxt/static_dependencies/bip/conf/bip49/bip49_conf_getter.py +80 -0
- coinex/ccxt/static_dependencies/bip/conf/bip84/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/conf/bip84/bip84_coins.py +39 -0
- coinex/ccxt/static_dependencies/bip/conf/bip84/bip84_conf.py +113 -0
- coinex/ccxt/static_dependencies/bip/conf/bip84/bip84_conf_getter.py +66 -0
- coinex/ccxt/static_dependencies/bip/conf/bip86/__init__.py +3 -0
- coinex/ccxt/static_dependencies/bip/conf/bip86/bip86_coins.py +37 -0
- coinex/ccxt/static_dependencies/bip/conf/bip86/bip86_conf.py +83 -0
- coinex/ccxt/static_dependencies/bip/conf/bip86/bip86_conf_getter.py +64 -0
- coinex/ccxt/static_dependencies/bip/conf/common/__init__.py +8 -0
- coinex/ccxt/static_dependencies/bip/conf/common/atom_addr.py +104 -0
- coinex/ccxt/static_dependencies/bip/conf/common/bip_bitcoin_cash_conf.py +106 -0
- coinex/ccxt/static_dependencies/bip/conf/common/bip_coin_conf.py +217 -0
- coinex/ccxt/static_dependencies/bip/conf/common/bip_coins.py +28 -0
- coinex/ccxt/static_dependencies/bip/conf/common/bip_conf_const.py +30 -0
- coinex/ccxt/static_dependencies/bip/conf/common/bip_litecoin_conf.py +121 -0
- coinex/ccxt/static_dependencies/bip/ecc/__init__.py +42 -0
- coinex/ccxt/static_dependencies/bip/ecc/common/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/ecc/common/dummy_point.py +219 -0
- coinex/ccxt/static_dependencies/bip/ecc/common/ikeys.py +263 -0
- coinex/ccxt/static_dependencies/bip/ecc/common/ipoint.py +190 -0
- coinex/ccxt/static_dependencies/bip/ecc/conf.py +28 -0
- coinex/ccxt/static_dependencies/bip/ecc/curve/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve.py +121 -0
- coinex/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve_getter.py +74 -0
- coinex/ccxt/static_dependencies/bip/ecc/curve/elliptic_curve_types.py +37 -0
- coinex/ccxt/static_dependencies/bip/ecc/ecdsa/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/ecc/ecdsa/ecdsa_keys.py +36 -0
- coinex/ccxt/static_dependencies/bip/ecc/secp256k1/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1.py +36 -0
- coinex/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_const.py +59 -0
- coinex/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_keys_ecdsa.py +248 -0
- coinex/ccxt/static_dependencies/bip/ecc/secp256k1/secp256k1_point_ecdsa.py +234 -0
- coinex/ccxt/static_dependencies/bip/slip/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/slip/slip173/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/slip/slip173/slip173.py +60 -0
- coinex/ccxt/static_dependencies/bip/slip/slip32/__init__.py +4 -0
- coinex/ccxt/static_dependencies/bip/slip/slip32/slip32.py +322 -0
- coinex/ccxt/static_dependencies/bip/slip/slip32/slip32_key_net_ver.py +62 -0
- coinex/ccxt/static_dependencies/bip/slip/slip44/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/slip/slip44/slip44.py +81 -0
- coinex/ccxt/static_dependencies/bip/utils/__init__.py +0 -0
- coinex/ccxt/static_dependencies/bip/utils/conf/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/utils/conf/coin_names.py +59 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/__init__.py +10 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/aes_ecb.py +152 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/blake2.py +191 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/chacha20_poly1305.py +101 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/hash160.py +57 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/hmac.py +118 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/pbkdf2.py +66 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/ripemd.py +58 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/scrypt.py +66 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/sha2.py +182 -0
- coinex/ccxt/static_dependencies/bip/utils/crypto/sha3.py +99 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/__init__.py +7 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/algo.py +108 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/base32.py +151 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/bit.py +115 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/bytes.py +200 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/data_bytes.py +181 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/integer.py +97 -0
- coinex/ccxt/static_dependencies/bip/utils/misc/string.py +54 -0
- coinex/ccxt/static_dependencies/bip/utils/typing/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/utils/typing/literal.py +27 -0
- coinex/ccxt/static_dependencies/bip/wif/__init__.py +1 -0
- coinex/ccxt/static_dependencies/bip/wif/wif.py +144 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/amino/amino_pb2.py +31 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/base/v1beta1/coin_pb2.py +47 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/multisig/keys_pb2.py +33 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/multisig/v1beta1/multisig_pb2.py +33 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/crypto/secp256k1/keys_pb2.py +34 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/msg/v1/msg_pb2.py +27 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/tx/signing/v1beta1/signing_pb2.py +38 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos/tx/v1beta1/tx_pb2.py +75 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/cosmos_proto/cosmos_pb2.py +36 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/accountplus_pb2.py +31 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/genesis_pb2.py +40 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/models_pb2.py +26 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/params_pb2.py +29 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/query_pb2.py +57 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/accountplus/tx_pb2.py +51 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/block_rate_limit_config_pb2.py +37 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/clob_pair_pb2.py +41 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/equity_tier_limit_config_pb2.py +35 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/finalize_block_pb2.py +27 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/liquidations_config_pb2.py +39 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/liquidations_pb2.py +38 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/matches_pb2.py +55 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/mev_pb2.py +49 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/operation_pb2.py +32 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/order_pb2.py +86 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/order_removals_pb2.py +32 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/process_proposer_matches_events_pb2.py +42 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/query_pb2.py +124 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/streaming_pb2.py +29 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/clob/tx_pb2.py +117 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/genesis_pb2.py +26 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/query_pb2.py +26 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/transfer_pb2.py +61 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/sending/tx_pb2.py +37 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/asset_position_pb2.py +29 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/genesis_pb2.py +30 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/perpetual_position_pb2.py +33 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/query_pb2.py +63 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/streaming_pb2.py +31 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/dydxprotocol/subaccounts/subaccount_pb2.py +33 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/gogoproto/gogo_pb2.py +102 -0
- coinex/ccxt/static_dependencies/dydx_v4_client/registry.py +38 -0
- coinex/ccxt/static_dependencies/ecdsa/ellipticcurve.py +842 -0
- coinex/ccxt/static_dependencies/ecdsa/keys.py +15 -4
- coinex/ccxt/static_dependencies/mnemonic/__init__.py +4 -0
- coinex/ccxt/static_dependencies/mnemonic/mnemonic.py +282 -0
- coinex/ccxt/static_dependencies/mnemonic/py.typed +1 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/chinese_simplified.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/chinese_traditional.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/czech.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/english.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/french.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/italian.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/japanese.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/korean.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/portuguese.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/russian.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/spanish.txt +2048 -0
- coinex/ccxt/static_dependencies/mnemonic/wordlist/turkish.txt +2048 -0
- {coinex_api-0.0.89.dist-info → coinex_api-0.0.110.dist-info}/METADATA +3 -3
- {coinex_api-0.0.89.dist-info → coinex_api-0.0.110.dist-info}/RECORD +197 -17
- {coinex_api-0.0.89.dist-info → coinex_api-0.0.110.dist-info}/WHEEL +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright (c) 2021 Emanuele Bellocchia
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
# THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""Module with interface for address encoding classes."""
|
|
22
|
+
|
|
23
|
+
# Imports
|
|
24
|
+
from abc import ABC, abstractmethod
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class IAddrDecoder(ABC):
|
|
29
|
+
"""Address decoder interface."""
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def DecodeAddr(addr: str,
|
|
34
|
+
**kwargs: Any) -> bytes:
|
|
35
|
+
"""
|
|
36
|
+
Decode an address to bytes.
|
|
37
|
+
Depending on the coin, the result can be a public key or a public key hash bytes.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
addr (str): Address string
|
|
41
|
+
**kwargs : Arbitrary arguments depending on the address type
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
bytes: Public key bytes or public key hash
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
ValueError: If the address encoding is not valid
|
|
48
|
+
"""
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (c) 2021 Emanuele Bellocchia
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
# THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""Module with interface for address encoding classes."""
|
|
22
|
+
|
|
23
|
+
# Imports
|
|
24
|
+
from abc import ABC, abstractmethod
|
|
25
|
+
from typing import Any, Union
|
|
26
|
+
|
|
27
|
+
from ..ecc import IPublicKey
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class IAddrEncoder(ABC):
|
|
31
|
+
"""Address encoder interface."""
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def EncodeKey(pub_key: Union[bytes, IPublicKey],
|
|
36
|
+
**kwargs: Any) -> str:
|
|
37
|
+
"""
|
|
38
|
+
Encode public key to address.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
pub_key (bytes or IPublicKey): Public key bytes or object
|
|
42
|
+
**kwargs : Arbitrary arguments depending on the address type
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
str: Address string
|
|
46
|
+
|
|
47
|
+
Raised:
|
|
48
|
+
ValueError: If the public key is not valid
|
|
49
|
+
TypeError: If the public key is not of the correct type (it depends on the address type)
|
|
50
|
+
"""
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Copyright (c) 2021 Emanuele Bellocchia
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
# THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""Module for base58 decoding/encoding."""
|
|
22
|
+
|
|
23
|
+
# Imports
|
|
24
|
+
from enum import Enum, auto, unique
|
|
25
|
+
from typing import Dict
|
|
26
|
+
|
|
27
|
+
from .base58_ex import Base58ChecksumError
|
|
28
|
+
from ..utils.crypto import DoubleSha256
|
|
29
|
+
from ..utils.misc import BytesUtils
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@unique
|
|
33
|
+
class Base58Alphabets(Enum):
|
|
34
|
+
"""Enumerative for Base58 alphabet."""
|
|
35
|
+
|
|
36
|
+
BITCOIN = auto()
|
|
37
|
+
RIPPLE = auto()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Base58Const:
|
|
41
|
+
"""Class container for Base58 constants."""
|
|
42
|
+
|
|
43
|
+
# Base58 radix
|
|
44
|
+
RADIX: int = 58
|
|
45
|
+
# Checksum length in bytes
|
|
46
|
+
CHECKSUM_BYTE_LEN: int = 4
|
|
47
|
+
# Alphabets
|
|
48
|
+
ALPHABETS: Dict[Base58Alphabets, str] = {
|
|
49
|
+
Base58Alphabets.BITCOIN: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
|
|
50
|
+
Base58Alphabets.RIPPLE: "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Base58Utils:
|
|
55
|
+
"""Class container for Base58 utility functions."""
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def ComputeChecksum(data_bytes: bytes) -> bytes:
|
|
59
|
+
"""
|
|
60
|
+
Compute Base58 checksum.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
data_bytes (bytes): Data bytes
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
bytes: Computed checksum
|
|
67
|
+
"""
|
|
68
|
+
return DoubleSha256.QuickDigest(data_bytes)[:Base58Const.CHECKSUM_BYTE_LEN]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Base58Encoder:
|
|
72
|
+
"""Base58 encoder class. It provides methods for encoding and checksum encoding to Base58 format."""
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def Encode(data_bytes: bytes,
|
|
76
|
+
alph_idx: Base58Alphabets = Base58Alphabets.BITCOIN) -> str:
|
|
77
|
+
"""
|
|
78
|
+
Encode bytes into a Base58 string.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
data_bytes (bytes) : Data bytes
|
|
82
|
+
alph_idx (Base58Alphabets, optional): Alphabet index, Bitcoin by default
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
str: Encoded string
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
TypeError: If alphabet index is not a Base58Alphabets enumerative
|
|
89
|
+
"""
|
|
90
|
+
if not isinstance(alph_idx, Base58Alphabets):
|
|
91
|
+
raise TypeError("Alphabet index is not an enumerative of Base58Alphabets")
|
|
92
|
+
|
|
93
|
+
enc = ""
|
|
94
|
+
|
|
95
|
+
# Get alphabet
|
|
96
|
+
alphabet = Base58Const.ALPHABETS[alph_idx]
|
|
97
|
+
|
|
98
|
+
# Convert bytes to integer
|
|
99
|
+
val = BytesUtils.ToInteger(data_bytes)
|
|
100
|
+
|
|
101
|
+
# Algorithm implementation
|
|
102
|
+
while val > 0:
|
|
103
|
+
val, mod = divmod(val, Base58Const.RADIX)
|
|
104
|
+
enc = alphabet[mod] + enc
|
|
105
|
+
|
|
106
|
+
# Get number of leading zeros
|
|
107
|
+
n = len(data_bytes) - len(data_bytes.lstrip(b"\x00"))
|
|
108
|
+
# Add padding
|
|
109
|
+
return (alphabet[0] * n) + enc
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
def CheckEncode(data_bytes: bytes,
|
|
113
|
+
alph_idx: Base58Alphabets = Base58Alphabets.BITCOIN) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Encode bytes into Base58 string with checksum.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
data_bytes (bytes) : Data bytes
|
|
119
|
+
alph_idx (Base58Alphabets, optional): Alphabet index, Bitcoin by default
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
str: Encoded string with checksum
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
TypeError: If alphabet index is not a Base58Alphabets enumerative
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
# Append checksum and encode all together
|
|
129
|
+
return Base58Encoder.Encode(data_bytes + Base58Utils.ComputeChecksum(data_bytes), alph_idx)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class Base58Decoder:
|
|
133
|
+
"""Base58 decoder class. It provides methods for decoding and checksum decoding Base58 format."""
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def Decode(data_str: str,
|
|
137
|
+
alph_idx: Base58Alphabets = Base58Alphabets.BITCOIN) -> bytes:
|
|
138
|
+
"""
|
|
139
|
+
Decode bytes from a Base58 string.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
data_str (str) : Data string
|
|
143
|
+
alph_idx (Base58Alphabets, optional): Alphabet index, Bitcoin by default
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
bytes: Decoded bytes
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
TypeError: If alphabet index is not a Base58Alphabets enumerative
|
|
150
|
+
"""
|
|
151
|
+
if not isinstance(alph_idx, Base58Alphabets):
|
|
152
|
+
raise TypeError("Alphabet index is not an enumerative of Base58Alphabets")
|
|
153
|
+
|
|
154
|
+
# Get alphabet
|
|
155
|
+
alphabet = Base58Const.ALPHABETS[alph_idx]
|
|
156
|
+
|
|
157
|
+
# Convert string to integer
|
|
158
|
+
val = 0
|
|
159
|
+
for i, c in enumerate(data_str[::-1]):
|
|
160
|
+
val += alphabet.index(c) * (Base58Const.RADIX ** i)
|
|
161
|
+
|
|
162
|
+
dec = bytearray()
|
|
163
|
+
while val > 0:
|
|
164
|
+
val, mod = divmod(val, 2**8)
|
|
165
|
+
dec.append(mod)
|
|
166
|
+
|
|
167
|
+
# Get padding length
|
|
168
|
+
pad_len = len(data_str) - len(data_str.lstrip(alphabet[0]))
|
|
169
|
+
# Add padding
|
|
170
|
+
return (b"\x00" * pad_len) + bytes(dec[::-1])
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def CheckDecode(data_str: str,
|
|
174
|
+
alph_idx: Base58Alphabets = Base58Alphabets.BITCOIN) -> bytes:
|
|
175
|
+
"""
|
|
176
|
+
Decode bytes from a Base58 string with checksum.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
data_str (str) : Data string
|
|
180
|
+
alph_idx (Base58Alphabets, optional): Alphabet index, Bitcoin by default
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
bytes: Decoded bytes (checksum removed)
|
|
184
|
+
|
|
185
|
+
Raises:
|
|
186
|
+
ValueError: If the string is not a valid Base58 format
|
|
187
|
+
TypeError: If alphabet index is not a Base58Alphabets enumerative
|
|
188
|
+
Base58ChecksumError: If checksum is not valid
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
# Decode string
|
|
192
|
+
dec_bytes = Base58Decoder.Decode(data_str, alph_idx)
|
|
193
|
+
# Get data and checksum bytes
|
|
194
|
+
data_bytes = dec_bytes[:-Base58Const.CHECKSUM_BYTE_LEN]
|
|
195
|
+
checksum_bytes = dec_bytes[-Base58Const.CHECKSUM_BYTE_LEN:]
|
|
196
|
+
|
|
197
|
+
# Compute checksum
|
|
198
|
+
checksum_bytes_got = Base58Utils.ComputeChecksum(data_bytes)
|
|
199
|
+
|
|
200
|
+
# Verify checksum
|
|
201
|
+
if checksum_bytes != checksum_bytes_got:
|
|
202
|
+
raise Base58ChecksumError(
|
|
203
|
+
f"Invalid checksum (expected {BytesUtils.ToHexString(checksum_bytes_got)}, "
|
|
204
|
+
f"got {BytesUtils.ToHexString(checksum_bytes)})"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
return data_bytes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2021 Emanuele Bellocchia
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
# THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""Module for base58 exceptions."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Base58ChecksumError(Exception):
|
|
25
|
+
"""Exception in case of checksum error."""
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Copyright (c) 2021 Emanuele Bellocchia
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
# THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""Module for base58-monero decoding/encoding."""
|
|
22
|
+
|
|
23
|
+
# Imports
|
|
24
|
+
from typing import List
|
|
25
|
+
|
|
26
|
+
from .base58 import Base58Alphabets, Base58Const, Base58Decoder, Base58Encoder
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Base58XmrConst:
|
|
30
|
+
"""Class container for Base58 Monero constants."""
|
|
31
|
+
|
|
32
|
+
# Alphabet
|
|
33
|
+
ALPHABET: str = Base58Const.ALPHABETS[Base58Alphabets.BITCOIN]
|
|
34
|
+
|
|
35
|
+
# Block decoded maximum length in bytes
|
|
36
|
+
BLOCK_DEC_MAX_BYTE_LEN: int = 8
|
|
37
|
+
|
|
38
|
+
# Block encoded maximum length in bytes
|
|
39
|
+
BLOCK_ENC_MAX_BYTE_LEN: int = 11
|
|
40
|
+
# Block encoded lengths in bytes
|
|
41
|
+
BLOCK_ENC_BYTE_LENS: List[int] = [0, 2, 3, 5, 6, 7, 9, 10, 11]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Base58XmrEncoder:
|
|
45
|
+
"""
|
|
46
|
+
Base58 Monero encoder class.
|
|
47
|
+
It provides methods for encoding to Base58 format with Monero variation (encoding by blocks of 8-byte).
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def Encode(data_bytes: bytes) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Encode bytes into a Base58 string with Monero variation.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
data_bytes (bytes): Data bytes
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
str: Encoded string
|
|
60
|
+
"""
|
|
61
|
+
enc = ""
|
|
62
|
+
|
|
63
|
+
# Get lengths
|
|
64
|
+
data_len = len(data_bytes)
|
|
65
|
+
block_dec_len = Base58XmrConst.BLOCK_DEC_MAX_BYTE_LEN
|
|
66
|
+
|
|
67
|
+
# Compute total block count and last block length
|
|
68
|
+
tot_block_cnt, last_block_enc_len = divmod(data_len, block_dec_len)
|
|
69
|
+
|
|
70
|
+
# Encode each single block and pad
|
|
71
|
+
for i in range(tot_block_cnt):
|
|
72
|
+
block_enc = Base58Encoder.Encode(data_bytes[i * block_dec_len:(i + 1) * block_dec_len])
|
|
73
|
+
enc += Base58XmrEncoder.__Pad(block_enc, Base58XmrConst.BLOCK_ENC_MAX_BYTE_LEN)
|
|
74
|
+
|
|
75
|
+
# Encode last block and pad
|
|
76
|
+
if last_block_enc_len > 0:
|
|
77
|
+
block_enc = Base58Encoder.Encode(
|
|
78
|
+
data_bytes[tot_block_cnt * block_dec_len:(tot_block_cnt * block_dec_len) + last_block_enc_len])
|
|
79
|
+
enc += Base58XmrEncoder.__Pad(block_enc, Base58XmrConst.BLOCK_ENC_BYTE_LENS[last_block_enc_len])
|
|
80
|
+
|
|
81
|
+
return enc
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def __Pad(enc_str: str,
|
|
85
|
+
pad_len: int) -> str:
|
|
86
|
+
"""
|
|
87
|
+
Pad the encoded string to the specified length.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
enc_str (str): Encoded string
|
|
91
|
+
pad_len (int): Pad length
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
str: Padded string
|
|
95
|
+
"""
|
|
96
|
+
return enc_str.rjust(pad_len, Base58XmrConst.ALPHABET[0])
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class Base58XmrDecoder:
|
|
100
|
+
"""
|
|
101
|
+
Base58 Monero decoder class.
|
|
102
|
+
It provides methods for decoding Base58 format with Monero variation (encoding by blocks of 8-byte).
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def Decode(data_str: str) -> bytes:
|
|
107
|
+
"""
|
|
108
|
+
Decode bytes from a Base58 string with Monero variation.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
data_str (str): Data string
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
bytes: Decoded bytes
|
|
115
|
+
"""
|
|
116
|
+
dec = b""
|
|
117
|
+
|
|
118
|
+
# Get lengths
|
|
119
|
+
data_len = len(data_str)
|
|
120
|
+
block_dec_len = Base58XmrConst.BLOCK_DEC_MAX_BYTE_LEN
|
|
121
|
+
block_enc_len = Base58XmrConst.BLOCK_ENC_MAX_BYTE_LEN
|
|
122
|
+
|
|
123
|
+
# Compute block count and last block length
|
|
124
|
+
tot_block_cnt, last_block_enc_len = divmod(data_len, block_enc_len)
|
|
125
|
+
|
|
126
|
+
# Get last block decoded length
|
|
127
|
+
last_block_dec_len = Base58XmrConst.BLOCK_ENC_BYTE_LENS.index(last_block_enc_len)
|
|
128
|
+
|
|
129
|
+
# Decode each single block and unpad
|
|
130
|
+
for i in range(tot_block_cnt):
|
|
131
|
+
block_dec = Base58Decoder.Decode(data_str[(i * block_enc_len):((i + 1) * block_enc_len)])
|
|
132
|
+
dec += Base58XmrDecoder.__UnPad(block_dec, block_dec_len)
|
|
133
|
+
|
|
134
|
+
# Decode last block and unpad
|
|
135
|
+
if last_block_enc_len > 0:
|
|
136
|
+
block_dec = Base58Decoder.Decode(
|
|
137
|
+
data_str[(tot_block_cnt * block_enc_len):((tot_block_cnt * block_enc_len) + last_block_enc_len)])
|
|
138
|
+
dec += Base58XmrDecoder.__UnPad(block_dec, last_block_dec_len)
|
|
139
|
+
|
|
140
|
+
return dec
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def __UnPad(dec_bytes: bytes,
|
|
144
|
+
unpad_len: int) -> bytes:
|
|
145
|
+
"""
|
|
146
|
+
Unpad the decoded string to the specified length.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
dec_bytes (bytes): Decoded bytes
|
|
150
|
+
unpad_len (int): Unpad length
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
bytes: Unpadded string
|
|
154
|
+
"""
|
|
155
|
+
return dec_bytes[len(dec_bytes) - unpad_len:len(dec_bytes)]
|