From 718f4c3db3ccf17d1cf8e3672358e316522b8d6f Mon Sep 17 00:00:00 2001 From: Lennart Date: Tue, 12 Sep 2023 19:15:55 +0200 Subject: [PATCH 01/38] [REF] Rewrite setup.py to setup.cfg and pyproject.toml files --- .readthedocs.yml | 4 +-- pyproject.toml | 3 ++ setup.cfg | 48 ++++++++++++++++++++++++- setup.py | 92 ------------------------------------------------ 4 files changed, 52 insertions(+), 95 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.py diff --git a/.readthedocs.yml b/.readthedocs.yml index 1c9a3fc5..358b81bb 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -13,7 +13,7 @@ build: # Optionally set the version of Python and requirements required to build your docs python: - version: 3.7 + version: 3.10 install: - requirements: docs/requirements.txt -# - requirements: requirements.txt \ No newline at end of file +# - requirements: requirements.txt diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..fed528d4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index 5aef279b..379242f9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,48 @@ [metadata] -description-file = README.rst +name = bitcoinlib +version = 0.6.12.1 +url = http://github.com/1200wd/bitcoinlib +author = 1200wd +author_email = info@1200wd.com +license= GNU3 +description = Bitcoin cryptocurrency Library +long_description = file: README.rst +keywords = bitcoin library cryptocurrency wallet crypto keys segwit transactions blocks +classifiers = + Development Status :: 4 - Beta + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Intended Audience :: Developers + Intended Audience :: Financial and Insurance Industry + Intended Audience :: Science/Research + Intended Audience :: Information Technology + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Natural Language :: English + Operating System :: OS Independent + Operating System :: Microsoft :: Windows + Operating System :: POSIX + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Topic :: Software Development :: Libraries :: Python Modules + Topic :: Security :: Cryptography + Topic :: Office/Business :: Financial :: Accounting + +[options] +packages = find: +zip_safe = True +include_package_data = True +install_requires = + requests >= 2.25.0 + fastecdsa >= 2.2.1;platform_system!="Windows" + ecdsa >= 0.17;platform_system=="Windows" + pycryptodome >= 3.14.1 + SQLAlchemy >= 1.4.28 + numpy == 1.19.5;python_version<"3.9" + numpy >= 1.22.0;python_version>="3.9" + +[options.entry_points] +console_scripts = + cli-wallet = bitcoinlib.tools.clw:main + clw = bitcoinlib.tools.clw:main diff --git a/setup.py b/setup.py deleted file mode 100644 index 91c1395e..00000000 --- a/setup.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# -# BitcoinLib - Python Cryptocurrency Library -# PyPi Setup Tool -# © 2018-2023 May - 1200 Web Development -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -from setuptools import setup -from codecs import open -import os -import sys - -here = os.path.abspath(os.path.dirname(__file__)) -version = '0.6.12' - -# Get the long description from the relevant file -readmetxt = '' -try: - with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: - readmetxt = f.read() -except: - pass - -kwargs = {} - - -install_requires = [ - 'requests>=2.25.0', - 'fastecdsa>=2.2.1;platform_system!="Windows"', - 'ecdsa>=0.17;platform_system=="Windows"', - 'pycryptodome>=3.14.1', - 'SQLAlchemy>=1.4.28', - 'numpy==1.19.5;python_version<"3.9"', - 'numpy>=1.22.0;python_version>="3.9"' -] - -kwargs['install_requires'] = install_requires - -setup( - name='bitcoinlib', - version=version, - description='Bitcoin and Other cryptocurrency Library', - long_description=readmetxt, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Intended Audience :: Developers', - 'Intended Audience :: Financial and Insurance Industry', - 'Intended Audience :: Science/Research', - 'Intended Audience :: Information Technology', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Security :: Cryptography', - 'Topic :: Office/Business :: Financial :: Accounting', - ], - url='http://github.com/1200wd/bitcoinlib', - author='1200wd', - author_email='info@1200wd.com', - license='GNU3', - packages=['bitcoinlib'], - entry_points={ - 'console_scripts': ['cli-wallet=bitcoinlib.tools.clw:main', - 'clw=bitcoinlib.tools.clw:main'] - }, - test_suite='tests', - include_package_data=True, - keywords='bitcoin library cryptocurrency wallet crypto keys segwit litecoin dash', - zip_safe=False, - **kwargs -) From 6f7ae5636f5bc65937189ca90dcbade522a6a225 Mon Sep 17 00:00:00 2001 From: Lennart Date: Tue, 12 Sep 2023 19:26:34 +0200 Subject: [PATCH 02/38] [REF] Replace setup.py in github workflow tests --- .github/workflows/unittests-noscrypt.yaml | 2 +- .github/workflows/unittests.yaml | 2 +- .github/workflows/unittests_windows.yaml | 2 +- setup.cfg | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unittests-noscrypt.yaml b/.github/workflows/unittests-noscrypt.yaml index 37c850c3..50bc596e 100644 --- a/.github/workflows/unittests-noscrypt.yaml +++ b/.github/workflows/unittests-noscrypt.yaml @@ -21,7 +21,7 @@ jobs: pip install mysqlclient pip install parameterized pip install Cython - python setup.py install + python -m pip install . - name: Test with coverage env: BCL_CONFIG_FILE: config_encryption.ini.unittest diff --git a/.github/workflows/unittests.yaml b/.github/workflows/unittests.yaml index 19d4f6d0..cc3d451e 100644 --- a/.github/workflows/unittests.yaml +++ b/.github/workflows/unittests.yaml @@ -25,7 +25,7 @@ jobs: pip install parameterized pip install scrypt pip install Cython - python setup.py install + python -m pip install . - name: Test with coverage env: BCL_CONFIG_FILE: config.ini.unittest diff --git a/.github/workflows/unittests_windows.yaml b/.github/workflows/unittests_windows.yaml index 08800c2b..7177253c 100644 --- a/.github/workflows/unittests_windows.yaml +++ b/.github/workflows/unittests_windows.yaml @@ -22,7 +22,7 @@ jobs: pip install mysqlclient pip install parameterized pip install scrypt - python setup.py install + python -m pip install . - name: Test with coverage env: BCL_CONFIG_FILE: config.ini.unittest diff --git a/setup.cfg b/setup.cfg index 379242f9..0a97caac 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = bitcoinlib -version = 0.6.12.1 +version = 0.6.12 url = http://github.com/1200wd/bitcoinlib author = 1200wd author_email = info@1200wd.com From 066e57268c1f67b3d4a3d8ba227cf45371c9bff2 Mon Sep 17 00:00:00 2001 From: Lennart Date: Sun, 17 Sep 2023 14:44:53 +0200 Subject: [PATCH 03/38] [DEL] Del obsolete requirements-dev --- requirements-dev.txt | 13 ------------- requirements.txt | 12 ++++++++++-- 2 files changed, 10 insertions(+), 15 deletions(-) delete mode 100644 requirements-dev.txt diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 42a9c412..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,13 +0,0 @@ -requests>=2.25.0 -fastecdsa>=2.2.1 -scrypt>=0.8.18 -pycryptodome>=3.14.1 -SQLAlchemy>=1.4.45 -numpy>=1.22.0 -sphinx>=4.3.1 -coveralls>=3.0.1 -psycopg2>=2.9.2 -mysql-connector-python>=8.0.27 -mysqlclient>=2.1.0 -parameterized>=0.8.1 -sphinx_rtd_theme>=1.0.0 diff --git a/requirements.txt b/requirements.txt index 48e677d1..42a9c412 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,13 @@ requests>=2.25.0 fastecdsa>=2.2.1 -SQLAlchemy>=1.4.24 -numpy>=1.22.0 +scrypt>=0.8.18 pycryptodome>=3.14.1 +SQLAlchemy>=1.4.45 +numpy>=1.22.0 +sphinx>=4.3.1 +coveralls>=3.0.1 +psycopg2>=2.9.2 +mysql-connector-python>=8.0.27 +mysqlclient>=2.1.0 +parameterized>=0.8.1 +sphinx_rtd_theme>=1.0.0 From 4a8c70d0f918940e6e8763b9f2c81af94b10fb4f Mon Sep 17 00:00:00 2001 From: Lennart Date: Sun, 17 Sep 2023 15:49:26 +0200 Subject: [PATCH 04/38] [REF] Move dev requirements to setup.cfg --- .github/workflows/unittests-noscrypt.yaml | 9 ++------- .github/workflows/unittests.yaml | 9 +-------- .github/workflows/unittests_windows.yaml | 9 +-------- requirements.txt | 2 ++ setup.cfg | 15 ++++++++++++++- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/.github/workflows/unittests-noscrypt.yaml b/.github/workflows/unittests-noscrypt.yaml index 50bc596e..91070810 100644 --- a/.github/workflows/unittests-noscrypt.yaml +++ b/.github/workflows/unittests-noscrypt.yaml @@ -15,13 +15,8 @@ jobs: architecture: 'x64' - name: Install dependencies run: | - pip install coveralls - pip install psycopg2 - pip install mysql-connector - pip install mysqlclient - pip install parameterized - pip install Cython - python -m pip install . + python -m pip install .[dev] + pip uninstall scrypt - name: Test with coverage env: BCL_CONFIG_FILE: config_encryption.ini.unittest diff --git a/.github/workflows/unittests.yaml b/.github/workflows/unittests.yaml index cc3d451e..28ae94bc 100644 --- a/.github/workflows/unittests.yaml +++ b/.github/workflows/unittests.yaml @@ -18,14 +18,7 @@ jobs: architecture: 'x64' - name: Install dependencies run: | - pip install coveralls - pip install psycopg2 - pip install mysql-connector - pip install mysqlclient - pip install parameterized - pip install scrypt - pip install Cython - python -m pip install . + python -m pip install .[dev] - name: Test with coverage env: BCL_CONFIG_FILE: config.ini.unittest diff --git a/.github/workflows/unittests_windows.yaml b/.github/workflows/unittests_windows.yaml index 7177253c..a2e13d37 100644 --- a/.github/workflows/unittests_windows.yaml +++ b/.github/workflows/unittests_windows.yaml @@ -15,14 +15,7 @@ jobs: architecture: 'x64' - name: Install dependencies run: | - pip install win-unicode-console - pip install coveralls - pip install psycopg2 - pip install mysql-connector - pip install mysqlclient - pip install parameterized - pip install scrypt - python -m pip install . + python -m pip install .[dev] - name: Test with coverage env: BCL_CONFIG_FILE: config.ini.unittest diff --git a/requirements.txt b/requirements.txt index 42a9c412..4ce7c391 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,5 @@ mysql-connector-python>=8.0.27 mysqlclient>=2.1.0 parameterized>=0.8.1 sphinx_rtd_theme>=1.0.0 +Cython +win-unicode-console;platform_system=="Windows" diff --git a/setup.cfg b/setup.cfg index 0a97caac..58b66138 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,12 +36,25 @@ include_package_data = True install_requires = requests >= 2.25.0 fastecdsa >= 2.2.1;platform_system!="Windows" - ecdsa >= 0.17;platform_system=="Windows" + ecdsa >= 0.17 pycryptodome >= 3.14.1 SQLAlchemy >= 1.4.28 numpy == 1.19.5;python_version<"3.9" numpy >= 1.22.0;python_version>="3.9" +[options.extras_require] +dev = + scrypt >= 0.8.18 + sphinx >= 4.3.1 + coveralls > =3.0.1 + psycopg2 >= 2.9.2 + mysql-connector-python >= 8.0.27 + mysqlclient >= 2.1.0 + parameterized >= 0.8.1 + sphinx_rtd_theme >= 1.0.0 + Cython + win-unicode-console;platform_system=="Windows" + [options.entry_points] console_scripts = cli-wallet = bitcoinlib.tools.clw:main From 0c17f9c231f5a21c169eecdca288ead0c505760a Mon Sep 17 00:00:00 2001 From: Lennart Date: Sun, 17 Sep 2023 15:53:57 +0200 Subject: [PATCH 05/38] [FIX] typo in setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 58b66138..7cfaf230 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,7 @@ install_requires = dev = scrypt >= 0.8.18 sphinx >= 4.3.1 - coveralls > =3.0.1 + coveralls >= 3.0.1 psycopg2 >= 2.9.2 mysql-connector-python >= 8.0.27 mysqlclient >= 2.1.0 From bfd39ded22abe34381489803a41d38301e560151 Mon Sep 17 00:00:00 2001 From: Lennart Date: Sun, 17 Sep 2023 16:04:58 +0200 Subject: [PATCH 06/38] [FIX] Bypass confirmation prompt --- .github/workflows/unittests-noscrypt.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unittests-noscrypt.yaml b/.github/workflows/unittests-noscrypt.yaml index 91070810..9dae687c 100644 --- a/.github/workflows/unittests-noscrypt.yaml +++ b/.github/workflows/unittests-noscrypt.yaml @@ -16,7 +16,7 @@ jobs: - name: Install dependencies run: | python -m pip install .[dev] - pip uninstall scrypt + pip uninstall -y scrypt - name: Test with coverage env: BCL_CONFIG_FILE: config_encryption.ini.unittest From ae354c9b0efb09fd2beb5d3cfc56a2c20852392b Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 23 Oct 2023 20:45:03 +0200 Subject: [PATCH 07/38] [FIX] Using wrong type when extracting key from script --- bitcoinlib/transactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitcoinlib/transactions.py b/bitcoinlib/transactions.py index b54166c1..6894e70f 100644 --- a/bitcoinlib/transactions.py +++ b/bitcoinlib/transactions.py @@ -1190,7 +1190,7 @@ def __init__(self, value, address='', public_hash=b'', public_key=b'', lock_scri self.encoding = 'bech32' self.public_hash = self.script.public_hash if self.script.keys: - self.public_key = self.script.keys[0].public_hex + self.public_key = self.script.keys[0].public_byte if self.script_type == 'p2tr': self.witver = self.script.commands[0] - 80 From d935eea0744738667e32ce4bac06c571ec679458 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 30 Oct 2023 19:16:15 +0100 Subject: [PATCH 08/38] [FIX] Correctly parse arguments in bitcoindclient --- bitcoinlib/services/bitcoind.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bitcoinlib/services/bitcoind.py b/bitcoinlib/services/bitcoind.py index 2e4eeaf6..f74001c8 100644 --- a/bitcoinlib/services/bitcoind.py +++ b/bitcoinlib/services/bitcoind.py @@ -53,7 +53,7 @@ class BitcoindClient(BaseClient): """ @staticmethod - def from_config(configfile=None, network='bitcoin'): + def from_config(configfile=None, network='bitcoin', **kwargs): """ Read settings from bitcoind config file @@ -113,9 +113,9 @@ def from_config(configfile=None, network='bitcoin'): server = _read_from_config(config, 'rpc', 'externalip', server) url = "http://%s:%s@%s:%s" % (config.get('rpc', 'rpcuser'), config.get('rpc', 'rpcpassword'), server, port) - return BitcoindClient(network, url) + return BitcoindClient(network, url, **kwargs) - def __init__(self, network='bitcoin', base_url='', denominator=100000000, *args): + def __init__(self, network='bitcoin', base_url='', denominator=100000000, **kwargs): """ Open connection to bitcoin node @@ -123,7 +123,7 @@ def __init__(self, network='bitcoin', base_url='', denominator=100000000, *args) :type: str :param base_url: Connection URL in format http(s)://user:password@host:port. :type: str - :param denominator: Denominator for this currency. Should be always 100000000 (satoshis) for bitcoin + :param denominator: Denominator for this currency. Should be always 100000000 (Satoshi's) for bitcoin :type: str """ if isinstance(network, Network): @@ -134,7 +134,7 @@ def __init__(self, network='bitcoin', base_url='', denominator=100000000, *args) network = bdc.network _logger.info("Connect to bitcoind") self.proxy = AuthServiceProxy(base_url) - super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, *args) + super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, **kwargs) def getbalance(self, addresslist): balance = 0 From 9de639b1812296229664fc33ea87b5ba2dd5ec40 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 30 Oct 2023 19:30:10 +0100 Subject: [PATCH 09/38] [FIX] Also fix arguments in Litecoind and other clients --- bitcoinlib/services/dashd.py | 8 ++++---- bitcoinlib/services/dogecoind.py | 8 ++++---- bitcoinlib/services/litecoind.py | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bitcoinlib/services/dashd.py b/bitcoinlib/services/dashd.py index de5aec20..1178d626 100644 --- a/bitcoinlib/services/dashd.py +++ b/bitcoinlib/services/dashd.py @@ -56,7 +56,7 @@ class DashdClient(BaseClient): """ @staticmethod - def from_config(configfile=None, network='dash'): + def from_config(configfile=None, network='dash', **kargs): """ Read settings from dashd config file @@ -104,9 +104,9 @@ def from_config(configfile=None, network='dash'): elif 'externalip' in config['rpc']: server = config.get('rpc', 'externalip') url = "http://%s:%s@%s:%s" % (config.get('rpc', 'rpcuser'), config.get('rpc', 'rpcpassword'), server, port) - return DashdClient(network, url) + return DashdClient(network, url, **kargs) - def __init__(self, network='dash', base_url='', denominator=100000000, *args): + def __init__(self, network='dash', base_url='', denominator=100000000, **kargs): """ Open connection to dashcore node @@ -123,7 +123,7 @@ def __init__(self, network='dash', base_url='', denominator=100000000, *args): network = bdc.network _logger.info("Connect to dashd") self.proxy = AuthServiceProxy(base_url) - super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, *args) + super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, **kargs) def _parse_transaction(self, tx, block_height=None, get_input_values=True): t = Transaction.parse_hex(tx['hex'], strict=self.strict, network=self.network) diff --git a/bitcoinlib/services/dogecoind.py b/bitcoinlib/services/dogecoind.py index 2efe737b..1a1ffc31 100644 --- a/bitcoinlib/services/dogecoind.py +++ b/bitcoinlib/services/dogecoind.py @@ -54,7 +54,7 @@ class DogecoindClient(BaseClient): """ @staticmethod - def from_config(configfile=None, network='dogecoin'): + def from_config(configfile=None, network='dogecoin', **kargs): """ Read settings from dogecoind config file @@ -113,9 +113,9 @@ def from_config(configfile=None, network='dogecoin'): server = _read_from_config(config, 'rpc', 'externalip', server) url = "http://%s:%s@%s:%s" % (config.get('rpc', 'rpcuser'), config.get('rpc', 'rpcpassword'), server, port) - return DogecoindClient(network, url) + return DogecoindClient(network, url, **kargs) - def __init__(self, network='dogecoin', base_url='', denominator=100000000, *args): + def __init__(self, network='dogecoin', base_url='', denominator=100000000, **kargs): """ Open connection to dogecoin node @@ -141,7 +141,7 @@ def __init__(self, network='dogecoin', base_url='', denominator=100000000, *args "Please replace default password and set url in providers.json or dogecoin.conf file") _logger.info("Connect to dogecoind") self.proxy = AuthServiceProxy(base_url) - super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, *args) + super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, **kargs) def getutxos(self, address, after_txid='', max_txs=MAX_TRANSACTIONS): txs = [] diff --git a/bitcoinlib/services/litecoind.py b/bitcoinlib/services/litecoind.py index 1f0c36ee..1f708117 100644 --- a/bitcoinlib/services/litecoind.py +++ b/bitcoinlib/services/litecoind.py @@ -53,7 +53,7 @@ class LitecoindClient(BaseClient): """ @staticmethod - def from_config(configfile=None, network='litecoin'): + def from_config(configfile=None, network='litecoin', **kargs): """ Read settings from litecoind config file @@ -112,9 +112,9 @@ def from_config(configfile=None, network='litecoin'): server = _read_from_config(config, 'rpc', 'bind', server) server = _read_from_config(config, 'rpc', 'externalip', server) url = "http://%s:%s@%s:%s" % (config.get('rpc', 'rpcuser'), config.get('rpc', 'rpcpassword'), server, port) - return LitecoindClient(network, url) + return LitecoindClient(network, url, **kargs) - def __init__(self, network='litecoin', base_url='', denominator=100000000, *args): + def __init__(self, network='litecoin', base_url='', denominator=100000000, **kargs): """ Open connection to litecoin node @@ -133,7 +133,7 @@ def __init__(self, network='litecoin', base_url='', denominator=100000000, *args network = bdc.network _logger.info("Connect to litecoind") self.proxy = AuthServiceProxy(base_url) - super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, *args) + super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, **kargs) def getbalance(self, addresslist): balance = 0 From 094d3041bb08a9db66a585fd1f66ecc30d1141d0 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 2 Nov 2023 19:41:52 +0100 Subject: [PATCH 10/38] [REF] Test python 3.11 in windows --- .github/workflows/unittests_windows.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unittests_windows.yaml b/.github/workflows/unittests_windows.yaml index 08800c2b..dcd04f95 100644 --- a/.github/workflows/unittests_windows.yaml +++ b/.github/workflows/unittests_windows.yaml @@ -11,7 +11,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v3 with: - python-version: '3.9' + python-version: '3.11' architecture: 'x64' - name: Install dependencies run: | From 6c82ac40ac66cfec2fd010d7bbcf70d5df46e623 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 2 Nov 2023 20:10:13 +0100 Subject: [PATCH 11/38] [REF] Convert encoding to lowercase --- bitcoinlib/config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitcoinlib/config/config.py b/bitcoinlib/config/config.py index b0284f50..8227eb34 100644 --- a/bitcoinlib/config/config.py +++ b/bitcoinlib/config/config.py @@ -120,7 +120,7 @@ 1000000000000000000000000: 'Y', } -if os.name == 'nt' and locale.getpreferredencoding() != 'UTF-8': +if os.name == 'nt' and locale.getpreferredencoding().lower() != 'utf-8': # TODO: Find a better windows hack import _locale _locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8']) From e4ce8fb993bde2fed961df3e9f5075732ba83d1b Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 2 Nov 2023 20:42:49 +0100 Subject: [PATCH 12/38] [REF] Do not overwrite language settings when setting locale --- bitcoinlib/config/config.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bitcoinlib/config/config.py b/bitcoinlib/config/config.py index 8227eb34..d39da1ba 100644 --- a/bitcoinlib/config/config.py +++ b/bitcoinlib/config/config.py @@ -121,10 +121,12 @@ } if os.name == 'nt' and locale.getpreferredencoding().lower() != 'utf-8': - # TODO: Find a better windows hack + # import _locale + # _locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8']) import _locale - _locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8']) -elif locale.getpreferredencoding() != 'UTF-8': + _locale._gdl_bak = _locale._getdefaultlocale + _locale._getdefaultlocale = (lambda *args: (_locale._gdl_bak()[0], 'utf8')) +elif locale.getpreferredencoding().lower() != 'utf-8': raise EnvironmentError("Locale is currently set to '%s'. " "This library needs the locale set to UTF-8 to function properly" % locale.getpreferredencoding()) From 6afd43eca9679c75e0bf7372ec01c43303262826 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 2 Nov 2023 20:56:34 +0100 Subject: [PATCH 13/38] [REF] Try running windows in UTF-8 mode --- .github/workflows/unittests_windows.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/unittests_windows.yaml b/.github/workflows/unittests_windows.yaml index dcd04f95..59c1d772 100644 --- a/.github/workflows/unittests_windows.yaml +++ b/.github/workflows/unittests_windows.yaml @@ -27,4 +27,5 @@ jobs: env: BCL_CONFIG_FILE: config.ini.unittest UNITTESTS_FULL_DATABASE_TEST: False + PYTHONUTF8: 1 run: coverage run --source=bitcoinlib -m unittest -v From c22f96fa2a80b2e5ee1849debdd71ba1e701ba6f Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 2 Nov 2023 21:19:55 +0100 Subject: [PATCH 14/38] [UPD] Add info about utf8 mode for Windows: --- bitcoinlib/config/config.py | 2 -- docs/_static/manuals.install.rst | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bitcoinlib/config/config.py b/bitcoinlib/config/config.py index d39da1ba..95d5733d 100644 --- a/bitcoinlib/config/config.py +++ b/bitcoinlib/config/config.py @@ -121,8 +121,6 @@ } if os.name == 'nt' and locale.getpreferredencoding().lower() != 'utf-8': - # import _locale - # _locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8']) import _locale _locale._gdl_bak = _locale._getdefaultlocale _locale._getdefaultlocale = (lambda *args: (_locale._gdl_bak()[0], 'utf8')) diff --git a/docs/_static/manuals.install.rst b/docs/_static/manuals.install.rst index 89588c4e..e63a54f0 100644 --- a/docs/_static/manuals.install.rst +++ b/docs/_static/manuals.install.rst @@ -108,6 +108,10 @@ for steps you could take to install this library. If you have problems with installing this library on Windows you could try to use the pycryptodome library instead of scrypt. The pycryptodome library is pure Python so it doesn't need any C compilers installed. But this will run slower. +When using Python on Windows it needs to be set to UTF-8 mode. You can do this by adding the PYTHONUTF8=1 to the +environment variables or use the -X utf8 command line option. Please see +https://docs.python.org/3/using/windows.html#win-utf8-mode for more information. + Update Bitcoinlib ----------------- From 84b3e23857caac56a87b62e2b605d12dd2e7fd10 Mon Sep 17 00:00:00 2001 From: Lennart Date: Tue, 7 Nov 2023 21:30:06 +0100 Subject: [PATCH 15/38] [FIX] Listing bitcoin account when default is other network --- bitcoinlib/wallets.py | 5 +++-- tests/test_wallets.py | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bitcoinlib/wallets.py b/bitcoinlib/wallets.py index bc94a02d..23c43ec6 100644 --- a/bitcoinlib/wallets.py +++ b/bitcoinlib/wallets.py @@ -2508,16 +2508,17 @@ def account(self, account_id): key_id = qr.id return self.key(key_id) - def accounts(self, network=DEFAULT_NETWORK): + def accounts(self, network=None): """ Get list of accounts for this wallet - :param network: Network name filter. Default filter is DEFAULT_NETWORK + :param network: Network name filter. Default filter is network of first main key :type network: str :return list of integers: List of accounts IDs """ + network, _, _ = self._get_account_defaults(network) if self.multisig and self.cosigner: if self.cosigner_id is None: raise WalletError("Missing Cosigner ID value for this wallet, cannot fetch account ID") diff --git a/tests/test_wallets.py b/tests/test_wallets.py index f0833b28..dcc1fb5b 100644 --- a/tests/test_wallets.py +++ b/tests/test_wallets.py @@ -2617,6 +2617,13 @@ def test_wallet_normalize_path(self): self.assertRaisesRegexp(WalletError, 'Could not parse path. Index is empty.', normalize_path, "m/44h/0p/100H//1201") + def test_wallet_accounts(self): + w = Wallet.create('test_litecoin_accounts', network='litecoin', account_id=1111, db_uri=self.DATABASE_URI) + w.new_account(account_id=2222) + w.new_account(account_id=5555, network='testnet') + self.assertListEqual(w.accounts(), [1111, 2222]) + self.assertListEqual(w.accounts(network='testnet'), [5555]) + @parameterized_class(*params) class TestWalletReadonlyAddress(TestWalletMixin, unittest.TestCase): From fa927d8d8a55dfe7fa2c5da6eb96db1b7c2beb89 Mon Sep 17 00:00:00 2001 From: Lennart Date: Wed, 22 Nov 2023 20:28:23 +0100 Subject: [PATCH 16/38] [FIX] Do not install scrypt for windows unittesting --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 7cfaf230..9595ddfe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,7 +44,7 @@ install_requires = [options.extras_require] dev = - scrypt >= 0.8.18 + scrypt >= 0.8.18;platform_system!="Windows" sphinx >= 4.3.1 coveralls >= 3.0.1 psycopg2 >= 2.9.2 From b11604bf6eb0065839faf111512e722b7d5fa38a Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 23 Nov 2023 21:12:46 +0100 Subject: [PATCH 17/38] [UPD] Update required packages versions --- requirements.txt | 6 +++--- setup.cfg | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4ce7c391..151bfeed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,14 +2,14 @@ requests>=2.25.0 fastecdsa>=2.2.1 scrypt>=0.8.18 pycryptodome>=3.14.1 -SQLAlchemy>=1.4.45 +SQLAlchemy>=2.0.0 numpy>=1.22.0 -sphinx>=4.3.1 +sphinx>=6.0.0 coveralls>=3.0.1 psycopg2>=2.9.2 mysql-connector-python>=8.0.27 mysqlclient>=2.1.0 parameterized>=0.8.1 sphinx_rtd_theme>=1.0.0 -Cython +Cython>=3.0.0 win-unicode-console;platform_system=="Windows" diff --git a/setup.cfg b/setup.cfg index 9595ddfe..9dbfa68e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,21 +38,21 @@ install_requires = fastecdsa >= 2.2.1;platform_system!="Windows" ecdsa >= 0.17 pycryptodome >= 3.14.1 - SQLAlchemy >= 1.4.28 + SQLAlchemy >= 2.0.0 numpy == 1.19.5;python_version<"3.9" numpy >= 1.22.0;python_version>="3.9" [options.extras_require] dev = scrypt >= 0.8.18;platform_system!="Windows" - sphinx >= 4.3.1 + sphinx >= 6.0.0 coveralls >= 3.0.1 psycopg2 >= 2.9.2 mysql-connector-python >= 8.0.27 mysqlclient >= 2.1.0 parameterized >= 0.8.1 sphinx_rtd_theme >= 1.0.0 - Cython + Cython>=3.0.0 win-unicode-console;platform_system=="Windows" [options.entry_points] From 35c04dffea41efe974bd0b173dc022da9b23bdc4 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 23 Nov 2023 22:11:51 +0100 Subject: [PATCH 18/38] [ADD] Unittest for keys hash method --- tests/test_keys.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_keys.py b/tests/test_keys.py index e535145e..aa6033a5 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -47,6 +47,7 @@ def test_keys_classes_dunder_methods(self): b'\x84\xf2\xb4\x00k\x03\xdc\x86qk+\xe2z\x05uU\x8b\xacs\'\x92\x90\xac"' b'\xc3\xea\x02@\xe4*!R\xd5\x84\xf2\xb4\x00k') self.assertEqual(k + k2, k.public_byte + k2.public_byte) + self.assertEqual(hash(k), hash(k)) def test_dict_and_json_outputs(self): k = HDKey() From 2a71800483371f77bf3ba7ad2148acab4454d45e Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 23 Nov 2023 22:59:02 +0100 Subject: [PATCH 19/38] [REL] RELEASE 0.6.13 - Update config and bugfixes --- CHANGELOG | 6 ++++++ bitcoinlib/config/VERSION | 2 +- docs/conf.py | 2 +- setup.cfg | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0a1ad289..e591bcfa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +RELEASE 0.6.13 - Update config & fix some bugs +============================================== +* Rewrite configuration files for easier installation +* Fix issues with bitcoind and litecoind client +* Fix encoding issues with Python3.11 and Windows + RELEASE 0.6.12 - Prepare for Taproot ==================================== * Parse p2tr input scripts diff --git a/bitcoinlib/config/VERSION b/bitcoinlib/config/VERSION index e9acb99e..4655c9e9 100644 --- a/bitcoinlib/config/VERSION +++ b/bitcoinlib/config/VERSION @@ -1 +1 @@ -0.6.12 \ No newline at end of file +0.6.13 \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index c0d1f67c..21182508 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -45,7 +45,7 @@ # The short X.Y version. version = '0.6' # The full version, including alpha/beta/rc tags. -release = '0.6.12' +release = '0.6.13' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.cfg b/setup.cfg index 9dbfa68e..4681f4b3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = bitcoinlib -version = 0.6.12 +version = 0.6.13 url = http://github.com/1200wd/bitcoinlib author = 1200wd author_email = info@1200wd.com From 771b9f1329e1bce332c119fc4614463887ad0d5a Mon Sep 17 00:00:00 2001 From: Lennart Date: Wed, 29 Nov 2023 17:58:37 +0100 Subject: [PATCH 20/38] [FIX] Issue when using hexdecimal password for Mnemonic --- bitcoinlib/mnemonic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitcoinlib/mnemonic.py b/bitcoinlib/mnemonic.py index 52612dad..54adbbf1 100644 --- a/bitcoinlib/mnemonic.py +++ b/bitcoinlib/mnemonic.py @@ -82,8 +82,8 @@ def to_seed(self, words, password='', validate=True): # Check if passphrase is valid if validate: self.to_entropy(words) - mnemonic = to_bytes(words) - password = to_bytes(password) + mnemonic = bytes(words, 'utf8') + password = bytes(password, 'utf8') return hashlib.pbkdf2_hmac(hash_name='sha512', password=mnemonic, salt=b'mnemonic' + password, iterations=2048) From c6efbdeb137c9850ca5a10b01ed1b48e26589f79 Mon Sep 17 00:00:00 2001 From: yoprogramo Date: Thu, 30 Nov 2023 13:01:27 +0100 Subject: [PATCH 21/38] Change kwargs by args on constructors --- bitcoinlib/services/bitcoind.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bitcoinlib/services/bitcoind.py b/bitcoinlib/services/bitcoind.py index f74001c8..6bdb1878 100644 --- a/bitcoinlib/services/bitcoind.py +++ b/bitcoinlib/services/bitcoind.py @@ -53,7 +53,7 @@ class BitcoindClient(BaseClient): """ @staticmethod - def from_config(configfile=None, network='bitcoin', **kwargs): + def from_config(configfile=None, network='bitcoin', *args): """ Read settings from bitcoind config file @@ -113,9 +113,9 @@ def from_config(configfile=None, network='bitcoin', **kwargs): server = _read_from_config(config, 'rpc', 'externalip', server) url = "http://%s:%s@%s:%s" % (config.get('rpc', 'rpcuser'), config.get('rpc', 'rpcpassword'), server, port) - return BitcoindClient(network, url, **kwargs) + return BitcoindClient(network, url, *args) - def __init__(self, network='bitcoin', base_url='', denominator=100000000, **kwargs): + def __init__(self, network='bitcoin', base_url='', denominator=100000000, *args): """ Open connection to bitcoin node @@ -134,7 +134,7 @@ def __init__(self, network='bitcoin', base_url='', denominator=100000000, **kwar network = bdc.network _logger.info("Connect to bitcoind") self.proxy = AuthServiceProxy(base_url) - super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, **kwargs) + super(self.__class__, self).__init__(network, PROVIDERNAME, base_url, denominator, *args) def getbalance(self, addresslist): balance = 0 From 4ee79c9c6baf6d7d9159a7316552ea79729f4f02 Mon Sep 17 00:00:00 2001 From: yoprogramo Date: Tue, 5 Dec 2023 13:36:24 +0100 Subject: [PATCH 22/38] Error si strict=False --- bitcoinlib/transactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitcoinlib/transactions.py b/bitcoinlib/transactions.py index 6894e70f..58ccb43c 100644 --- a/bitcoinlib/transactions.py +++ b/bitcoinlib/transactions.py @@ -859,7 +859,7 @@ def __init__(self, prev_txid, output_n, keys=None, signatures=None, public_hash= b'\0' not in self.witnesses: self.signatures = [Signature.parse_bytes(self.witnesses[0])] self.hash_type = self.signatures[0].hash_type - self.keys = [Key(self.witnesses[1], network=self.network)] + self.keys = [Key(self.witnesses[1], network=self.network, strict=self.strict)] self.update_scripts(hash_type=self.hash_type) From e1ab456da79e4b616910e5302b2264354528264f Mon Sep 17 00:00:00 2001 From: Lennart Date: Fri, 8 Dec 2023 13:07:16 +0100 Subject: [PATCH 23/38] [UPD] regtest address prefix is bcrt --- bitcoinlib/data/networks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitcoinlib/data/networks.json b/bitcoinlib/data/networks.json index 5eac02c3..3530125c 100644 --- a/bitcoinlib/data/networks.json +++ b/bitcoinlib/data/networks.json @@ -107,7 +107,7 @@ "currency_code": "rBTC", "prefix_address": "00", "prefix_address_p2sh": "05", - "prefix_bech32": "bc", + "prefix_bech32": "bcrt", "prefix_wif": "80", "prefixes_wif": [ ["0488B21E", "xpub", "public", false, "legacy", "p2pkh"], From afca4cce853e2d58a5e834f374ca12a3ea16b24a Mon Sep 17 00:00:00 2001 From: Lennart Date: Fri, 8 Dec 2023 13:13:05 +0100 Subject: [PATCH 24/38] [REF] Add extra unittest for p2tr reg- address generation --- tests/test_keys.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_keys.py b/tests/test_keys.py index aa6033a5..de702836 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -731,6 +731,12 @@ def test_keys_address_p2tr(self): address = 'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297' self.assertEqual(Address(hashed_data=public_hash, script_type='p2tr', encoding='bech32').address, address) + def test_keys_address_p2tr_bcrt(self): + # Compared with taproot-workshop p2tr address generation + hashed_data = '07bd8d4b39db0ee37e17a5e814b41a8aa33ef3a72742bcc65c716e4ce0f1d8cf' + addr = Address(hashed_data=hashed_data, script_type='p2tr', prefix='bcrt', + encoding='bech32').address + self.assertEqual(addr, 'bcrt1pq77c6jeemv8wxlsh5h5pfdq6323naua8yapte3juw9hyec83mr8sw2eggg') class TestKeysDash(unittest.TestCase): def test_format_wif_compressed_private_dash(self): From 9467891d8bd3bcd4efed4e039665e0783e855a0a Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 11 Dec 2023 21:00:24 +0100 Subject: [PATCH 25/38] [UPD] Update development installations instructions --- docs/_static/manuals.install.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/_static/manuals.install.rst b/docs/_static/manuals.install.rst index e63a54f0..ff05072c 100644 --- a/docs/_static/manuals.install.rst +++ b/docs/_static/manuals.install.rst @@ -24,8 +24,8 @@ Create a virtual environment for instance on linux with virtualenv: .. code-block:: bash - $ virtualenv -p python3 venv/bitcoinlib - $ source venv/bitcoinlib/bin/activate + $ virtualenv -p ~/.virtualenvs/bitcoinlib + $ source ~/.virtualenvs/bitcoinlib/bin/activate Then clone the repository and install dependencies: @@ -33,7 +33,13 @@ Then clone the repository and install dependencies: $ git clone https://github.com/1200wd/bitcoinlib.git $ cd bitcoinlib - $ pip install -r requirements-dev.txt + $ python -m pip install .[dev] + +You can test your local installation by running all unittests: + +.. code-block:: bash + + $ python -m unittest From 8042a02f9a0cf797b2550946e8c4db49343a6b39 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 11 Dec 2023 21:31:15 +0100 Subject: [PATCH 26/38] [UPD] Remove scrypt references from installation instructions, pycryptodome works just as fast --- docs/_static/manuals.install.rst | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/docs/_static/manuals.install.rst b/docs/_static/manuals.install.rst index ff05072c..e49ca810 100644 --- a/docs/_static/manuals.install.rst +++ b/docs/_static/manuals.install.rst @@ -33,7 +33,7 @@ Then clone the repository and install dependencies: $ git clone https://github.com/1200wd/bitcoinlib.git $ cd bitcoinlib - $ python -m pip install .[dev] + $ python -m pip install . You can test your local installation by running all unittests: @@ -42,7 +42,6 @@ You can test your local installation by running all unittests: $ python -m unittest - Package dependencies ~~~~~~~~~~~~~~~~~~~~ @@ -54,10 +53,6 @@ Required Python Packages, are automatically installed upon installing bitcoinlib * numpy * pycryptodome -If you want to use BIP38 encrypted private keys, it is strongly advised to install the much faster scrypt library. - -``pip install scrypt`` - Other requirements Linux ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -92,11 +87,11 @@ Check for the latest version of the PostgreSQL dev server: From library root directory install the Python requirements -``pip install -r requirements-dev.txt`` +``python -m pip install .[dev]`` Then run the unittests to see if everything works -``python setup.py test`` +``python -m unittest`` @@ -111,9 +106,6 @@ The fastecdsa library is not enabled at this moment in the windows install, the Installation of fastecdsa on Windows is possible but not easy, read https://github.com/AntonKueltz/fastecdsa/issues/11 for steps you could take to install this library. -If you have problems with installing this library on Windows you could try to use the pycryptodome library instead of -scrypt. The pycryptodome library is pure Python so it doesn't need any C compilers installed. But this will run slower. - When using Python on Windows it needs to be set to UTF-8 mode. You can do this by adding the PYTHONUTF8=1 to the environment variables or use the -X utf8 command line option. Please see https://docs.python.org/3/using/windows.html#win-utf8-mode for more information. @@ -157,21 +149,12 @@ of database changes. So backup database / private keys first and use at your own Troubleshooting --------------- -When you experience issues with the scrypt package when installing you can try to solve this by installing -scrypt separately: - -.. code-block:: bash - - $ pip uninstall scrypt - $ pip install scrypt - -Please make sure you also have the Python development and SSL development packages installed, see 'Other requirements' +Please make sure you have the Python development and SSL development packages installed, see 'Other requirements' above. -You can also use pycryptodome or pyscrypt instead of scrypt. Pycryptodome is a pure Python scrypt password-based key +You can also use pycryptodome, pyscrypt or scrypt. pyscript is a pure Python scrypt password-based key derivation library. It works but it is slow when using BIP38 password protected keys. - If you run into issues do not hesitate to contact us or file an issue at https://github.com/1200wd/bitcoinlib/issues From 5bb29127f94f218a53cdd2866a765a1131d2beb6 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 14 Dec 2023 21:43:22 +0100 Subject: [PATCH 27/38] [UPD] Dev install instructions for other linux systems --- docs/_static/manuals.install.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/_static/manuals.install.rst b/docs/_static/manuals.install.rst index e49ca810..b82adb87 100644 --- a/docs/_static/manuals.install.rst +++ b/docs/_static/manuals.install.rst @@ -16,9 +16,9 @@ Package can be found at https://pypi.org/project/bitcoinlib/ Install from source ~~~~~~~~~~~~~~~~~~~ -Required packages: +Required packages for Ubuntu, for other systems see below: -``sudo apt install -y postgresql postgresql-contrib mysql-server libpq-dev libmysqlclient-dev`` +``apt install build-essential python3-dev libgmp3-dev pkg-config postgresql postgresql-contrib mariadb-server libpq-dev libmysqlclient-dev pkg-config`` Create a virtual environment for instance on linux with virtualenv: @@ -59,19 +59,19 @@ Other requirements Linux On Debian, Ubuntu or their derivatives: -``sudo apt install build-essential python3-dev libgmp3-dev`` +``apt install build-essential python3-dev libgmp3-dev pkg-config postgresql postgresql-contrib mariadb-server libpq-dev libmysqlclient-dev pkg-config`` On Fedora, CentOS or RHEL: -``sudo dnf install python3-devel gmp-devel`` +``dnf install python3-devel gmp-devel`` -To install OpenSSL development package on Debian, Ubuntu or their derivatives +On Alpine Linux, lightweight Linux used for Docker images: -``sudo apt install libssl-dev`` +``apk add python3-dev gmp-dev py3-pip gcc musl-dev libpq-dev postgresql postgresql-contrib mariadb-dev mysql-client`` -To install OpenSSL development package on Fedora, CentOS or RHEL +On Kali linux: -``sudo yum install gcc openssl-devel`` +``apt install libgmp3-dev postgresql postgresql-contrib libpq-dev pkg-config default-libmysqlclient-dev default-mysql-server`` Development environment @@ -79,11 +79,11 @@ Development environment Install database packages for MySQL and PostgreSQL -``sudo apt install mysql-server postgresql postgresql-contrib libmysqlclient-dev`` +``apt install mysql-server postgresql postgresql-contrib libmysqlclient-dev pkg-config libpq-dev`` Check for the latest version of the PostgreSQL dev server: -``sudo apt install postgresql-server-dev-`` +``apt install postgresql-server-dev-`` From library root directory install the Python requirements From 1d03dc2a2b53ada894815b6e1c81f87a2158e7b1 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 14 Dec 2023 21:59:25 +0100 Subject: [PATCH 28/38] [REF] Replace all deprecated self.assertRaisesRegexp methods --- tests/test_keys.py | 34 ++++++------ tests/test_mnemonic.py | 14 ++--- tests/test_networks.py | 2 +- tests/test_script.py | 4 +- tests/test_services.py | 4 +- tests/test_transactions.py | 14 ++--- tests/test_wallets.py | 110 ++++++++++++++++++------------------- 7 files changed, 91 insertions(+), 91 deletions(-) diff --git a/tests/test_keys.py b/tests/test_keys.py index de702836..602eb992 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -69,9 +69,9 @@ def test_path_expand(self): self.assertListEqual(path_expand([], witness_type='p2sh-segwit'), ['m', "49'", "0'", "0'", '0', '0']) self.assertListEqual(path_expand([99], witness_type='p2sh-segwit', multisig=True), ['m', "48'", "0'", "0'", "1'", '0', '99']) - self.assertRaisesRegexp(BKeyError, "Invalid path provided. Path should be shorter than 6 items.", + self.assertRaisesRegex(BKeyError, "Invalid path provided. Path should be shorter than 6 items.", path_expand, [0, 1, 2, 3, 4, 5, 6]) - self.assertRaisesRegexp(BKeyError, "Please provide path as list with at least 1 item", + self.assertRaisesRegex(BKeyError, "Please provide path as list with at least 1 item", path_expand, 5) @@ -110,8 +110,8 @@ def test_format_hdkey_mnemonic(self): self.assertEqual(get_key_format('abandon car zoo')['format'], 'mnemonic') def test_format_key_exceptions(self): - self.assertRaisesRegexp(BKeyError, "Key empty, please specify a valid key", get_key_format, '') - self.assertRaisesRegexp(BKeyError, "Attribute 'is_private' must be False or True", get_key_format, + self.assertRaisesRegex(BKeyError, "Key empty, please specify a valid key", get_key_format, '') + self.assertRaisesRegex(BKeyError, "Attribute 'is_private' must be False or True", get_key_format, '666368e477a8ddd46808c527cc3c506719bb3f52a927b6c13532984b714b56ad', 3) @@ -185,11 +185,11 @@ def test_private_key_import_generate_random(self): self.assertEqual(52, len(self.k.wif())) def test_private_key_import_error_1(self): - self.assertRaisesRegexp(BKeyError, "Invalid checksum, not a valid WIF key", + self.assertRaisesRegex(BKeyError, "Invalid checksum, not a valid WIF key", Key, 'L1odb1uUozbfK2NrsMyhJfvRsxGM2axixgPL8vG9BUBnE6W1VyTX') def test_private_key_import_error_2(self): - self.assertRaisesRegexp(BKeyError, "Unrecognised key format", + self.assertRaisesRegex(BKeyError, "Unrecognised key format", Key, 'M1odb1uUozbfK2NrsMyhJfvRsxGM2AxixgPL8vG9BUBnE6W1VyTX') def test_private_key_import_testnet(self): @@ -238,7 +238,7 @@ def test_public_key_try_private(self): self.assertFalse(self.K.private_hex) def test_public_key_import_error(self): - self.assertRaisesRegexp(BKeyError, "Unrecognised key format", + self.assertRaisesRegex(BKeyError, "Unrecognised key format", Key, '064781e448a7ff0e1b66f1a249b4c952dae33326cf57c0a643738886f4efcd14d5') def test_litecoin_private_key(self): @@ -449,10 +449,10 @@ def test_hdkey_bip44_account_litecoin(self): def test_hdkey_derive_from_public_error(self): k = HDKey().public() - self.assertRaisesRegexp(BKeyError, "Need a private key to create child private key", k.child_private) + self.assertRaisesRegex(BKeyError, "Need a private key to create child private key", k.child_private) k0 = HDKey() k1 = k0.child_private(10, hardened=True) - self.assertRaisesRegexp(BKeyError, "Cannot derive hardened key from public private key", + self.assertRaisesRegex(BKeyError, "Cannot derive hardened key from public private key", k1.child_public, 2147483659) @@ -573,7 +573,7 @@ def test_bip38_invalid_keys(self): return for v in self.vectors["invalid"]["verify"]: print("Checking invalid key %s" % v['base58']) - self.assertRaisesRegexp(Exception, "", Key, str(v['base58'])) + self.assertRaisesRegex(Exception, "", Key, str(v['base58'])) def test_bip38_other_networks(self): if not USING_MODULE_SCRYPT: @@ -655,16 +655,16 @@ def test_keys_address_encodings(self): self.assertEqual(a.address, 'tb1q8hehumvm039nxnwwtqdjr7qmm46sfxrdw7vc3g') def test_keys_address_deserialize_exceptions(self): - self.assertRaisesRegexp(BKeyError, "Invalid address 17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bb, checksum incorrect", + self.assertRaisesRegex(BKeyError, "Invalid address 17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bb, checksum incorrect", deserialize_address, '17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bb', encoding='base58') - self.assertRaisesRegexp(EncodingError, + self.assertRaisesRegex(EncodingError, "Address 17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bd is not in specified encoding bs", deserialize_address, '17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bd', encoding='bs') - self.assertRaisesRegexp(EncodingError, + self.assertRaisesRegex(EncodingError, "Invalid address 17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bb: " "Invalid bech32 character in bech string", deserialize_address, '17N9VQbP89ThunSq7Yo2VooXCFTW1Lp8bb', encoding='bech32') - self.assertRaisesRegexp(EncodingError, + self.assertRaisesRegex(EncodingError, "Address bc1qk077yl8zf6yty25rgrys8h40j8adun267y3m44 is not in specified " "encoding base58", deserialize_address, 'bc1qk077yl8zf6yty25rgrys8h40j8adun267y3m44', encoding='base58') @@ -925,11 +925,11 @@ def test_signatures_from_r_and_s(self): def test_signatures_rs_out_of_curve(self): outofcurveint = 115792089237316195423570985008687907852837564279074904382605163141518161494339 - self.assertRaisesRegexp(BKeyError, "r is not a positive integer smaller than the curve order", + self.assertRaisesRegex(BKeyError, "r is not a positive integer smaller than the curve order", Signature, outofcurveint, 10) - self.assertRaisesRegexp(BKeyError, "r is not a positive integer smaller than the curve order", + self.assertRaisesRegex(BKeyError, "r is not a positive integer smaller than the curve order", Signature, 0, 10) - self.assertRaisesRegexp(BKeyError, "s is not a positive integer smaller than the curve order", + self.assertRaisesRegex(BKeyError, "s is not a positive integer smaller than the curve order", Signature, 11, outofcurveint) def test_signatures_dunder(self): diff --git a/tests/test_mnemonic.py b/tests/test_mnemonic.py index 02d55f3d..dd0953ff 100644 --- a/tests/test_mnemonic.py +++ b/tests/test_mnemonic.py @@ -57,7 +57,7 @@ def test_mnemonic_generate(self): self.assertEqual(Mnemonic.detect_language(phrase), 'dutch') def test_mnemonic_generate_error(self): - self.assertRaisesRegexp(ValueError, 'Strength should be divisible by 32', Mnemonic().generate, 11) + self.assertRaisesRegex(ValueError, 'Strength should be divisible by 32', Mnemonic().generate, 11) def test_mnemonic_to_entropy(self): phrase = 'usage grid neither voice worry armor sudden core excuse keen stand pudding' @@ -68,22 +68,22 @@ def test_mnemonic_to_mnemonic(self): 'chunk gun celery million wood kite tackle twenty story episode raccoon dutch') self.assertEqual(Mnemonic().to_mnemonic('28acfc94465fd2f6774759d6897ec122', add_checksum=False), 'action filter venture match garlic nut oven modify output dwarf wild cattle') - self.assertRaisesRegexp(ValueError, "Integer value of data should be in secp256k1 domain between 1 and " + self.assertRaisesRegex(ValueError, "Integer value of data should be in secp256k1 domain between 1 and " "secp256k1_n-1", Mnemonic().to_mnemonic, '28acfc94465fd2f6774759d6897ec12228acfc94465fd2f6774759d6897ec12228acfc94465fd2f6774') def test_mnemonic_to_seed_invalid_checksum(self): phrase = "runway truly foil future recall scatter garage over floor clutch shy boat" - self.assertRaisesRegexp(ValueError, "Invalid checksum 0110 for entropy", Mnemonic().to_seed, phrase) + self.assertRaisesRegex(ValueError, "Invalid checksum 0110 for entropy", Mnemonic().to_seed, phrase) def test_mnemonic_exceptions(self): - self.assertRaisesRegexp(ValueError, "Strength should be divisible by 32", Mnemonic().generate, 20) - self.assertRaisesRegexp(ValueError, "Data length in bits should be divisible by 32", Mnemonic().checksum, + self.assertRaisesRegex(ValueError, "Strength should be divisible by 32", Mnemonic().generate, 20) + self.assertRaisesRegex(ValueError, "Data length in bits should be divisible by 32", Mnemonic().checksum, 'aabbccddeeff') - self.assertRaisesRegexp(Warning, "Unrecognised word", + self.assertRaisesRegex(Warning, "Unrecognised word", Mnemonic().sanitize_mnemonic, 'action filter venture match garlic nut oven modify output dwarf wild fiets') - self.assertRaisesRegexp(Warning, "Could not detect language", + self.assertRaisesRegex(Warning, "Could not detect language", Mnemonic().detect_language, 'floep fliep') diff --git a/tests/test_networks.py b/tests/test_networks.py index 2b4b143d..31be4f1c 100644 --- a/tests/test_networks.py +++ b/tests/test_networks.py @@ -49,7 +49,7 @@ def test_networks_network_value_for(self): def test_network_defined(self): self.assertTrue(network_defined('bitcoin')) self.assertFalse(network_defined('bitcoiiin')) - self.assertRaisesRegexp(NetworkError, "Network bitcoiin not found in network definitions", Network, 'bitcoiin') + self.assertRaisesRegex(NetworkError, "Network bitcoiin not found in network definitions", Network, 'bitcoiin') def test_wif_prefix_search(self): exp_dict = { diff --git a/tests/test_script.py b/tests/test_script.py index f7a33522..fe6ad70c 100644 --- a/tests/test_script.py +++ b/tests/test_script.py @@ -550,9 +550,9 @@ def test_script_multisig_errors(self): 'd1b1ec45d76724f26901099416b9265b76ba67c8b0b73d' '210202be80a0ca69c0e000b97d507f45b98c49f58fec6650b64ff70e6ffccc3e6d00' '210202be80a0ca69c0e000b97d507f45b98c49f58fec6650b64ff70e6ffccc3e6d0052ae') - self.assertRaisesRegexp(ScriptError, '3 keys found but 2 keys expected', + self.assertRaisesRegex(ScriptError, '3 keys found but 2 keys expected', Script.parse, scr) - self.assertRaisesRegexp(ScriptError, 'Number of signatures required \(3\) is higher then number of keys \(2\)', + self.assertRaisesRegex(ScriptError, 'Number of signatures required \(3\) is higher then number of keys \(2\)', Script.parse, '532102d9d64770e0510c650cfaa0c05ba34f6faa35a18defcf9f2d493c4c225d93fbf221020c39c418c2' '38ba876d09c4529bdafb2a1295c57ece923997ab693bf0a84189b852ae') diff --git a/tests/test_services.py b/tests/test_services.py index 5f277cac..edd09284 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -326,7 +326,7 @@ def test_service_gettransactions_after_txid_litecoin(self): self.assertEqual(res[0].txid, 'e0c1e90fa2195869905e90d4fa644082dfd0523540c13baea0c7a4e246ef40e4') def test_service_gettransactions_addresslist_error(self): - self.assertRaisesRegexp(ServiceError, "Address parameter must be of type text", + self.assertRaisesRegex(ServiceError, "Address parameter must be of type text", ServiceTest().gettransactions, ['1LGJzocooaciEtsxEVAajLhCymCXNvPoLh', '19KedreX9aR64fN7tnNzVLVFHQAUL6dLzr']) @@ -689,7 +689,7 @@ def test_service_max_providers(self): self.assertEqual(srv.resultcount, 1) def test_service_errors(self): - self.assertRaisesRegexp(ServiceError, "Provider 'unknown_provider' not found in provider definitions", + self.assertRaisesRegex(ServiceError, "Provider 'unknown_provider' not found in provider definitions", Service, providers='unknown_provider') def test_service_mempool(self): diff --git a/tests/test_transactions.py b/tests/test_transactions.py index 1745ae0e..7e99511d 100644 --- a/tests/test_transactions.py +++ b/tests/test_transactions.py @@ -213,7 +213,7 @@ def test_transactions_deserialize_p2sh_output(self): def test_transactions_deserialize_errors(self): rawtx = '01000000000102c114c54564ea09b33c73bfd0237a4d283fe9e73285ad6d34fd3fa42c99f194640300000000ffffffff' - self.assertRaisesRegexp(TransactionError, + self.assertRaisesRegex(TransactionError, 'Input transaction hash not found. Probably malformed raw transaction', Transaction.parse_hex, rawtx) # FIXME: tx.parse_hex() should check remaining size @@ -225,7 +225,7 @@ def test_transactions_deserialize_errors(self): # '3c12b67ddd3cf8127fe054dec971c858252c004bf8016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea36' \ # '8e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5' \ # 'ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae000000' - # self.assertRaisesRegexp(TransactionError, + # self.assertRaisesRegex(TransactionError, # 'Error when deserializing raw transaction, bytes left for locktime must be 4 not 3', # Transaction.parse, rawtx) # rawtx = '01000000000101c114c54564ea09b33c73bfd0237a4d283fe9e73285ad6d34fd3fa42c99f194640300000000ffffffff0200' \ @@ -236,7 +236,7 @@ def test_transactions_deserialize_errors(self): # '3c12b67ddd3cf8127fe054dec971c858252c004bf8016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea36' \ # '8e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70f01874496feff2103c96d495bfdd5' \ # 'ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000' - # self.assertRaisesRegexp(TransactionError, + # self.assertRaisesRegex(TransactionError, # "Error when deserializing raw transaction, bytes left for locktime must be 4 not 3", # Transaction.parse, rawtx) @@ -1029,7 +1029,7 @@ def test_transactions_parse_totals(self): def test_transaction_sendto_wrong_address(self): t = Transaction(network='bitcoin') - self.assertRaisesRegexp(BKeyError, 'Network bitcoin not found in extracted networks*', + self.assertRaisesRegex(BKeyError, 'Network bitcoin not found in extracted networks*', t.add_output, 100000, 'LTK1nK5TyGALmSup5SzhgkX1cnVQrC4cLd') def test_transaction_create_with_address_objects(self): @@ -1052,7 +1052,7 @@ def test_transaction_info(self): self.assertIsNone(t.info()) def test_transaction_errors(self): - self.assertRaisesRegexp(TransactionError, "Please specify a valid witness type: legacy or segwit", + self.assertRaisesRegex(TransactionError, "Please specify a valid witness type: legacy or segwit", Transaction, witness_type='error') @@ -1063,7 +1063,7 @@ def test_transaction_redeemscript_errors(self): keys = [] for n in range(20): keys.append(HDKey().public_hex) - self.assertRaisesRegexp(TransactionError, exp_error, serialize_multisig_redeemscript, keys) + self.assertRaisesRegex(TransactionError, exp_error, serialize_multisig_redeemscript, keys) def test_transaction_script_type_string(self): # Locking script @@ -1178,7 +1178,7 @@ def test_transaction_locktime(self): def test_transaction_get_unlocking_script_type(self): self.assertEqual(get_unlocking_script_type('p2pk'), 'signature') - self.assertRaisesRegexp(TransactionError, "Unknown locking script type troep", get_unlocking_script_type, + self.assertRaisesRegex(TransactionError, "Unknown locking script type troep", get_unlocking_script_type, 'troep') def test_transaction_equal(self): diff --git a/tests/test_wallets.py b/tests/test_wallets.py index dcc1fb5b..407581db 100644 --- a/tests/test_wallets.py +++ b/tests/test_wallets.py @@ -202,21 +202,21 @@ def test_wallet_empty(self): self.assertEqual(len(w2.keys()), 1) self.assertEqual(len(w3.keys()), 1) # Test exceptions - self.assertRaisesRegexp(WalletError, "Wallet 'unknown_wallet_2' not found", wallet_empty, 'unknown_wallet_2', + self.assertRaisesRegex(WalletError, "Wallet 'unknown_wallet_2' not found", wallet_empty, 'unknown_wallet_2', db_uri=self.DATABASE_URI) def test_wallet_delete_not_empty(self): w = Wallet.create('unempty_wallet_test', network='bitcoinlib_test', db_uri=self.DATABASE_URI) w.utxos_update() - self.assertRaisesRegexp(WalletError, "still has unspent outputs. Use 'force=True' to delete this wallet", + self.assertRaisesRegex(WalletError, "still has unspent outputs. Use 'force=True' to delete this wallet", wallet_delete, 'unempty_wallet_test', db_uri=self.DATABASE_URI) self.assertTrue(wallet_delete('unempty_wallet_test', db_uri=self.DATABASE_URI, force=True)) def test_delete_wallet_exception(self): - self.assertRaisesRegexp(WalletError, '', wallet_delete, 'unknown_wallet', db_uri=self.DATABASE_URI) + self.assertRaisesRegex(WalletError, '', wallet_delete, 'unknown_wallet', db_uri=self.DATABASE_URI) def test_wallet_unknown_error(self): - self.assertRaisesRegexp(WalletError, "Wallet 'test_wallet_create_errors10' not found", + self.assertRaisesRegex(WalletError, "Wallet 'test_wallet_create_errors10' not found", Wallet, 'test_wallet_create_errors10', db_uri=self.DATABASE_URI) def test_wallet_duplicate_key_for_path(self): @@ -251,49 +251,49 @@ def test_wallet_create_change_name(self): def test_wallet_create_errors(self): Wallet.create('test_wallet_create_errors', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Wallet with name 'test_wallet_create_errors' already exists", + self.assertRaisesRegex(WalletError, "Wallet with name 'test_wallet_create_errors' already exists", Wallet.create, 'test_wallet_create_errors', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Only bip32 or single key scheme's are supported at the moment", + self.assertRaisesRegex(WalletError, "Only bip32 or single key scheme's are supported at the moment", Wallet.create, 'test_wallet_create_errors2', scheme='raar', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Wallet name '123' invalid, please include letter characters", + self.assertRaisesRegex(WalletError, "Wallet name '123' invalid, please include letter characters", Wallet.create, '123', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Please enter wallet name", + self.assertRaisesRegex(WalletError, "Please enter wallet name", Wallet.create, '', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Witness type unknown not supported at the moment", + self.assertRaisesRegex(WalletError, "Witness type unknown not supported at the moment", Wallet.create, '', witness_type='unknown', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Multisig wallets should use bip32 scheme not single", + self.assertRaisesRegex(WalletError, "Multisig wallets should use bip32 scheme not single", Wallet.create, 'test_wallet_create_errors_multisig', keys=[HDKey(), HDKey()], scheme='single', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Password protected multisig wallets not supported", + self.assertRaisesRegex(WalletError, "Password protected multisig wallets not supported", Wallet.create, 'test_wallet_create_errors_multisig2', keys=[HDKey(), HDKey()], password='geheim', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Number of keys required to sign is greater then number of keys provided", + self.assertRaisesRegex(WalletError, "Number of keys required to sign is greater then number of keys provided", Wallet.create, 'test_wallet_create_errors_multisig3', keys=[HDKey(), HDKey()], sigs_required=3, db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, + self.assertRaisesRegex(WalletError, "Network from key \(dash\) is different then specified network \(bitcoin\)", Wallet.create, 'test_wallet_create_errors_multisig4', keys=[HDKey(), HDKey(network='dash')], db_uri=self.DATABASE_URI) passphrase = 'usual olympic ride small mix follow trend baby stereo sweet lucky lend' - self.assertRaisesRegexp(WalletError, "Please specify network when using passphrase to create a key", + self.assertRaisesRegex(WalletError, "Please specify network when using passphrase to create a key", Wallet.create, 'test_wallet_create_errors3', keys=passphrase, db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Invalid key or address: zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3", + self.assertRaisesRegex(WalletError, "Invalid key or address: zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3", Wallet.create, 'test_wallet_create_errors4', keys='zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Invalid key or address: zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3", + self.assertRaisesRegex(WalletError, "Invalid key or address: zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3", Wallet.create, 'test_wallet_create_errors4', keys='zwqrC7h9pRj7SBhLRDG4FnkNBRQgene3y3', db_uri=self.DATABASE_URI) k = HDKey(network='litecoin').wif_private() - self.assertRaisesRegexp(WalletError, "Invalid key or address", + self.assertRaisesRegex(WalletError, "Invalid key or address", Wallet.create, 'test_wallet_create_errors5', keys=k, network='bitcoin', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Segwit is not supported for Dash wallets", + self.assertRaisesRegex(WalletError, "Segwit is not supported for Dash wallets", Wallet.create, 'test_wallet_create_errors6', keys=HDKey(network='dash'), witness_type='segwit', db_uri=self.DATABASE_URI) k = HDKey().subkey_for_path('m/1/2/3/4/5/6/7') - self.assertRaisesRegexp(WalletError, "Depth of provided public master key 7 does not correspond with key path", + self.assertRaisesRegex(WalletError, "Depth of provided public master key 7 does not correspond with key path", Wallet.create, 'test_wallet_create_errors7', keys=k, db_uri=self.DATABASE_URI) @@ -304,7 +304,7 @@ def test_wallet_rename_duplicate(self): def test_func(): w2.name = 'test_wallet_rename_duplicate1' - self.assertRaisesRegexp(WalletError, "Wallet with name 'test_wallet_rename_duplicate1' already exists", + self.assertRaisesRegex(WalletError, "Wallet with name 'test_wallet_rename_duplicate1' already exists", test_func) def test_wallet_as_dict_json(self): @@ -405,7 +405,7 @@ def test_wallet_import_key_network_error(self): w = Wallet.create( name='Wallet Error', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, + self.assertRaisesRegex(WalletError, "Network litecoin not available in this wallet, please create an account " "for this network first.", w.import_key, 'T43gB4F6k1Ly3YWbMuddq13xLb56hevUDP3RthKArr7FPHjQiXpp', @@ -459,12 +459,12 @@ def test_wallet_import_master_key(self): w = Wallet.create('test_wallet_import_master_key', keys=k.public_master(), db_uri=self.DATABASE_URI) self.assertFalse(w.main_key.is_private) - self.assertRaisesRegexp(WalletError, "Please supply a valid private BIP32 master key with key depth 0", + self.assertRaisesRegex(WalletError, "Please supply a valid private BIP32 master key with key depth 0", w.import_master_key, k.public()) - self.assertRaisesRegexp(WalletError, "Network of Wallet class, main account key and the imported private " + self.assertRaisesRegex(WalletError, "Network of Wallet class, main account key and the imported private " "key must use the same network", w.import_master_key, HDKey(network='litecoin')) - self.assertRaisesRegexp(WalletError, "This key does not correspond to current public master key", + self.assertRaisesRegex(WalletError, "This key does not correspond to current public master key", w.import_master_key, HDKey()) w.import_master_key(k.wif_private()) self.assertTrue(w.main_key.is_private) @@ -472,16 +472,16 @@ def test_wallet_import_master_key(self): k2 = HDKey() w2 = Wallet.create('test_wallet_import_master_key2', keys=k2.subkey_for_path("m/32'"), scheme='single', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Main key is already a private key, cannot import key", + self.assertRaisesRegex(WalletError, "Main key is already a private key, cannot import key", w2.import_master_key, k2) w2.main_key = None - self.assertRaisesRegexp(WalletError, "Main wallet key is not an WalletKey instance", + self.assertRaisesRegex(WalletError, "Main wallet key is not an WalletKey instance", w2.import_master_key, k2) k3 = HDKey() w3 = Wallet.create('test_wallet_import_master_key3', keys=k3.subkey_for_path("m/32'").public(), scheme='single', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "Current main key is not a valid BIP32 public master key", + self.assertRaisesRegex(WalletError, "Current main key is not a valid BIP32 public master key", w3.import_master_key, k3) @@ -595,7 +595,7 @@ def test_wallet_keys_single_key(self): 'ujRHzmBMxE' w = Wallet.create('test_wallet_keys_single_key', wk, scheme='single', db_uri=self.DATABASE_URI) self.assertEqual(w.new_key(), w.new_key()) - self.assertRaisesRegexp(WalletError, + self.assertRaisesRegex(WalletError, "Single wallet has only one \(master\)key. Use get_key\(\) or main_key\(\) method", w.get_keys) @@ -612,7 +612,7 @@ def test_wallet_create_invalid_key(self): key_invalid = HDKey(witness_type='segwit', network='testnet') w = wallet_create_or_open('my-awesome-wallet55', keys=key_correct, witness_type='segwit', network='testnet', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(AssertionError, '', Wallet, 'my-awesome-wallet55', main_key_object=key_invalid, + self.assertRaisesRegex(AssertionError, '', Wallet, 'my-awesome-wallet55', main_key_object=key_invalid, db_uri=self.DATABASE_URI) def test_wallet_single_key(self): @@ -684,13 +684,13 @@ def test_wallet_key_create_from_key(self): w1 = Wallet.create('network_mixup_test_wallet', network='litecoin', db_uri=self.DATABASE_URI) wk1 = WalletKey.from_key('key1', w1.wallet_id, w1._session, key=k1.address_obj) self.assertEqual(wk1.network.name, 'dash') - self.assertRaisesRegexp(WalletError, "Specified network and key network should be the same", + self.assertRaisesRegex(WalletError, "Specified network and key network should be the same", WalletKey.from_key, 'key2', w1.wallet_id, w1._session, key=k2.address_obj, network='bitcoin') w2 = Wallet.create('network_mixup_test_wallet2', network='litecoin', db_uri=self.DATABASE_URI) wk2 = WalletKey.from_key('key1', w2.wallet_id, w2._session, key=k1) self.assertEqual(wk2.network.name, 'dash') - self.assertRaisesRegexp(WalletError, "Specified network and key network should be the same", + self.assertRaisesRegex(WalletError, "Specified network and key network should be the same", WalletKey.from_key, 'key2', w2.wallet_id, w2._session, key=k2, network='bitcoin') wk3 = WalletKey.from_key('key3', w2.wallet_id, w2._session, key=k1) @@ -709,12 +709,12 @@ def test_wallet_key_create_from_key(self): def test_wallet_key_exceptions(self): w = Wallet.create('test_wallet_key_not_found', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, 'Key with id 1000000 not found', WalletKey, 1000000, w._session) - self.assertRaisesRegexp(BKeyError, "Specified key \['litecoin', 'litecoin_legacy'\] is from different " + self.assertRaisesRegex(WalletError, 'Key with id 1000000 not found', WalletKey, 1000000, w._session) + self.assertRaisesRegex(BKeyError, "Specified key \['litecoin', 'litecoin_legacy'\] is from different " "network then specified: bitcoin", WalletKey.from_key, '', w.wallet_id, w._session, 'T3Er8TQUMjkor8JBGm6aPqg1FA2L98MSK52htgNDeSJmfhLYTpgN') - self.assertRaisesRegexp(WalletError, "", w.get_key, cosigner_id=10) + self.assertRaisesRegex(WalletError, "", w.get_key, cosigner_id=10) def test_wallet_key_public_leaks(self): w = wallet_create_or_open("wallet_private", network='testnet', db_uri=self.DATABASE_URI) @@ -824,7 +824,7 @@ def test_wallet_multiple_networks_import_error(self): 'KoMgKnjvAZ6a4Yn2QZg' error_str = "Network bitcoinlib_test not available in this wallet, please create an account for this network " \ "first." - self.assertRaisesRegexp(WalletError, error_str, self.wallet.import_key, pk_dashtest) + self.assertRaisesRegex(WalletError, error_str, self.wallet.import_key, pk_dashtest) def test_wallet_multiple_networks_value(self): pk = 'vprv9DMUxX4ShgxMM1FFB24BgXE3fMYXKicceSdMUtfhyyUzKNkCvPeYrcoZpPezahBEzFc23yHTPj46eqx3jKuQpQFq5kbd2oxDysd' \ @@ -888,7 +888,7 @@ def test_wallet_multi_networks_send_transaction(self): def test_wallet_multi_networks_account_bip44_code_error(self): wlt = Wallet.create("wallet-bip44-code-error", network='testnet', db_uri=self.DATABASE_URI) error_str = "Can not create new account for network litecoin_testnet with same BIP44 cointype" - self.assertRaisesRegexp(WalletError, error_str, wlt.new_account, network='litecoin_testnet') + self.assertRaisesRegex(WalletError, error_str, wlt.new_account, network='litecoin_testnet') def test_wallet_get_account_defaults(self): w = wallet_create_or_open("test_wallet_get_account_defaults", witness_type='segwit', @@ -953,7 +953,7 @@ def test_wallet_bitcoinlib_testnet_sendto_no_funds_txfee(self): w.new_key() w.utxos_update() balance = w.balance() - self.assertRaisesRegexp(WalletError, "Not enough unspent transaction outputs found", + self.assertRaisesRegex(WalletError, "Not enough unspent transaction outputs found", w.send_to, '21DBmFUMQMP7A6KeENXgZQ4wJdSCeGc2zFo', balance, offline=False) def test_wallet_bitcoinlib_testnet_sweep(self): @@ -967,7 +967,7 @@ def test_wallet_bitcoinlib_testnet_sweep(self): w.utxos_update() self.assertIsNone(w.sweep('21DBmFUMQMP7A6KeENXgZQ4wJdSCeGc2zFo', offline=False).error) self.assertEqual(w.utxos(), []) - self.assertRaisesRegexp(WalletError, "Cannot sweep wallet, no UTXO's found", + self.assertRaisesRegex(WalletError, "Cannot sweep wallet, no UTXO's found", w.sweep, '21DBmFUMQMP7A6KeENXgZQ4wJdSCeGc2zFo', offline=False) @@ -1009,7 +1009,7 @@ def test_wallet_multisig_create_2_cosigner_wallets(self): wl1_key = wl1.new_key() wl2_key = wl2.new_key(cosigner_id=wl1.cosigner_id) self.assertEqual(wl1_key.address, wl2_key.address) - self.assertRaisesRegexp(WalletError, "Accounts are not supported for this wallet", wl1.account, 10) + self.assertRaisesRegex(WalletError, "Accounts are not supported for this wallet", wl1.account, 10) def test_wallet_multisig_bitcoinlib_testnet_transaction_send(self): self.db_remove() @@ -1378,7 +1378,7 @@ def test_wallets_multisig_missing_private_and_cosigner(self): hdkey0 = HDKey(k0).public_master_multisig() hdkey1 = HDKey(k1, key_type='single') hdkey2 = HDKey(k2, key_type='single') - self.assertRaisesRegexp(WalletError, + self.assertRaisesRegex(WalletError, "This wallet does not contain any private keys, please specify cosigner_id for " "this wallet", wallet_create_or_open, 'test_wallets_multisig_missing_private_and_cosigner', @@ -1456,7 +1456,7 @@ def test_wallets_multisig_huge_error(self): pk_n = random.randint(0, n_keys - 1) key_list_cosigners = [k.public_master(multisig=True) for k in key_list if k is not key_list[pk_n]] key_list_wallet = [key_list[pk_n]] + key_list_cosigners - self.assertRaisesRegexp(WalletError, 'Redeemscripts with more then 15 keys are non-standard and could ' + self.assertRaisesRegex(WalletError, 'Redeemscripts with more then 15 keys are non-standard and could ' 'result in locked up funds', Wallet.create, wallet_name, keys=key_list_wallet, sigs_required=sigs_req, network=network, db_uri=self.DATABASE_URI) @@ -1845,9 +1845,9 @@ def test_wallet_transaction_fee_limits(self): wlt = Wallet.create('bcltestwlt6', network='bitcoinlib_test', db_uri=self.DATABASE_URI) to_key = wlt.get_key() wlt.utxos_update() - self.assertRaisesRegexp(WalletError, 'Fee per kB of 660 is lower then minimal network fee of 1000', + self.assertRaisesRegex(WalletError, 'Fee per kB of 660 is lower then minimal network fee of 1000', wlt.send_to, to_key.address, 50000000, fee=150) - self.assertRaisesRegexp(WalletError, 'Fee per kB of 1321585 is higher then maximum network fee of 1000000', + self.assertRaisesRegex(WalletError, 'Fee per kB of 1321585 is higher then maximum network fee of 1000000', wlt.send_to, to_key.address, 50000000, fee=300000) def test_wallet_transaction_fee_zero_problem(self): @@ -1985,7 +1985,7 @@ def test_wallet_transaction_send_keyid(self): offline=False) self.assertEqual(t.inputs[0].address, keys[1].address) self.assertTrue(t.verified) - self.assertRaisesRegexp(WalletError, "Not enough unspent transaction outputs found", w.send_to, + self.assertRaisesRegex(WalletError, "Not enough unspent transaction outputs found", w.send_to, 'blt1qtk5swtntg8gvtsyr3kkx3mjcs5ncav84exjvde', 250000000, input_key_id=keys[0].key_id) @@ -2031,15 +2031,15 @@ def test_wallet_transaction_create_exceptions(self): 'FwNjcNknbseoKp1vR2h' wlt = Wallet.create('test_wallet_transaction_create_exceptions', keys=wif, db_uri=self.DATABASE_URI) wlt.utxos_update() - self.assertRaisesRegexp(WalletError, "Output array must be a list of tuples with address and amount. " + self.assertRaisesRegex(WalletError, "Output array must be a list of tuples with address and amount. " "Use 'send_to' method to send to one address", wlt.transaction_create, '217rBycQpv9rjhiLcg94vdZ7muMVLJ9yysJ') inps = wlt.select_inputs(150000000) - self.assertRaisesRegexp(WalletError, "Input array contains 2 UTXO's but max_utxos=1 parameter specified", + self.assertRaisesRegex(WalletError, "Input array contains 2 UTXO's but max_utxos=1 parameter specified", wlt.transaction_create, [('217rBycQpv9rjhiLcg94vdZ7muMVLJ9yysJ', 150000000)], inps, max_utxos=1) wallet_empty('test_wallet_transaction_create_exceptions', db_uri=self.DATABASE_URI) - self.assertRaisesRegexp(WalletError, "UTXO", + self.assertRaisesRegex(WalletError, "UTXO", wlt.transaction_create, [('217rBycQpv9rjhiLcg94vdZ7muMVLJ9yysJ', 150000000)], inps) @@ -2211,7 +2211,7 @@ def test_wallet_avoid_forced_address_reuse2(self): } ] w.utxos_update(utxos=utxos) - self.assertRaisesRegexp(WalletError, "", w.send_to, 'bc1qx76mfmrgvejprscpk8e76d90h94xdhhgnr3jfk', 200001, + self.assertRaisesRegex(WalletError, "", w.send_to, 'bc1qx76mfmrgvejprscpk8e76d90h94xdhhgnr3jfk', 200001, fee=150) def test_wallet_transactions_delete(self): @@ -2413,7 +2413,7 @@ def test_wallet_segwit_p2sh_p2wsh_send(self): def test_wallet_segwit_uncompressed_error(self): k = HDKey(compressed=False, network='bitcoinlib_test') - self.assertRaisesRegexp(BKeyError, 'Uncompressed keys are non-standard', wallet_create_or_open, + self.assertRaisesRegex(BKeyError, 'Uncompressed keys are non-standard', wallet_create_or_open, 'segwit_uncompressed_error', k, witness_type='segwit', network='bitcoinlib_test', db_uri=self.DATABASE_URI) @@ -2528,9 +2528,9 @@ def test_wallet_segwit_multiple_account_paths(self): w.new_account() w.new_account() w.new_account(account_id=100) - self.assertRaisesRegexp(WalletError, "Account with ID 100 already exists for this wallet", + self.assertRaisesRegex(WalletError, "Account with ID 100 already exists for this wallet", w.new_account, 'test', 100) - self.assertRaisesRegexp(WalletError, "Account with ID 1001 not found in this wallet", + self.assertRaisesRegex(WalletError, "Account with ID 1001 not found in this wallet", w.account, 1001) paths = ["m/48'/0'/0'/2'", "m/48'/0'/0'/2'/0/0", "m/48'/0'/0'/2'/1/0", "m/48'/0'/1'/2'", "m/48'/0'/1'/2'/0/0", @@ -2580,9 +2580,9 @@ def test_wallet_path_expand(self): self.assertListEqual(wlt.path_expand(['m', "purpose", "coin_type'", "1", 2, 3]), ['m', "44'", "0'", "1'", '2', '3']) self.assertListEqual(wlt.path_expand([100], -2), ['m', "44'", "0'", "100'"]) - self.assertRaisesRegexp(BKeyError, "Please provide value for 'address_index'", + self.assertRaisesRegex(BKeyError, "Please provide value for 'address_index'", wlt.path_expand, ['m', 45, "cosigner_index", 55, "address_index"]) - self.assertRaisesRegexp(BKeyError, "Variable bestaatnie not found in Key structure definitions in main.py", + self.assertRaisesRegex(BKeyError, "Variable bestaatnie not found in Key structure definitions in main.py", wlt.path_expand, ['m', "bestaatnie'", "coin_type'", "1", 2, 3]) def test_wallet_exotic_key_paths(self): @@ -2614,7 +2614,7 @@ def test_wallet_exotic_key_paths(self): def test_wallet_normalize_path(self): self.assertEqual(normalize_path("m/48h/0p/100H/1200'/1234555"), "m/48'/0'/100'/1200'/1234555") - self.assertRaisesRegexp(WalletError, 'Could not parse path. Index is empty.', normalize_path, + self.assertRaisesRegex(WalletError, 'Could not parse path. Index is empty.', normalize_path, "m/44h/0p/100H//1201") def test_wallet_accounts(self): @@ -2642,7 +2642,7 @@ def test_wallet_readonly_create_and_import(self): self.assertListEqual(w.addresslist(), ['13A1W4jLPP75pzvn2qJ5KyyqG3qPSpb9jM', '12yuSkjKmHzXCFn39PK1XP3XyeoVw9LJdN']) self.assertGreaterEqual(w.balance(), 4532991) - self.assertRaisesRegexp(WalletError, "No unspent", w.send_to, '1ApcyGtcX4DUmfGqPBPY1bvKEh2irLqnhp', 50000) + self.assertRaisesRegex(WalletError, "No unspent", w.send_to, '1ApcyGtcX4DUmfGqPBPY1bvKEh2irLqnhp', 50000) self.assertEqual(w.utxo_last('13A1W4jLPP75pzvn2qJ5KyyqG3qPSpb9jM'), '22965c151d850b5c7d98561e5432459141b1321a299cdcac1764f540eef56451') From 4cd0b089fc6b6f2aa8baa800076934da89d8ade0 Mon Sep 17 00:00:00 2001 From: Lennart Date: Thu, 14 Dec 2023 22:20:01 +0100 Subject: [PATCH 29/38] Replace rest of deprecated self.assertRaisesRegexp methods --- tests/test_db.py | 2 +- tests/test_encoding.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_db.py b/tests/test_db.py index 9649d1ec..c4b23d83 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -54,7 +54,7 @@ def test_database_upgrade(self): def test_database_create_drop(self): dbtmp = Db(DATABASEFILE_TMP) Wallet.create("tmpwallet", db_uri=DATABASEFILE_TMP) - self.assertRaisesRegexp(WalletError, "Wallet with name 'tmpwallet' already exists", + self.assertRaisesRegex(WalletError, "Wallet with name 'tmpwallet' already exists", Wallet.create, 'tmpwallet', db_uri=DATABASEFILE_TMP) dbtmp.drop_db(yes_i_am_sure=True) Wallet.create("tmpwallet", db_uri=DATABASEFILE_TMP) diff --git a/tests/test_encoding.py b/tests/test_encoding.py index 642e359e..6a062914 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -113,21 +113,21 @@ def test_change_base_bytes_as_string(self): self.assertEqual('c8e90996c7c6080ee06284600c684ed904d14c5c', change_base(s, 256, 16)) def test_change_base_decimal_input_lenght_exception(self): - self.assertRaisesRegexp(EncodingError, "For a decimal input a minimum output length is required", + self.assertRaisesRegex(EncodingError, "For a decimal input a minimum output length is required", change_base, 100, 10, 2) def test_encoding_exceptions(self): - self.assertRaisesRegexp(EncodingError, "Unknown input format {}", + self.assertRaisesRegex(EncodingError, "Unknown input format {}", change_base, {}, 4, 2) - self.assertRaisesRegexp(EncodingError, "Byteint must be a list or defined as bytes", + self.assertRaisesRegex(EncodingError, "Byteint must be a list or defined as bytes", varbyteint_to_int, 'fd1027') - self.assertRaisesRegexp(EncodingError, "Input must be a number type", + self.assertRaisesRegex(EncodingError, "Input must be a number type", int_to_varbyteint, '1000') - self.assertRaisesRegexp(TypeError, "String value expected", normalize_string, 100) - self.assertRaisesRegexp(EncodingError, "Encoding base32 not supported", pubkeyhash_to_addr, '123', + self.assertRaisesRegex(TypeError, "String value expected", normalize_string, 100) + self.assertRaisesRegex(EncodingError, "Encoding base32 not supported", pubkeyhash_to_addr, '123', encoding='base32') addr = 'qc1qy8qmc6262m68ny0ftlexs4h9paud8sgce3sf84' - self.assertRaisesRegexp(EncodingError, "Invalid bech32 address. Prefix 'qc', prefix expected is 'bc'", + self.assertRaisesRegex(EncodingError, "Invalid bech32 address. Prefix 'qc', prefix expected is 'bc'", addr_bech32_to_pubkeyhash, addr, prefix='bc') @@ -169,7 +169,7 @@ def test_address_base58_zero_prefixes(self): self.assertEqual(change_base('0000003acd8f60b766e48e9db32093b419c21de7e9b35f7e0d', 16, 58), '111GxfgFVyDW3zcFpUF1upSZoL7GCRiLk') self.assertEqual(change_base('1111GxfgFVyDW3zcFpUF1upSZoL7GCRiLk', 58, 256).hex(), '000000003acd8f60b766e48e9db32093b419c21de7e9b35f7e0d') - self.assertRaisesRegexp(EncodingError, "Invalid address hash160 length, should be 25 characters not", + self.assertRaisesRegex(EncodingError, "Invalid address hash160 length, should be 25 characters not", addr_base58_to_pubkeyhash, '1111GxfgFVyDW3zcFpUF1upSZoL7GCRiLk') From a7d4282e4cc4470995f7d9ba4bcc5c5af76dd401 Mon Sep 17 00:00:00 2001 From: Lennart Date: Wed, 20 Dec 2023 17:32:40 +0100 Subject: [PATCH 30/38] Remove outdated database update script --- updatedb.py | 133 ---------------------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 updatedb.py diff --git a/updatedb.py b/updatedb.py deleted file mode 100644 index 929f8988..00000000 --- a/updatedb.py +++ /dev/null @@ -1,133 +0,0 @@ -# -*- coding: utf-8 -*- -# -# BitcoinLib - Python Cryptocurrency Library -# Update database -# © 2017 November - 1200 Web Development -# -# This script creates a database with latest structure and copies only wallets and keys from old database -# Transactions, UTXO's and values are not copied, but can be recreated with utxos_update and transaction_update -# methods of the Wallet class. -# - -import os -import sys -import argparse -from copy import deepcopy -from datetime import datetime -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker -from shutil import move -from bitcoinlib.main import DEFAULT_DATABASE, BCL_DATABASE_DIR, BITCOINLIB_VERSION -from bitcoinlib.db import Base, DbWallet, DbKey, DbKeyMultisigChildren, DbConfig - - -print("Database should update automatically when using BitcoinLib. If automatic update fails you can run this script. " - "!!! After everything is backuped !!!") - -def parse_args(): - parser = argparse.ArgumentParser(description='BitcoinLib Database update script') - parser.add_argument('--database', '-d', default='sqlite:///' + DEFAULT_DATABASE, - help="Name of specific database file to use",) - pa = parser.parse_args() - return pa - - -args = parse_args() -database_file = args.database -if not os.path.isfile(database_file): - database_file = os.path.join(BCL_DATABASE_DIR, database_file) -database_backup_file = os.path.join(BCL_DATABASE_DIR, "%s.backup-%s" % - (database_file, datetime.now().strftime("%Y%m%d-%I:%M"))) - -print("\nWallet and Key data will be copied to new database. Transaction data will NOT be copied") -print("Updating database file: %s" % database_file) -print("Old database will be backed up to %s" % database_backup_file) - -if input("Type 'y' or 'Y' to continue or any other key to cancel: ") not in ['y', 'Y']: - print("Aborted by user") - sys.exit() - - -# Move old database to temporary database -move(database_file, database_backup_file) - -try: - # Create new database - engine = create_engine('sqlite:///%s' % database_file) - Base.metadata.create_all(engine) - - # Copy wallets and keys to new database - Session = sessionmaker(bind=engine) - session = Session() - - engine_backup = create_engine('sqlite:///%s' % database_backup_file) - Session_backup = sessionmaker(bind=engine_backup) - session_backup = Session_backup() - - wallets = session_backup.execute("SELECT * FROM wallets") - for wallet in wallets: - fields = dict(wallet) - - # Update, rename - try: - del(fields['balance']) - except: - pass - if fields['scheme'] == 'bip44': - fields['scheme'] = 'bip32' - elif fields['scheme'] == 'multisig': - fields['scheme'] = 'bip32' - fields['multisig'] = True - - # Remove unused fields - db_field_names = [field[0] for field in DbWallet.__table__.columns.items()] - fields_copy = deepcopy(fields) - for f in fields_copy: - if f not in db_field_names: - del(fields[f]) - - session.add(DbWallet(**fields)) - session.commit() - - keys = session_backup.execute("SELECT * FROM keys") - for key in keys: - fields = dict(key) - - # Update for 'key' field - if 'key' in fields: - if fields['is_private']: - fields['private'] = fields['key'] - else: - fields['public'] = fields['key'] - del(fields['key']) - - # Remove unused fields - db_field_names = [field[0] for field in DbKey.__table__.columns.items()] - fields_copy = deepcopy(fields) - for f in fields_copy: - if f not in db_field_names: - del(fields[f]) - - fields['used'] = False # To force rescan of all keys - session.add(DbKey(**fields)) - session.commit() - - keysubs = session_backup.execute("SELECT * FROM key_multisig_children") - for keysub in keysubs: - fields = dict(keysub) - session.add(DbKeyMultisigChildren(**fields)) - session.commit() - - session.query(DbConfig).filter(DbConfig.variable == 'version').update({DbConfig.value: BITCOINLIB_VERSION}) - session.add(DbConfig(variable='version', value=BITCOINLIB_VERSION)) - session.add(DbConfig(variable='upgrade_date', value=str(datetime.now()))) - session.commit() - - print("Database %s has been updated, backup of old database has been created at %s" % - (database_file, database_backup_file)) - -except Exception as e: - # If ANYTHING goes wrong move back to old database - print(e) - print("Errors occured, database not updated") - move(database_backup_file, database_file) From 245d76f3abaa6833a1eecc7a61ec3cdf13f80f0c Mon Sep 17 00:00:00 2001 From: Lennart Date: Sun, 24 Dec 2023 13:34:08 +0100 Subject: [PATCH 31/38] Add Dockerfiles for unittesting on various Linux systems --- docker/README.rst | 7 +++++++ docker/alpine/Dockerfile | 14 ++++++++++++++ docker/fedora/Dockerfile | 17 +++++++++++++++++ docker/kali/Dockerfile | 21 +++++++++++++++++++++ docker/ubuntu/Dockerfile | 21 +++++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 docker/README.rst create mode 100644 docker/alpine/Dockerfile create mode 100644 docker/fedora/Dockerfile create mode 100644 docker/kali/Dockerfile create mode 100644 docker/ubuntu/Dockerfile diff --git a/docker/README.rst b/docker/README.rst new file mode 100644 index 00000000..06294040 --- /dev/null +++ b/docker/README.rst @@ -0,0 +1,7 @@ +Dockerfiles +=========== + +You can find some basic Dockerfiles here for various system images. + +These are used for testing and are not optimized for size and configuration. If you run the container is will +start all unittests. diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile new file mode 100644 index 00000000..833478d4 --- /dev/null +++ b/docker/alpine/Dockerfile @@ -0,0 +1,14 @@ +FROM alpine:latest +MAINTAINER Cryp Toon + +WORKDIR /code + +RUN apk add --no-cache git python3-dev gmp-dev python3 py3-pip gcc musl-dev libpq-dev +RUN apk add --no-cache postgresql postgresql-contrib mariadb-dev mysql-client + +RUN git clone https://github.com/1200wd/bitcoinlib.git + +WORKDIR /code/bitcoinlib +RUN python3 -m pip install .[dev] --break-system-packages + +CMD python3 -m unittest diff --git a/docker/fedora/Dockerfile b/docker/fedora/Dockerfile new file mode 100644 index 00000000..379c19d1 --- /dev/null +++ b/docker/fedora/Dockerfile @@ -0,0 +1,17 @@ +FROM fedora:latest +MAINTAINER Cryp Toon + +WORKDIR /code + +RUN yum update -y; yum clean all + +RUN yum install -y python3-devel gmp-devel python3-pip git gcc + +RUN yum install -y postgresql postgresql-server mariadb-server libpq-devel mariadb-devel + +RUN git clone https://github.com/1200wd/bitcoinlib.git + +WORKDIR /code/bitcoinlib +RUN python3 -m pip install .[dev] + +CMD python3 -m unittest diff --git a/docker/kali/Dockerfile b/docker/kali/Dockerfile new file mode 100644 index 00000000..a08056d0 --- /dev/null +++ b/docker/kali/Dockerfile @@ -0,0 +1,21 @@ +FROM kalilinux/kali-last-release +MAINTAINER Cryp Toon + +WORKDIR /code + +RUN apt-get update && apt-get upgrade -y +RUN apt-get install -y \ + software-properties-common git \ + build-essential python3-dev libgmp3-dev python3-pip + +#ENV TZ=Europe/Brussels +#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +RUN apt-get install -y postgresql postgresql-contrib default-libmysqlclient-dev default-mysql-server pkg-config libpq-dev +RUN apt-get clean + +RUN git clone https://github.com/1200wd/bitcoinlib.git + +WORKDIR /code/bitcoinlib +RUN python3 -m pip install .[dev] + +CMD python3 -m unittest diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile new file mode 100644 index 00000000..96366893 --- /dev/null +++ b/docker/ubuntu/Dockerfile @@ -0,0 +1,21 @@ +FROM ubuntu:latest +MAINTAINER Cryp Toon + +WORKDIR /code + +RUN apt-get update && apt-get upgrade -y +RUN apt-get install -y \ + software-properties-common git \ + build-essential python3-dev libgmp3-dev python3-pip + +ENV TZ=Europe/Brussels +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +RUN apt-get install -y postgresql postgresql-contrib mariadb-server libpq-dev libmysqlclient-dev pkg-config +RUN apt-get clean + +RUN git clone https://github.com/1200wd/bitcoinlib.git + +WORKDIR /code/bitcoinlib +RUN python3 -m pip install .[dev] + +CMD python3 -m unittest From 1454d578765bfa684491a7d90b42448706c29895 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 15 Jan 2024 09:03:26 +0100 Subject: [PATCH 32/38] Fix error when parsing incorrect spending script witness --- bitcoinlib/transactions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bitcoinlib/transactions.py b/bitcoinlib/transactions.py index 6894e70f..22ce2c4b 100644 --- a/bitcoinlib/transactions.py +++ b/bitcoinlib/transactions.py @@ -1498,7 +1498,9 @@ def parse_bytesio(cls, rawtx, strict=True, network=DEFAULT_NETWORK): inputs[n].script = script if not inputs[n].script else inputs[n].script + script inputs[n].keys = script.keys inputs[n].signatures = script.signatures - if script.script_types[0][:13] == 'p2sh_multisig' or script.script_types[0] =='signature_multisig': + if not script.signatures: + inputs[n].script_type = 'unknown' + elif script.script_types[0][:13] == 'p2sh_multisig' or script.script_types[0] =='signature_multisig': inputs[n].script_type = 'p2sh_multisig' inputs[n].redeemscript = inputs[n].witnesses[-1] elif script.script_types[0] == 'p2tr_unlock': From 717802d5eca1170952c4603b5f44bc100cdf35d0 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 15 Jan 2024 12:55:01 +0100 Subject: [PATCH 33/38] Fix autocorrect error --- bitcoinlib/transactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitcoinlib/transactions.py b/bitcoinlib/transactions.py index 22ce2c4b..ca6c459e 100644 --- a/bitcoinlib/transactions.py +++ b/bitcoinlib/transactions.py @@ -1498,7 +1498,7 @@ def parse_bytesio(cls, rawtx, strict=True, network=DEFAULT_NETWORK): inputs[n].script = script if not inputs[n].script else inputs[n].script + script inputs[n].keys = script.keys inputs[n].signatures = script.signatures - if not script.signatures: + if not script.script_types: inputs[n].script_type = 'unknown' elif script.script_types[0][:13] == 'p2sh_multisig' or script.script_types[0] =='signature_multisig': inputs[n].script_type = 'p2sh_multisig' From fe5f9b60d694cda59ab51544164cc329e2dbdd52 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 15 Jan 2024 14:04:57 +0100 Subject: [PATCH 34/38] Raise more informative error when trying to use unsupported EC multiplied BIP38 key --- bitcoinlib/encoding.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bitcoinlib/encoding.py b/bitcoinlib/encoding.py index 7196fe81..e970610d 100644 --- a/bitcoinlib/encoding.py +++ b/bitcoinlib/encoding.py @@ -962,12 +962,20 @@ def bip38_decrypt(encrypted_privkey, password): :return tupple (bytes, bytes): (Private Key bytes, 4 byte address hash for verification) """ - d = change_base(encrypted_privkey, 58, 256)[2:] - flagbyte = d[0:1] - d = d[1:] + d = change_base(encrypted_privkey, 58, 256) + identifier = d[0:2] + flagbyte = d[2:3] + d = d[3:] + # ec_multiply = False + if identifier == b'\x01\x43': + # ec_multiply = True + raise EncodingError("EC multiply BIP38 keys are not supported at the moment") + elif identifier != b'\x01\x42': + raise EncodingError("Unknown BIP38 identifier, value must be 0x0142 (non-EC-multiplied) or " + "0x0143 (EC-multiplied)") if flagbyte == b'\xc0': compressed = False - elif flagbyte == b'\xe0': + elif flagbyte == b'\xe0' or flagbyte == b'\x20': compressed = True else: raise EncodingError("Unrecognised password protected key format. Flagbyte incorrect.") From 140eaea9f00a0f3ede3814e5e8b77320a89aae67 Mon Sep 17 00:00:00 2001 From: Lennart Date: Mon, 15 Jan 2024 15:41:34 +0100 Subject: [PATCH 35/38] Remove unused exit methods --- README.rst | 1 + bitcoinlib/services/services.py | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/README.rst b/README.rst index ed6c00b6..135ecf54 100644 --- a/README.rst +++ b/README.rst @@ -44,6 +44,7 @@ Then install using pip For more detailed installation instructions, how to install on other systems or troubleshooting please read https://bitcoinlib.readthedocs.io/en/latest/source/_static/manuals.install.html +If you are using docker you can check some Dockerfiles to create images in the docker directory. Documentation ------------- diff --git a/bitcoinlib/services/services.py b/bitcoinlib/services/services.py index 0b7b747b..da952a2e 100644 --- a/bitcoinlib/services/services.py +++ b/bitcoinlib/services/services.py @@ -144,12 +144,6 @@ def __init__(self, network=DEFAULT_NETWORK, min_providers=1, max_providers=1, pr else: self._blockcount = self.blockcount() - def __exit__(self): - try: - self.cache.session.close() - except Exception: - pass - def _reset_results(self): self.results = {} self.errors = {} @@ -694,12 +688,6 @@ def __init__(self, network, db_uri=''): self.session = DbCache(db_uri=db_uri).session self.network = network - def __exit__(self): - try: - self.session.close() - except Exception: - pass - def cache_enabled(self): """ Check if caching is enabled. Returns False if SERVICE_CACHING_ENABLED is False or no session is defined. From 3d92fa09d0e351847ca008ffb1b6f3ede1969922 Mon Sep 17 00:00:00 2001 From: Cryp Toon Date: Mon, 15 Jan 2024 21:26:41 +0100 Subject: [PATCH 36/38] Remove Blocksmurfer providers as API is down --- bitcoinlib/data/providers.json | 22 ---------------------- bitcoinlib/encoding.py | 2 +- bitcoinlib/services/services.py | 2 +- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/bitcoinlib/data/providers.json b/bitcoinlib/data/providers.json index bc2a275c..16a9e036 100644 --- a/bitcoinlib/data/providers.json +++ b/bitcoinlib/data/providers.json @@ -405,27 +405,5 @@ "priority": 10, "denominator": 1, "network_overrides": null - }, - "blocksmurfer": { - "provider": "blocksmurfer", - "network": "bitcoin", - "client_class": "BlocksmurferClient", - "provider_coin_id": "", - "url": "https://harari.blocksmurfer.io/api/v1/btc/", - "api_key": "", - "priority": 10, - "denominator": 100000000, - "network_overrides": null - }, - "blocksmurfer.testnet": { - "provider": "blocksmurfer", - "network": "testnet", - "client_class": "BlocksmurferClient", - "provider_coin_id": "", - "url": "https://harari.blocksmurfer.io/api/v1/tbtc/", - "api_key": "", - "priority": 10, - "denominator": 100000000, - "network_overrides": null } } diff --git a/bitcoinlib/encoding.py b/bitcoinlib/encoding.py index e970610d..8b78e9d1 100644 --- a/bitcoinlib/encoding.py +++ b/bitcoinlib/encoding.py @@ -33,7 +33,7 @@ try: from Crypto.Hash import RIPEMD160 except ImportError as err: - _logger.warning("Could not import RIPEMD160 from cryptodome, will try do use hashlib but this could lead to errors") + _logger.warning("Could not import RIPEMD160 from cryptodome, will try to use hashlib but this could lead to errors") try: from Crypto.Cipher import AES diff --git a/bitcoinlib/services/services.py b/bitcoinlib/services/services.py index da952a2e..b032dbf3 100644 --- a/bitcoinlib/services/services.py +++ b/bitcoinlib/services/services.py @@ -25,7 +25,7 @@ from sqlalchemy import func from bitcoinlib import services from bitcoinlib.networks import Network -from bitcoinlib.encoding import to_bytes, int_to_varbyteint, varstr, varbyteint_to_int +from bitcoinlib.encoding import to_bytes, int_to_varbyteint, varstr from bitcoinlib.db_cache import * from bitcoinlib.transactions import Transaction, transaction_update_spents from bitcoinlib.blocks import Block From 839b99c0fa86dae7c3a05a725ed5b404353441a8 Mon Sep 17 00:00:00 2001 From: Cryp Toon Date: Mon, 15 Jan 2024 22:05:16 +0100 Subject: [PATCH 37/38] RELEASE 0.6.14 - UPDATE INSTALLATION INSTRUCTIONS, DOCKER & BUGFIXES --- CHANGELOG | 8 ++++++++ bitcoinlib/config/VERSION | 2 +- bitcoinlib/wallets.py | 1 - docs/conf.py | 8 ++++---- setup.cfg | 2 +- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e591bcfa..4f58d87f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +RELEASE 0.6.14 - Update installation instruction, docker & bugfixes +=================================================================== +* Update installation instructions +* Add Docker files for testing and installation testing +* Fix Bitcoind constructors +* Fix issue with hexadecimal passwords for Mnemonics +* Fix regtest address prefix + RELEASE 0.6.13 - Update config & fix some bugs ============================================== * Rewrite configuration files for easier installation diff --git a/bitcoinlib/config/VERSION b/bitcoinlib/config/VERSION index 4655c9e9..5c858bde 100644 --- a/bitcoinlib/config/VERSION +++ b/bitcoinlib/config/VERSION @@ -1 +1 @@ -0.6.13 \ No newline at end of file +0.6.14 \ No newline at end of file diff --git a/bitcoinlib/wallets.py b/bitcoinlib/wallets.py index 23c43ec6..f83d5a53 100644 --- a/bitcoinlib/wallets.py +++ b/bitcoinlib/wallets.py @@ -56,7 +56,6 @@ def wallets_list(db_uri=None, include_cosigners=False, db_password=None): :param db_uri: URI of the database :type db_uri: str - :param include_cosigners: Child wallets for multisig wallets are for internal use only and are skipped by default :type include_cosigners: bool :param db_password: Password to use for encrypted database. Requires the installation of sqlcipher (see diff --git a/docs/conf.py b/docs/conf.py index 21182508..776715e6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,8 +35,8 @@ # General information about the project. project = 'Bitcoinlib' -copyright = '2023, Coineva (mccwdev)' -author = 'Lennart (mccwdev)' +copyright = '2017-2024, Coineva (mccwdev)' +author = 'Cryp Toon (mccwdev)' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -45,7 +45,7 @@ # The short X.Y version. version = '0.6' # The full version, including alpha/beta/rc tags. -release = '0.6.13' +release = '0.6.14' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -115,7 +115,7 @@ # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'Bitcoinlib.tex', 'Bitcoinlib Documentation', - 'Lennart (mccwdev)', 'manual'), + 'Cryp Toon (mccwdev)', 'manual'), ] diff --git a/setup.cfg b/setup.cfg index 4681f4b3..0bf33236 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = bitcoinlib -version = 0.6.13 +version = 0.6.14 url = http://github.com/1200wd/bitcoinlib author = 1200wd author_email = info@1200wd.com From 51cc152a746126658275eccbe77241389ddab95b Mon Sep 17 00:00:00 2001 From: Cryp Toon Date: Tue, 16 Jan 2024 20:10:06 +0100 Subject: [PATCH 38/38] Try to fix documentation build --- .readthedocs.yml | 6 +++--- docs/requirements.txt | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 358b81bb..f909144d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,11 +9,11 @@ version: 2 formats: all build: - image: latest + os: ubuntu-22.04 + tools: + python: "3.11" # Optionally set the version of Python and requirements required to build your docs python: - version: 3.10 install: - requirements: docs/requirements.txt -# - requirements: requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt index 2932366a..fc6b1bc9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ requests>=2.25.0 -SQLAlchemy>=1.4.28 -ecdsa>=0.17 -sphinx>=5.0.0 -sphinx_rtd_theme>=0.5.0 -numpy>=1.21.0 +SQLAlchemy>=2.0.0 +fastecdsa>=2.2.1 +sphinx>=6.0.0 +sphinx_rtd_theme>=1.0.0 +numpy>=1.22.0 pycryptodome>=3.14.1