generated from dopt-python/py311-cython
more core implementation in Cython
This commit is contained in:
parent
d3d5d04ef2
commit
68356e06a5
File diff suppressed because it is too large
Load Diff
@ -16,92 +16,40 @@ import dopt_basics.datetime
|
||||
from polluck_blockchain.block cimport Block
|
||||
from libcpp.unordered_map cimport unordered_map
|
||||
from libcpp.string cimport string
|
||||
from libc.stdint cimport uint64_t
|
||||
|
||||
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 <bytes>string.ptr[: string.length]
|
||||
|
||||
|
||||
ctypedef unordered_map[uint64_t, Block*] BcHashmap
|
||||
|
||||
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 class PyBlock:
|
||||
cdef:
|
||||
ULong _index
|
||||
double _timestamp
|
||||
string _data
|
||||
string _prev_hash
|
||||
ULong _nonce
|
||||
string _hash
|
||||
Block* Block
|
||||
# ULong _index
|
||||
# double _timestamp
|
||||
# string _data
|
||||
# string _prev_hash
|
||||
# ULong _nonce
|
||||
# string _hash
|
||||
Block *BlockC
|
||||
bint ptr_owner
|
||||
|
||||
def __cinit__(self,
|
||||
index: int,
|
||||
data: str,
|
||||
previous_hash: str,
|
||||
nonce: int,
|
||||
index,
|
||||
nonce,
|
||||
data,
|
||||
previous_hash,
|
||||
from_ptr=False,
|
||||
):
|
||||
self.Block = new Block(
|
||||
self.ptr_owner = False
|
||||
if not from_ptr:
|
||||
self.BlockC = new Block(
|
||||
index,
|
||||
datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp(),
|
||||
nonce,
|
||||
@ -109,25 +57,13 @@ cdef class BlockPy:
|
||||
previous_hash.encode("UTF-8"),
|
||||
"".encode("UTF-8"),
|
||||
)
|
||||
if self.BlockC == NULL:
|
||||
raise MemoryError("Allocation of block object failed")
|
||||
|
||||
def get_data(self):
|
||||
return self.Block.data.decode("UTF-8")
|
||||
self.ptr_owner = True
|
||||
|
||||
# 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"),
|
||||
# )
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
# self._index = index
|
||||
# # self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
|
||||
# self._timestamp = datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()
|
||||
@ -136,6 +72,26 @@ cdef class BlockPy:
|
||||
# self._nonce = nonce
|
||||
# self._hash = "".encode("UTF-8")
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.BlockC is not NULL and self.ptr_owner is True:
|
||||
del self.BlockC
|
||||
self.BlockC = NULL
|
||||
|
||||
@staticmethod
|
||||
cdef PyBlock from_ptr(Block *block, bint owner=False):
|
||||
cdef PyBlock py_block = PyBlock.__new__(
|
||||
PyBlock,
|
||||
block.index,
|
||||
block.nonce,
|
||||
block.data,
|
||||
block.prev_hash,
|
||||
True,
|
||||
)
|
||||
py_block.BlockC = block
|
||||
py_block.ptr_owner = owner
|
||||
|
||||
return py_block
|
||||
|
||||
# cpdef _perform_hash(self):
|
||||
# parts = bytearray()
|
||||
# parts.extend(self._index.to_bytes(8, "big"))
|
||||
@ -152,51 +108,124 @@ cdef class BlockPy:
|
||||
# def compute_hash(self):
|
||||
# return self._perform_hash().hexdigest()
|
||||
|
||||
# # Python public API
|
||||
# @property
|
||||
# def index(self):
|
||||
# return self._index
|
||||
# Python public API
|
||||
@property
|
||||
def index(self):
|
||||
return self.BlockC.index
|
||||
|
||||
# @property
|
||||
# def timestamp(self):
|
||||
# return timestamp_to_datetime(self._timestamp)
|
||||
@property
|
||||
def timestamp(self):
|
||||
return timestamp_to_datetime(self.BlockC.timestamp)
|
||||
|
||||
# @property
|
||||
# def data(self):
|
||||
# return self._data.decode("UTF-8")
|
||||
@property
|
||||
def data(self):
|
||||
return self.BlockC.data.decode("UTF-8")
|
||||
|
||||
# @property
|
||||
# def prev_hash(self):
|
||||
# return self._prev_hash.decode("UTF-8")
|
||||
@property
|
||||
def prev_hash(self):
|
||||
return self.BlockC.prev_hash.decode("UTF-8")
|
||||
|
||||
# @property
|
||||
# def nonce(self):
|
||||
# return self._nonce
|
||||
@property
|
||||
def nonce(self):
|
||||
return self.BlockC.nonce
|
||||
|
||||
# @nonce.setter
|
||||
# def nonce(self, value: int):
|
||||
# self._nonce = value
|
||||
|
||||
# @property
|
||||
# def hash(self):
|
||||
# return self._hash.decode("UTF-8")
|
||||
@property
|
||||
def hash(self):
|
||||
return self.BlockC.hash.decode("UTF-8")
|
||||
|
||||
# @hash.setter
|
||||
# def hash(self, value: str):
|
||||
# def hash(self, value):
|
||||
# if not isinstance(value, str):
|
||||
# raise TypeError("No string")
|
||||
# self._hash = value.encode("UTF-8")
|
||||
|
||||
# cdef void add_block(BcHashmap *map, Block *block):
|
||||
# map[block.index] = block
|
||||
|
||||
# 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 = <size_t>0
|
||||
# # self._chain = new unordered_map[size_t, Block]()
|
||||
cdef class Blockchain:
|
||||
cdef int _difficulty
|
||||
cdef uint64_t _index
|
||||
cdef BcHashmap *_chain
|
||||
cdef bint _genesis_done
|
||||
|
||||
def __cinit__(self):
|
||||
self._difficulty = 1
|
||||
self._index = <uint64_t>0
|
||||
self._genesis_done = <bint>0
|
||||
self._chain = new unordered_map[uint64_t, Block*]()
|
||||
if self._chain is NULL:
|
||||
raise MemoryError("Could not allocate hasmap")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __dealloc__(self):
|
||||
if self._chain is not NULL:
|
||||
del self._chain
|
||||
self._chain = NULL
|
||||
|
||||
def __len__(self):
|
||||
return self._index + 1
|
||||
|
||||
@property
|
||||
def genesis_done(self):
|
||||
return self._genesis_done
|
||||
|
||||
@property
|
||||
def index(self):
|
||||
return self._index
|
||||
|
||||
# TODO error handling
|
||||
cdef Block* get_block_c(self, uint64_t idx):
|
||||
return self._chain[0][idx]
|
||||
|
||||
def get_block(self, idx):
|
||||
if idx < 0 or idx > self._index:
|
||||
raise IndexError("Index value is out of bounds")
|
||||
|
||||
cdef Block *block = self.get_block_c(idx)
|
||||
return PyBlock.from_ptr(block, owner=False)
|
||||
|
||||
cdef void add_block(self, Block *block):
|
||||
self._chain[0][block.index] = block
|
||||
if self._genesis_done:
|
||||
self._index += 1
|
||||
|
||||
def create_genesis_block(self):
|
||||
cdef Block *block = new Block(
|
||||
self._index,
|
||||
datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp(),
|
||||
0,
|
||||
"Genesis Block".encode("UTF-8"),
|
||||
"0".encode("UTF-8"),
|
||||
"".encode("UTF-8"),
|
||||
)
|
||||
block.hash = <string>"dummy hash".encode("UTF-8")
|
||||
self.add_block(block)
|
||||
self._genesis_done = <bint>1
|
||||
|
||||
def new_block(self, data):
|
||||
if not self._genesis_done:
|
||||
raise RuntimeError("Create a genesis block first.")
|
||||
|
||||
cdef Block *prev_block = self.get_block_c(self._index)
|
||||
cdef string prev_hash = prev_block.prev_hash
|
||||
cdef uint64_t new_idx = self._index + 1
|
||||
|
||||
cdef Block *block = new Block(
|
||||
new_idx,
|
||||
datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp(),
|
||||
0,
|
||||
data.encode("UTF-8"),
|
||||
prev_hash,
|
||||
"".encode("UTF-8"),
|
||||
)
|
||||
self.add_block(block)
|
||||
|
||||
# def __init__(
|
||||
# self,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user