diff --git a/__init__.py b/__init__.py index f92c631..770769c 100644 --- a/__init__.py +++ b/__init__.py @@ -2,18 +2,18 @@ # # Copyright (c) 2022 Opentensor Foundation -# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -# documentation files (the “Software”), to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the “Software”), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all copies or substantial portions of +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of # the Software. # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. __version__ = "1.1.2" diff --git a/pyproject.toml b/pyproject.toml index 59e75bb..badfd74 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ # pyproject.toml [build-system] -requires = ["setuptools>=59.0.0", "wheel==0.37.1", "Cython>=0.29.33", "numpy==1.21.6" ] +requires = ["setuptools>=70.0.0", "wheel", "Cython>=0.29.33", "numpy>=1.21.6" ] build-backend = "setuptools.build_meta" [project] name = "cubit" -version = "1.2.0" +version = "1.2.1" description = "A python package for CUDA registration on bittensor. " readme = "README.md" authors = [{ name = "Opentensor Foundation", email = "cameron@opentensor.ai" }] @@ -18,12 +18,12 @@ classifiers = [ ] keywords = ["bittensor", "cuda", "register", "cubit"] dependencies = [ - "setuptools>=59.0.0", "wheel==0.37.1", "Cython>=0.29.33", "numpy==1.21.6" + "setuptools>=70.0.0", "wheel", "Cython>=0.29.33", "numpy>=1.21.6", "torch>=1.13.1,<3.0" ] requires-python = ">=3.8" [project.optional-dependencies] -test = ["black", "pip-tools", "bittensor>=3.0.0", "pycryptodome==3.4.3" ] +test = ["ruff", "pip-tools", "bittensor>=9.0.0", "pycryptodome==3.4.3" ] [project.urls] Homepage = "https://github.com/opentensor/cubit" diff --git a/setup.py b/setup.py index 9b37420..f4660da 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE @@ -28,6 +28,7 @@ from Cython.Build import cythonize import numpy + def find_in_path(name, path): """Find a file in a search path""" @@ -50,25 +51,31 @@ def locate_cuda(): """ # First check if the CUDAHOME env variable is in use - if 'CUDA_HOME' in os.environ: - home = os.environ['CUDA_HOME'] - nvcc = pjoin(home, 'bin', 'nvcc') + if "CUDA_HOME" in os.environ: + home = os.environ["CUDA_HOME"] + nvcc = pjoin(home, "bin", "nvcc") else: # Otherwise, search the PATH for NVCC - nvcc = find_in_path('nvcc', os.environ['PATH']) + nvcc = find_in_path("nvcc", os.environ["PATH"]) if nvcc is None: - raise EnvironmentError('The nvcc binary could not be ' - 'located in your $PATH. Either add it to your path, ' - 'or set $CUDA_HOME') + raise EnvironmentError( + "The nvcc binary could not be " + "located in your $PATH. Either add it to your path, " + "or set $CUDA_HOME" + ) home = os.path.dirname(os.path.dirname(nvcc)) - cudaconfig = {'home': home, 'nvcc': nvcc, - 'include': pjoin(home, 'include'), - 'lib64': pjoin(home, 'lib64')} + cudaconfig = { + "home": home, + "nvcc": nvcc, + "include": pjoin(home, "include"), + "lib64": pjoin(home, "lib64"), + } for k, v in iter(cudaconfig.items()): if not os.path.exists(v): - raise EnvironmentError('The CUDA %s path could not be ' - 'located in %s' % (k, v)) + raise EnvironmentError( + "The CUDA %s path could not be located in %s" % (k, v) + ) return cudaconfig @@ -85,7 +92,7 @@ def customize_compiler_for_nvcc(self): """ # Tell the compiler it can processes .cu and files - self.src_extensions.append('.cu') + self.src_extensions.append(".cu") # Save references to the default compiler_so and _comple methods default_compiler_so = self.compiler_so @@ -95,14 +102,14 @@ def customize_compiler_for_nvcc(self): # object but distutils doesn't have the ability to change compilers # based on source extension: we add it. def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): - if os.path.splitext(src)[1] == '.cu': + if os.path.splitext(src)[1] == ".cu": # use the cuda for .cu files - self.set_executable('compiler_so', CUDA['nvcc']) + self.set_executable("compiler_so", CUDA["nvcc"]) # use only a subset of the extra_postargs, which are 1-1 # translated from the extra_compile_args in the Extension class - postargs = extra_postargs['nvcc'] + postargs = extra_postargs["nvcc"] else: - postargs = extra_postargs['gcc'] + postargs = extra_postargs["gcc"] super(obj, src, ext, cc_args, postargs, pp_opts) # Reset the default compiler_so, which we might have changed for cuda @@ -112,7 +119,6 @@ def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): self._compile = _compile - # Run the customize_compiler class custom_build_ext(build_ext): def build_extensions(self): @@ -120,7 +126,6 @@ def build_extensions(self): build_ext.build_extensions(self) - CUDA = locate_cuda() # Obtain the numpy include directory. This logic works across numpy versions. @@ -129,44 +134,50 @@ def build_extensions(self): except AttributeError: numpy_include = numpy.get_numpy_include() -ext = Extension('cubit', - sources = ['kernels/main.cu', 'cubit.pyx'], - library_dirs=[CUDA['lib64']], - libraries=['cudart'], - language='c++', - runtime_library_dirs=[CUDA['lib64']], - extra_compile_args={ - 'gcc': [], - 'nvcc': ['-Xptxas', '-v', '-O3', - - '-gencode', 'arch=compute_86,code=sm_86', - '-gencode', 'arch=compute_80,code=sm_80', - '-gencode', 'arch=compute_75,code=sm_75', - '-gencode', 'arch=compute_70,code=sm_70', - '-gencode', 'arch=compute_61,code=sm_61', - - '--ptxas-options=-v', '-c', - '--compiler-options', "'-fPIC'" - ] - }, - include_dirs = [numpy_include, CUDA['include']]) - +ext = Extension( + "cubit", + sources=["kernels/main.cu", "cubit.pyx"], + library_dirs=[CUDA["lib64"]], + libraries=["cudart"], + language="c++", + runtime_library_dirs=[CUDA["lib64"]], + extra_compile_args={ + "gcc": [], + "nvcc": [ + "-Xptxas", + "-v", + "-O3", + "-gencode", + "arch=compute_86,code=sm_86", + "-gencode", + "arch=compute_80,code=sm_80", + "-gencode", + "arch=compute_75,code=sm_75", + "-gencode", + "arch=compute_70,code=sm_70", + "-gencode", + "arch=compute_61,code=sm_61", + "--ptxas-options=-v", + "-c", + "--compiler-options", + "'-fPIC'", + ], + }, + include_dirs=[numpy_include, CUDA["include"]], +) setup( - name = 'cubit', + name="cubit", # Random metadata. there's more you can supply - author = 'Opentensor Foundation', - author_email = 'cameron@opentensor.ai', - url = 'https://github.com/opentensor/cubit', - version = '1.2.1', - - ext_modules = cythonize(ext), - + author="Opentensor Foundation", + author_email="cameron@opentensor.ai", + url="https://github.com/opentensor/cubit", + version="1.2.1", + ext_modules=cythonize(ext), # Inject our custom trigger - cmdclass = {'build_ext': custom_build_ext}, - + cmdclass={"build_ext": custom_build_ext}, # Since the package has c code, the egg cannot be zipped - zip_safe = False, + zip_safe=False, packages=find_packages(), ) diff --git a/test.py b/test.py index 8c124d0..6cd8f00 100644 --- a/test.py +++ b/test.py @@ -3,18 +3,18 @@ # Copyright (c) 2022 Cameron Fairchild # Copyright (c) 2022 Opentensor Foundation -# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -# documentation files (the “Software”), to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +# documentation files (the “Software”), to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all copies or substantial portions of +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of # the Software. # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. import binascii @@ -29,16 +29,21 @@ import torch from Crypto.Hash import keccak -from cubit import (reset_cuda, run_test, - run_test_create_nonce_bytes, - run_test_create_pre_seal, run_test_keccak, - run_test_less_than, run_test_preseal_hash, - run_test_seal_hash, - run_test_seal_meets_difficulty, - solve_cuda) - - -class TestCli( unittest.TestCase ): +from cubit import ( + reset_cuda, + run_test, + run_test_create_nonce_bytes, + run_test_create_pre_seal, + run_test_keccak, + run_test_less_than, + run_test_preseal_hash, + run_test_seal_hash, + run_test_seal_meets_difficulty, + solve_cuda, +) + + +class TestCli(unittest.TestCase): st: bt.Subtensor bn: int bh: str @@ -49,174 +54,192 @@ class TestCli( unittest.TestCase ): block_bytes: bytes dev_id: int - def setUp( self ) -> None: + def setUp(self) -> None: if not torch.cuda.is_available(): print("No GPU available") self.fail("No GPU available") - self.dev_id = 5 # By default, use the first GPU + self.dev_id = 5 # By default, use the first GPU self.st = bt.subtensor(network="finney") self.bn = self.st.get_current_block() self.bh = self.st.substrate.get_block_hash(self.bn) - self.difficulty = 1_000_000_000 #st.difficulty - self.limit = int(math.pow(2,256)) - 1 + self.difficulty = 1_000_000_000 # st.difficulty + self.limit = int(math.pow(2, 256)) - 1 self.upper = int(self.limit // self.difficulty) - 1 - self.upper_bytes = self.upper.to_bytes(32, byteorder='little', signed=False) - self.block_bytes = self.bh.encode('utf-8')[2:] + self.upper_bytes = self.upper.to_bytes(32, byteorder="little", signed=False) + self.block_bytes = self.bh.encode("utf-8")[2:] def tearDown(self) -> None: - reset_cuda() # Reset the CUDA device + reset_cuda() # Reset the CUDA device @staticmethod - def hex_bytes_to_u8_list( hex_bytes:bytes ) -> List[int]: - hex_chunks = [int(hex_bytes[i:i+2], 16) for i in range(0, len(hex_bytes), 2)] + def hex_bytes_to_u8_list(hex_bytes: bytes) -> List[int]: + hex_chunks = [ + int(hex_bytes[i : i + 2], 16) for i in range(0, len(hex_bytes), 2) + ] return hex_chunks @staticmethod - def seal_meets_difficulty( seal:bytes, difficulty:int ) -> bool: + def seal_meets_difficulty(seal: bytes, difficulty: int) -> bool: seal_number = int.from_bytes(seal, "big") product = seal_number * difficulty - limit = int(math.pow(2,256))- 1 + limit = int(math.pow(2, 256)) - 1 return product <= limit @staticmethod - def get_nonce_bytes( nonce:int ) -> bytes: - nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little')) + def get_nonce_bytes(nonce: int) -> bytes: + nonce_bytes = binascii.hexlify(nonce.to_bytes(8, "little")) return nonce_bytes # Test sha256 implementation vs hashlib - def test_sha_implementation( self ) -> None: + def test_sha_implementation(self) -> None: print(self._testMethodName) - test_input = bytes("test", 'utf-8') + test_input = bytes("test", "utf-8") test_hash = run_test(test_input, len(test_input)) - compare_hash = hashlib.sha256( test_input ).digest() + compare_hash = hashlib.sha256(test_input).digest() self.assertEqual(test_hash, compare_hash) - - def test_keccak_implementation ( self ) -> None: + + def test_keccak_implementation(self) -> None: print(self._testMethodName) - test_input = bytes("test", 'utf-8') + test_input = bytes("test", "utf-8") test_hash = run_test_keccak(test_input, len(test_input)) kec = keccak.new(digest_bits=256) - compare_hash = kec.update( test_input ).digest() + compare_hash = kec.update(test_input).digest() self.assertEqual(test_hash, compare_hash) # Test hash of formed preseal - def test_preseal_hash( self ) -> None: + def test_preseal_hash(self) -> None: print(self._testMethodName) nonce = 0 nonce_bytes = self.get_nonce_bytes(nonce) pre_seal = nonce_bytes + self.block_bytes seal = run_test_preseal_hash(bytearray(self.hex_bytes_to_u8_list(pre_seal))) - - seal_sh256 = hashlib.sha256( bytearray(self.hex_bytes_to_u8_list(pre_seal)) ).digest() + + seal_sh256 = hashlib.sha256( + bytearray(self.hex_bytes_to_u8_list(pre_seal)) + ).digest() kec = keccak.new(digest_bits=256) - seal_2 = kec.update( seal_sh256 ).digest() + seal_2 = kec.update(seal_sh256).digest() self.assertEqual(seal, seal_2) - + # Test create nonce bytes from nonce - def test_create_nonce_bytes( self ) -> bytes: + def test_create_nonce_bytes(self) -> bytes: print(self._testMethodName) - nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63)-1)) + nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63) - 1)) nonce_bytes: bytes = run_test_create_nonce_bytes(nonce, self.dev_id) nonce_bytes_2 = self.get_nonce_bytes(nonce) # Unhexlify to compare nonce_bytes_2 = binascii.unhexlify(nonce_bytes_2) self.assertEqual(nonce_bytes, nonce_bytes_2) - + # Test create pre seal - def test_create_pre_seal( self ) -> bytes: + def test_create_pre_seal(self) -> bytes: print(self._testMethodName) - nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63)-1)) + nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63) - 1)) pre_seal = run_test_create_pre_seal(nonce, self.block_bytes, self.dev_id) nonce_bytes = self.get_nonce_bytes(nonce) - pre_seal_2 = bytearray(self.hex_bytes_to_u8_list(nonce_bytes + self.block_bytes)) + pre_seal_2 = bytearray( + self.hex_bytes_to_u8_list(nonce_bytes + self.block_bytes) + ) self.assertEqual(pre_seal, pre_seal_2) # Test create pre seal - def test_create_new_pre_seal( self ) -> bytes: + def test_create_new_pre_seal(self) -> bytes: print(self._testMethodName) - nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63)-1)) + nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63) - 1)) kec = keccak.new(digest_bits=512) - block_and_hotkey_hash_bytes = kec.update( self.block_bytes ).digest() + block_and_hotkey_hash_bytes = kec.update(self.block_bytes).digest() block_and_hotkey_hash_hex = binascii.hexlify(block_and_hotkey_hash_bytes)[:64] - pre_seal = run_test_create_pre_seal(nonce, block_and_hotkey_hash_hex, self.dev_id) + pre_seal = run_test_create_pre_seal( + nonce, block_and_hotkey_hash_hex, self.dev_id + ) nonce_bytes = self.get_nonce_bytes(nonce) - pre_seal_2 = bytearray(self.hex_bytes_to_u8_list(nonce_bytes + block_and_hotkey_hash_hex)) + pre_seal_2 = bytearray( + self.hex_bytes_to_u8_list(nonce_bytes + block_and_hotkey_hash_hex) + ) self.assertEqual(pre_seal, pre_seal_2) - def test_new_seal_hash( self ) -> None: - nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63)-1)) + def test_new_seal_hash(self) -> None: + nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63) - 1)) kec = keccak.new(digest_bits=512) - block_and_hotkey_hash_bytes = kec.update( self.block_bytes ).digest() + block_and_hotkey_hash_bytes = kec.update(self.block_bytes).digest() block_and_hotkey_hash_hex = binascii.hexlify(block_and_hotkey_hash_bytes)[:64] seal = run_test_seal_hash(block_and_hotkey_hash_hex, nonce, self.dev_id) - nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little')) + nonce_bytes = binascii.hexlify(nonce.to_bytes(8, "little")) pre_seal = nonce_bytes + block_and_hotkey_hash_hex - seal_sh256 = hashlib.sha256( bytearray(self.hex_bytes_to_u8_list(pre_seal)) ).digest() + seal_sh256 = hashlib.sha256( + bytearray(self.hex_bytes_to_u8_list(pre_seal)) + ).digest() kec = keccak.new(digest_bits=256) - seal_2 = kec.update( seal_sh256 ).digest() + seal_2 = kec.update(seal_sh256).digest() self.assertEqual(seal, seal_2) - + # Test block and nonce hash - def test_seal_hash( self ) -> None: + def test_seal_hash(self) -> None: print(self._testMethodName) - nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63)-1)) + nonce = random.randint(int(math.pow(2, 45)), int(math.pow(2, 63) - 1)) seal = run_test_seal_hash(self.block_bytes, nonce, self.dev_id) nonce_bytes = self.get_nonce_bytes(nonce) pre_seal = nonce_bytes + self.block_bytes - seal_sh256 = hashlib.sha256( bytearray(self.hex_bytes_to_u8_list(pre_seal)) ).digest() + seal_sh256 = hashlib.sha256( + bytearray(self.hex_bytes_to_u8_list(pre_seal)) + ).digest() kec = keccak.new(digest_bits=256) - seal_2 = kec.update( seal_sh256 ).digest() + seal_2 = kec.update(seal_sh256).digest() self.assertEqual(seal, seal_2) - + # Test less than - def test_less_than( self ) -> None: + def test_less_than(self) -> None: print(self._testMethodName) for _ in range(0, 100): a = random.randint(0, 20000000000000000000000) b = random.randint(0, 20000000000000000000000) - a_ = a.to_bytes(32, byteorder='little', signed=False) - b_ = b.to_bytes(32, byteorder='little', signed=False) + a_ = a.to_bytes(32, byteorder="little", signed=False) + b_ = b.to_bytes(32, byteorder="little", signed=False) result = run_test_less_than(a_, b_) - self.assertEqual(a < b, result == -1, f"{a} is{' not' if (a >= b) else ''} less than {b}") # 0 means a < b + self.assertEqual( + a < b, result == -1, f"{a} is{' not' if (a >= b) else ''} less than {b}" + ) # 0 means a < b # Test seal meets difficulty - def test_seal_meets_difficulty( self ) -> None: + def test_seal_meets_difficulty(self) -> None: print(self._testMethodName) difficulty = 48 * 10**9 upper = int(self.limit // difficulty) - upper_bytes = upper.to_bytes(32, byteorder='little', signed=False) + upper_bytes = upper.to_bytes(32, byteorder="little", signed=False) nonce = 0 nonce_bytes = self.get_nonce_bytes(nonce) pre_seal = nonce_bytes + self.block_bytes - seal_sh256 = hashlib.sha256( bytearray(self.hex_bytes_to_u8_list(pre_seal)) ).digest() + seal_sh256 = hashlib.sha256( + bytearray(self.hex_bytes_to_u8_list(pre_seal)) + ).digest() kec = keccak.new(digest_bits=256) - seal = kec.update( seal_sh256 ).digest() + seal = kec.update(seal_sh256).digest() result = run_test_seal_meets_difficulty(seal, upper_bytes) result_2 = self.seal_meets_difficulty(seal, difficulty) self.assertEqual(result, result_2) - + # Test a solve - def test_solve( self ) -> None: + def test_solve(self) -> None: print(self._testMethodName) solution = -1 interval = 30_000 @@ -226,7 +249,14 @@ def test_solve( self ) -> None: while solution == -1: # int blockSize, uint64 nonce_start, uint64 update_interval, const unsigned char[:] limit, # const unsigned char[:] block_bytes - solution = solve_cuda(TPB, start_nonce, interval, self.upper_bytes, self.block_bytes, self.dev_id) + solution = solve_cuda( + TPB, + start_nonce, + interval, + self.upper_bytes, + self.block_bytes, + self.dev_id, + ) start_nonce += interval * TPB self.assertNotEqual(solution, -1) @@ -234,16 +264,23 @@ def test_solve( self ) -> None: time_diff = time_end - time_start print(f"Solve took: {time_diff.total_seconds()} seconds") - - seal_sh256 = hashlib.sha256( bytearray(self.hex_bytes_to_u8_list(self.get_nonce_bytes(solution) + self.block_bytes)) ).digest() + + seal_sh256 = hashlib.sha256( + bytearray( + self.hex_bytes_to_u8_list( + self.get_nonce_bytes(solution) + self.block_bytes + ) + ) + ).digest() kec = keccak.new(digest_bits=256) - seal = kec.update( seal_sh256 ).digest() + seal = kec.update(seal_sh256).digest() seal_number = int.from_bytes(seal, "big") - limit = int(math.pow(2,256)) - 1 + limit = int(math.pow(2, 256)) - 1 product = seal_number * self.difficulty self.assertTrue( - product < limit, # self.seal_meets_difficulty(seal, self.difficulty) - f"solution: {solution} with seal: 0x{seal.hex()} for block_num: {self.bn} \ndoes not meet difficulty {self.difficulty} for block hash: {self.bh}" + product < limit, # self.seal_meets_difficulty(seal, self.difficulty) + f"solution: {solution} with seal: 0x{seal.hex()} for block_num: {self.bn} \ndoes not meet difficulty" + f" {self.difficulty} for block hash: {self.bh}", )