# distutils: language = c++ """placeholder module for compilation""" from __future__ import annotations import datetime import hashlib import struct import time import cython import dopt_basics.datetime # from cython.cimports.cpython.ref import Py_INCREF, PyObject from polluck_blockchain.block cimport Block from libcpp.unordered_map cimport unordered_map from libcpp.string cimport string ctypedef unsigned long ULong # cdef struct PyStringC: # char* ptr # Py_ssize_t length # cdef PyStringC_to_unicode(PyStringC string): # return string.ptr[: string.length].decode("UTF-8", "strict") # cdef PyStringC_to_bytes(PyStringC string): # return string.ptr[: string.length] cdef timestamp_to_datetime(double ts): return datetime.datetime.fromtimestamp(ts, dopt_basics.datetime.TIMEZONE_UTC) # cdef class StringHolder: # cdef readonly PyStringC c # cdef object _py_data # def __cinit__(self, data: str): # """accepting Python str # Parameters # ---------- # data : str # _description_ # """ # if not isinstance(data, str): # raise TypeError("Data not 'str'") # self._py_data = data.encode("UTF-8") # self.c = PyStringC(self._py_data, len(self._py_data)) # @property # def py_string(self): # return PyStringC_to_unicode(self.c) # @property # def py_bytes(self): # return PyStringC_to_bytes(self.c) # BlockC = cython.struct( # index=cython.ulonglong, # timestamp=cython.double, # data=PyStringC, # previous_hash=PyStringC, # nonce=cython.ulonglong, # ) cdef float_to_bytes(double num): return struct.pack(">d", num) # cdef struct BlockC: # ULong _index # double _timestamp # string _data # string _prev_hash # ULong _nonce # string _hash cdef class BlockPy: cdef: ULong _index double _timestamp string _data string _prev_hash ULong _nonce string _hash Block* Block def __cinit__(self, index: int, data: str, previous_hash: str, nonce: int, ): self.Block = new Block( index, datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp(), nonce, data.encode("UTF-8"), previous_hash.encode("UTF-8"), "".encode("UTF-8"), ) def get_data(self): return self.Block.data.decode("UTF-8") # def __init__( # self, # index: int, # data: str, # previous_hash: str, # nonce: int, # ): # self.C = new BlockC( # index, # datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp(), # data.encode("UTF-8"), # previous_hash.encode("UTF-8"), # nonce, # "".encode("UTF-8"), # ) # self._index = index # # self._timestamp = dopt_basics.datetime.current_time_tz().timestamp() # self._timestamp = datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp() # self._data = data.encode("UTF-8") # self._prev_hash = previous_hash.encode("UTF-8") # self._nonce = nonce # self._hash = "".encode("UTF-8") # cpdef _perform_hash(self): # parts = bytearray() # parts.extend(self._index.to_bytes(8, "big")) # parts.extend(float_to_bytes(self._timestamp)) # parts.extend(self._data) # parts.extend(self._prev_hash) # parts.extend(self._nonce.to_bytes(8, "big")) # return hashlib.sha256(parts) # def compute_hash_bytes(self): # return self._perform_hash().digest() # def compute_hash(self): # return self._perform_hash().hexdigest() # # Python public API # @property # def index(self): # return self._index # @property # def timestamp(self): # return timestamp_to_datetime(self._timestamp) # @property # def data(self): # return self._data.decode("UTF-8") # @property # def prev_hash(self): # return self._prev_hash.decode("UTF-8") # @property # def nonce(self): # return self._nonce # @nonce.setter # def nonce(self, value: int): # self._nonce = value # @property # def hash(self): # return self._hash.decode("UTF-8") # @hash.setter # def hash(self, value: str): # if not isinstance(value, str): # raise TypeError("No string") # self._hash = value.encode("UTF-8") # cdef class Blockchain: # cdef int _difficulty # cdef size_t _index # cdef unordered_map[size_t, int] _chain # def __cinit__(self): # self._difficulty = 1 # self._index = 0 # # self._chain = new unordered_map[size_t, Block]() # def __init__( # self, # difficulty: int = 1, # ) -> None: # self._difficulty = difficulty # @property # def index(self): # return self._index # @property # def difficulty(self): # return self._difficulty # cdef create_genesis_block(self): # genesis = Block( # index=0, # data="Genesis Block", # previous_hash="0", # nonce=0, # ) # genesis.hash = genesis.compute_hash() # self.chain[self._index] = genesis # cdef proof_of_work(self, block: Block): # prefix = "0" * self._difficulty # while True: # block_hash = block.compute_hash() # if block_hash.startswith(prefix): # return block_hash # block._nonce += 1 # cdef add_block(self, data: str): # prev_hash = self.chain[self._index].hash # new_block = Block( # index=(self._index + 1), # data=data, # previous_hash=prev_hash, # nonce=0, # ) # # start = time.perf_counter() # new_block.hash = self.proof_of_work(new_block) # # elapsed = time.perf_counter() - start # self.chain.append(new_block) # self._index += 1 # print(f"Mined block {new_block.index} with nonce={new_block.nonce}") # # print(f"Mined block {new_block.index} in {elapsed:.3f}s with nonce={new_block.nonce}") # return new_block