generated from dopt-python/py311-cython
Include prototyping steps #1
8
setup.py
8
setup.py
@ -12,6 +12,7 @@ Options.embed_pos_in_docstring = False
|
|||||||
Options.annotate = False
|
Options.annotate = False
|
||||||
Options.fast_fail = True
|
Options.fast_fail = True
|
||||||
|
|
||||||
|
OPEN_MP = False
|
||||||
DEBUG = bool(os.getenv("DOPT_DEBUG", None))
|
DEBUG = bool(os.getenv("DOPT_DEBUG", None))
|
||||||
linetrace_opt: bool = False
|
linetrace_opt: bool = False
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
@ -60,8 +61,11 @@ linker_args: list[str] = []
|
|||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith("win") and not DEBUG:
|
if sys.platform.startswith("win") and not DEBUG:
|
||||||
c_args = ("/O2", "/GL", "/Gy", "/openmp:llvm")
|
c_args = ["/O2", "/GL", "/Gy"]
|
||||||
l_args = ("/LTCG", "/OPT:REF", "/OPT:ICF", "/openmp:llvm")
|
l_args = ["/LTCG", "/OPT:REF", "/OPT:ICF"]
|
||||||
|
if OPEN_MP:
|
||||||
|
c_args.extend(["/openmp:llvm"])
|
||||||
|
l_args.extend(["/openmp:llvm"])
|
||||||
else:
|
else:
|
||||||
c_args = tuple()
|
c_args = tuple()
|
||||||
l_args = tuple()
|
l_args = tuple()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -21,15 +21,21 @@ from libc.stdlib cimport malloc, free
|
|||||||
from libc.string cimport memcpy
|
from libc.string cimport memcpy
|
||||||
from cython.operator import postincrement, dereference
|
from cython.operator import postincrement, dereference
|
||||||
cimport polluck_blockchain.openssl_evp as ossl
|
cimport polluck_blockchain.openssl_evp as ossl
|
||||||
from cython.parallel cimport prange
|
# from cython.parallel cimport prange
|
||||||
|
|
||||||
|
|
||||||
ctypedef unsigned long ULong
|
ctypedef unsigned long ULong
|
||||||
ctypedef unordered_map[uint64_t, Block*] BcHashmap
|
ctypedef unordered_map[uint64_t, Block*] BcHashmap
|
||||||
|
cdef const size_t NONCE_OFFSET = <size_t>16
|
||||||
|
|
||||||
cdef timestamp_to_datetime(uint64_t ts):
|
cdef timestamp_to_datetime(uint64_t ts):
|
||||||
return datetime.datetime.fromtimestamp(float(ts), dopt_basics.datetime.TIMEZONE_UTC)
|
return datetime.datetime.fromtimestamp(float(ts), dopt_basics.datetime.TIMEZONE_UTC)
|
||||||
|
|
||||||
|
cdef uint64_t current_timestamp_integer():
|
||||||
|
cdef uint64_t ts
|
||||||
|
dt = dopt_basics.datetime.current_time_tz(cut_microseconds=True)
|
||||||
|
ts = <uint64_t>int(dt.timestamp())
|
||||||
|
return ts
|
||||||
|
|
||||||
# cdef float_to_bytes(double num):
|
# cdef float_to_bytes(double num):
|
||||||
# return struct.pack(">d", num)
|
# return struct.pack(">d", num)
|
||||||
@ -50,15 +56,6 @@ cdef int serialize_uint64(unsigned char* out, unsigned long long v) except -1 no
|
|||||||
out[6] = (v >> 8) & 0xFF
|
out[6] = (v >> 8) & 0xFF
|
||||||
out[7] = v & 0xFF
|
out[7] = v & 0xFF
|
||||||
|
|
||||||
# cdef struct SerializeResult:
|
|
||||||
# unsigned char *ptr
|
|
||||||
# size_t size
|
|
||||||
|
|
||||||
# cdef struct DigestResult:
|
|
||||||
# unsigned char *ptr
|
|
||||||
# size_t size
|
|
||||||
|
|
||||||
cdef const size_t NONCE_OFFSET = <size_t>16
|
|
||||||
|
|
||||||
cdef inline bint has_leading_zero_bits(const unsigned char *digest, int num_bits) nogil:
|
cdef inline bint has_leading_zero_bits(const unsigned char *digest, int num_bits) nogil:
|
||||||
cdef int i, full_bytes = num_bits // 8
|
cdef int i, full_bytes = num_bits // 8
|
||||||
@ -141,22 +138,6 @@ cdef class PyBlock:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__repr__()
|
return self.__repr__()
|
||||||
|
|
||||||
# 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
|
# Python public API
|
||||||
@property
|
@property
|
||||||
def index(self):
|
def index(self):
|
||||||
@ -178,172 +159,159 @@ cdef class PyBlock:
|
|||||||
def nonce(self):
|
def nonce(self):
|
||||||
return self.BlockC.nonce
|
return self.BlockC.nonce
|
||||||
|
|
||||||
# @nonce.setter
|
|
||||||
# def nonce(self, value: int):
|
|
||||||
# self._nonce = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hash(self):
|
def hash(self):
|
||||||
return self.BlockC.hash.decode("UTF-8")
|
return self.BlockC.hash.decode("UTF-8")
|
||||||
|
|
||||||
cdef unsigned char* bytes_serialize_c(self, size_t *size) nogil:
|
|
||||||
cdef:
|
|
||||||
size_t total_len
|
|
||||||
unsigned char* buf
|
|
||||||
size_t pos = 0
|
|
||||||
|
|
||||||
# index (8), timestamp (8), nonce (8), data, prev_hash
|
|
||||||
size[0] = (
|
|
||||||
<size_t>(8 * 3) +
|
|
||||||
self.BlockC.data.size() +
|
|
||||||
self.BlockC.prev_hash.size()
|
|
||||||
)
|
|
||||||
buf = <unsigned char*>malloc(size[0] * sizeof(unsigned char))
|
|
||||||
|
|
||||||
if buf == NULL:
|
|
||||||
return NULL
|
|
||||||
|
|
||||||
serialize_uint64(buf + pos, self.BlockC.index)
|
|
||||||
pos += 8
|
|
||||||
serialize_uint64(buf + pos, self.BlockC.timestamp)
|
|
||||||
pos += 8
|
|
||||||
serialize_uint64(buf + pos, self.BlockC.nonce)
|
|
||||||
pos += 8
|
|
||||||
# Copy data
|
|
||||||
memcpy(
|
|
||||||
buf + pos,
|
|
||||||
self.BlockC.data.c_str(),
|
|
||||||
self.BlockC.data.size(),
|
|
||||||
)
|
|
||||||
pos += self.BlockC.data.size()
|
|
||||||
# Copy prev_hash
|
|
||||||
memcpy(
|
|
||||||
buf + pos,
|
|
||||||
self.BlockC.prev_hash.c_str(),
|
|
||||||
self.BlockC.prev_hash.size(),
|
|
||||||
)
|
|
||||||
pos += self.BlockC.prev_hash.size()
|
|
||||||
|
|
||||||
return buf
|
|
||||||
|
|
||||||
cdef unsigned char* digest(self, unsigned char *data, size_t data_size, size_t *digest_size) nogil:
|
|
||||||
cdef ossl.EVP_MD_CTX *ctx = ossl.EVP_MD_CTX_new()
|
|
||||||
if ctx == NULL:
|
|
||||||
return NULL
|
|
||||||
cdef const ossl.EVP_MD *algo = ossl.EVP_sha256()
|
|
||||||
if algo == NULL:
|
|
||||||
return NULL
|
|
||||||
|
|
||||||
cdef:
|
|
||||||
unsigned char* digest
|
|
||||||
size_t dig_buff_len
|
|
||||||
unsigned int digest_len
|
|
||||||
|
|
||||||
dig_buff_len = <size_t>ossl.EVP_MD_size(algo)
|
|
||||||
digest = <unsigned char*>malloc(dig_buff_len * sizeof(unsigned char))
|
|
||||||
ossl.EVP_DigestInit_ex(ctx, algo, NULL)
|
|
||||||
ossl.EVP_DigestUpdate(ctx, data, data_size)
|
|
||||||
ossl.EVP_DigestFinal_ex(ctx, digest, &digest_len)
|
|
||||||
|
|
||||||
digest_size[0] = dig_buff_len
|
|
||||||
|
|
||||||
ossl.EVP_MD_CTX_free(ctx)
|
|
||||||
|
|
||||||
return digest
|
|
||||||
|
|
||||||
def bytes_serialize(self):
|
def bytes_serialize(self):
|
||||||
cdef:
|
cdef:
|
||||||
unsigned char *serialize_res
|
unsigned char *serialize_res
|
||||||
size_t serialize_size
|
size_t serialize_size
|
||||||
try:
|
try:
|
||||||
serialize_res = self.bytes_serialize_c(&serialize_size)
|
serialize_res = bytes_serialize_c(self.BlockC, &serialize_size)
|
||||||
return serialize_res[:serialize_size]
|
return serialize_res[:serialize_size]
|
||||||
finally:
|
finally:
|
||||||
free(serialize_res)
|
free(serialize_res)
|
||||||
|
|
||||||
cpdef mine(self, unsigned int difficulty, unsigned int max_nonce=0xFFFFFFFF):
|
|
||||||
cdef:
|
|
||||||
unsigned char *serial_buf
|
|
||||||
size_t serialize_size
|
|
||||||
unsigned char *digest
|
|
||||||
size_t digest_size
|
|
||||||
bint nonce_found = False
|
|
||||||
int nonce, nonce_solution = 0
|
|
||||||
|
|
||||||
serial_buf = self.bytes_serialize_c(&serialize_size)
|
|
||||||
|
|
||||||
with nogil:
|
|
||||||
for nonce in range(max_nonce):
|
|
||||||
serialize_uint64(serial_buf + NONCE_OFFSET, <uint64_t>nonce)
|
|
||||||
digest = self.digest(serial_buf, serialize_size, &digest_size)
|
|
||||||
|
|
||||||
if has_leading_zero_bits(digest, difficulty):
|
def perform_hash(self):
|
||||||
nonce_found = True
|
|
||||||
nonce_solution = nonce
|
|
||||||
break
|
|
||||||
|
|
||||||
free(digest)
|
|
||||||
|
|
||||||
if not nonce_found:
|
|
||||||
raise RuntimeError("No valid nonce found")
|
|
||||||
|
|
||||||
self.BlockC.nonce = <uint64_t>nonce_solution
|
|
||||||
|
|
||||||
cdef unsigned char* perform_hash_c(self, size_t *digest_size) nogil:
|
|
||||||
cdef:
|
|
||||||
unsigned char *serialize_res
|
|
||||||
size_t serialize_size
|
|
||||||
unsigned char *digest
|
|
||||||
|
|
||||||
serialize_res = self.bytes_serialize_c(&serialize_size)
|
|
||||||
if serialize_res == NULL:
|
|
||||||
return NULL
|
|
||||||
digest = self.digest(serialize_res, serialize_size, digest_size)
|
|
||||||
if digest == NULL:
|
|
||||||
return NULL
|
|
||||||
|
|
||||||
free(serialize_res)
|
|
||||||
|
|
||||||
return digest
|
|
||||||
|
|
||||||
cpdef perform_hash(self):
|
|
||||||
cdef:
|
cdef:
|
||||||
unsigned char *digest
|
unsigned char *digest
|
||||||
size_t digest_size
|
size_t digest_size
|
||||||
|
|
||||||
try:
|
try:
|
||||||
digest = self.perform_hash_c(&digest_size)
|
digest = perform_hash_c(self.BlockC, &digest_size)
|
||||||
if digest == NULL:
|
if digest == NULL:
|
||||||
raise MemoryError()
|
raise MemoryError()
|
||||||
|
# TODO out: hash assignment in blockchain
|
||||||
self.BlockC.hash = bytes(digest[:digest_size]).hex().encode("UTF-8")
|
self.BlockC.hash = bytes(digest[:digest_size]).hex().encode("UTF-8")
|
||||||
finally:
|
finally:
|
||||||
free(digest)
|
free(digest)
|
||||||
|
# TODO rework
|
||||||
return self.hash
|
return self.hash
|
||||||
|
|
||||||
|
|
||||||
|
cdef unsigned char* bytes_serialize_c(Block *block, size_t *size) nogil:
|
||||||
|
cdef:
|
||||||
|
size_t total_len
|
||||||
|
unsigned char* buf
|
||||||
|
size_t pos = 0
|
||||||
|
|
||||||
|
# index (8), timestamp (8), nonce (8), data, prev_hash
|
||||||
|
size[0] = (
|
||||||
|
<size_t>(8 * 3) +
|
||||||
|
block.data.size() +
|
||||||
|
block.prev_hash.size()
|
||||||
|
)
|
||||||
|
buf = <unsigned char*>malloc(size[0] * sizeof(unsigned char))
|
||||||
|
|
||||||
|
if buf == NULL:
|
||||||
|
return NULL
|
||||||
|
|
||||||
|
serialize_uint64(buf + pos, block.index)
|
||||||
|
pos += 8
|
||||||
|
serialize_uint64(buf + pos, block.timestamp)
|
||||||
|
pos += 8
|
||||||
|
serialize_uint64(buf + pos, block.nonce)
|
||||||
|
pos += 8
|
||||||
|
# Copy data
|
||||||
|
memcpy(
|
||||||
|
buf + pos,
|
||||||
|
block.data.c_str(),
|
||||||
|
block.data.size(),
|
||||||
|
)
|
||||||
|
pos += block.data.size()
|
||||||
|
# Copy prev_hash
|
||||||
|
memcpy(
|
||||||
|
buf + pos,
|
||||||
|
block.prev_hash.c_str(),
|
||||||
|
block.prev_hash.size(),
|
||||||
|
)
|
||||||
|
pos += block.prev_hash.size()
|
||||||
|
|
||||||
|
return buf
|
||||||
|
|
||||||
|
cdef unsigned char* SHA256_digest(const void *data, size_t data_size, size_t *digest_size) nogil:
|
||||||
|
cdef ossl.EVP_MD_CTX *ctx = ossl.EVP_MD_CTX_new()
|
||||||
|
if ctx == NULL:
|
||||||
|
return NULL
|
||||||
|
cdef const ossl.EVP_MD *algo = ossl.EVP_sha256()
|
||||||
|
if algo == NULL:
|
||||||
|
return NULL
|
||||||
|
|
||||||
|
cdef:
|
||||||
|
unsigned char* digest
|
||||||
|
size_t dig_buff_len
|
||||||
|
unsigned int digest_len
|
||||||
|
|
||||||
|
dig_buff_len = <size_t>ossl.EVP_MD_size(algo)
|
||||||
|
digest_size[0] = dig_buff_len
|
||||||
|
digest = <unsigned char*>malloc(dig_buff_len * sizeof(unsigned char))
|
||||||
|
ossl.EVP_DigestInit_ex(ctx, algo, NULL)
|
||||||
|
ossl.EVP_DigestUpdate(ctx, data, data_size)
|
||||||
|
ossl.EVP_DigestFinal_ex(ctx, digest, &digest_len)
|
||||||
|
|
||||||
|
ossl.EVP_MD_CTX_free(ctx)
|
||||||
|
|
||||||
|
return digest
|
||||||
|
|
||||||
|
|
||||||
|
cdef unsigned char* perform_hash_c(Block *block, size_t *digest_size) nogil:
|
||||||
|
cdef:
|
||||||
|
unsigned char *serialize_res
|
||||||
|
size_t serialize_size
|
||||||
|
unsigned char *digest
|
||||||
|
|
||||||
|
serialize_res = bytes_serialize_c(block, &serialize_size)
|
||||||
|
if serialize_res == NULL:
|
||||||
|
return NULL
|
||||||
|
digest = SHA256_digest(serialize_res, serialize_size, digest_size)
|
||||||
|
free(serialize_res)
|
||||||
|
if digest == NULL:
|
||||||
|
return NULL
|
||||||
|
|
||||||
|
return digest
|
||||||
|
|
||||||
|
|
||||||
# @hash.setter
|
cdef int mine_block(Block *block, unsigned int difficulty, uint64_t *nonce_solution, unsigned int max_nonce=0xFFFFFFFF) nogil:
|
||||||
# def hash(self, value):
|
cdef:
|
||||||
# if not isinstance(value, str):
|
unsigned char *serial_buf
|
||||||
# raise TypeError("No string")
|
size_t serialize_size
|
||||||
# self._hash = value.encode("UTF-8")
|
unsigned char *digest
|
||||||
|
size_t digest_size
|
||||||
|
bint nonce_found = False
|
||||||
|
int nonce
|
||||||
|
|
||||||
# cdef void add_block(BcHashmap *map, Block *block):
|
serial_buf = bytes_serialize_c(block, &serialize_size)
|
||||||
# map[block.index] = block
|
|
||||||
|
with nogil:
|
||||||
|
for nonce in range(max_nonce):
|
||||||
|
serialize_uint64(serial_buf + NONCE_OFFSET, <uint64_t>nonce)
|
||||||
|
digest = SHA256_digest(serial_buf, serialize_size, &digest_size)
|
||||||
|
|
||||||
|
if has_leading_zero_bits(digest, difficulty):
|
||||||
|
nonce_found = True
|
||||||
|
nonce_solution[0] = nonce
|
||||||
|
break
|
||||||
|
|
||||||
|
free(digest)
|
||||||
|
|
||||||
|
free(serial_buf)
|
||||||
|
|
||||||
|
if not nonce_found:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
cdef class Blockchain:
|
cdef class Blockchain:
|
||||||
cdef int _difficulty
|
cdef unsigned int _difficulty
|
||||||
cdef uint64_t _index
|
cdef uint64_t _index
|
||||||
cdef BcHashmap *_chain
|
cdef BcHashmap *_chain
|
||||||
cdef bint _genesis_done
|
cdef bint _genesis_done
|
||||||
|
|
||||||
def __cinit__(self):
|
def __cinit__(self):
|
||||||
self._difficulty = 1
|
self._difficulty = 26
|
||||||
self._index = <uint64_t>0
|
self._index = <uint64_t>0
|
||||||
self._genesis_done = <bint>0
|
self._genesis_done = <bint>0
|
||||||
self._chain = new unordered_map[uint64_t, Block*]()
|
self._chain = new unordered_map[uint64_t, Block*]()
|
||||||
@ -351,8 +319,9 @@ cdef class Blockchain:
|
|||||||
raise MemoryError("Could not allocate hasmap")
|
raise MemoryError("Could not allocate hasmap")
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
# self.db_path = db_path
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __dealloc__(self):
|
def __dealloc__(self):
|
||||||
# ownership is typically not transferred from the Blockchain extension class
|
# ownership is typically not transferred from the Blockchain extension class
|
||||||
cdef BcHashmap.iterator it = self._chain.begin()
|
cdef BcHashmap.iterator it = self._chain.begin()
|
||||||
@ -367,6 +336,26 @@ cdef class Blockchain:
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self._index + 1
|
return self._index + 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def difficulty(self):
|
||||||
|
return self._difficulty
|
||||||
|
|
||||||
|
@difficulty.setter
|
||||||
|
def difficulty(self, value):
|
||||||
|
if not isinstance(value, int):
|
||||||
|
raise TypeError("Difficulty must be integer value")
|
||||||
|
if value <= 0:
|
||||||
|
raise ValueError("Difficulty must be greater than 0")
|
||||||
|
self._difficulty = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def genesis_done(self):
|
||||||
|
return self._genesis_done
|
||||||
|
|
||||||
|
@property
|
||||||
|
def index(self):
|
||||||
|
return self._index
|
||||||
|
|
||||||
def print_key_value_pair(self):
|
def print_key_value_pair(self):
|
||||||
cdef BcHashmap.iterator it = self._chain.begin()
|
cdef BcHashmap.iterator it = self._chain.begin()
|
||||||
cdef Block *block
|
cdef Block *block
|
||||||
@ -377,109 +366,101 @@ cdef class Blockchain:
|
|||||||
print(py_block)
|
print(py_block)
|
||||||
postincrement(it)
|
postincrement(it)
|
||||||
|
|
||||||
@property
|
cdef Block* get_block_c(self, uint64_t idx) nogil:
|
||||||
def genesis_done(self):
|
if idx > self._index:
|
||||||
return self._genesis_done
|
return NULL
|
||||||
|
|
||||||
@property
|
|
||||||
def index(self):
|
|
||||||
return self._index
|
|
||||||
|
|
||||||
# TODO error handling
|
|
||||||
cdef Block* get_block_c(self, uint64_t idx):
|
|
||||||
return self._chain[0][idx]
|
return self._chain[0][idx]
|
||||||
|
|
||||||
|
cdef int add_block(self, Block *block) nogil:
|
||||||
|
cdef:
|
||||||
|
uint64_t mined_nonce
|
||||||
|
size_t digest_size
|
||||||
|
unsigned char *sha256_digest
|
||||||
|
# mine block
|
||||||
|
if mine_block(block, self._difficulty, &mined_nonce) != 0:
|
||||||
|
return 1
|
||||||
|
block.nonce = mined_nonce
|
||||||
|
# hash block, add hash to block, add block to blockchain hashmap
|
||||||
|
sha256_digest = perform_hash_c(block, &digest_size)
|
||||||
|
with gil:
|
||||||
|
block.hash = bytes(sha256_digest[:digest_size]).hex().encode("UTF-8")
|
||||||
|
free(sha256_digest)
|
||||||
|
self._chain[0][block.index] = block
|
||||||
|
|
||||||
|
if self._genesis_done:
|
||||||
|
self._index += 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# // Python public API
|
||||||
def get_block(self, idx):
|
def get_block(self, idx):
|
||||||
if idx < 0 or idx > self._index:
|
if idx < 0 or idx > self._index:
|
||||||
raise IndexError("Index value is out of bounds")
|
raise IndexError("Index value is out of bounds")
|
||||||
|
|
||||||
cdef Block *block = self.get_block_c(idx)
|
cdef Block *block = self.get_block_c(idx)
|
||||||
|
if block == NULL:
|
||||||
|
raise IndexError("Provided index not found")
|
||||||
return PyBlock.from_ptr(block, owner=False)
|
return PyBlock.from_ptr(block, owner=False)
|
||||||
|
|
||||||
cdef void add_block(self, Block *block):
|
cdef string hash_data(self, data):
|
||||||
self._chain[0][block.index] = block
|
cdef:
|
||||||
if self._genesis_done:
|
string data_str
|
||||||
self._index += 1
|
unsigned char *data_digest
|
||||||
|
size_t digest_size
|
||||||
|
data_str = data.encode("UTF-8")
|
||||||
|
data_digest = SHA256_digest(data_str.c_str(), data_str.size(), &digest_size)
|
||||||
|
if data_digest == NULL:
|
||||||
|
raise RuntimeError("Failed to hash data")
|
||||||
|
data_str = bytes(data_digest[:digest_size]).hex().encode("UTF-8")
|
||||||
|
free(data_digest)
|
||||||
|
|
||||||
|
return data_str
|
||||||
|
|
||||||
def create_genesis_block(self):
|
def create_genesis_block(self):
|
||||||
|
genesis_prev_hash = ("0" * 64).encode("UTF-8")
|
||||||
|
cdef string data_str = self.hash_data("Genesis Block")
|
||||||
|
|
||||||
cdef Block *block = new Block(
|
cdef Block *block = new Block(
|
||||||
self._index,
|
self._index,
|
||||||
int(datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()),
|
int(datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()),
|
||||||
0,
|
0,
|
||||||
"Genesis Block".encode("UTF-8"),
|
data_str,
|
||||||
"0".encode("UTF-8"),
|
genesis_prev_hash,
|
||||||
"".encode("UTF-8"),
|
"".encode("UTF-8"),
|
||||||
)
|
)
|
||||||
block.hash = "dummy hash".encode("UTF-8")
|
cdef int res = self.add_block(block)
|
||||||
self.add_block(block)
|
if res != 0:
|
||||||
|
raise RuntimeError("Could not mine block. No nonce found")
|
||||||
self._genesis_done = True
|
self._genesis_done = True
|
||||||
|
|
||||||
def new_block(self, data):
|
def new_block(self, data):
|
||||||
|
cdef:
|
||||||
|
Block *prev_block
|
||||||
|
string prev_hash
|
||||||
|
uint64_t new_idx
|
||||||
|
string data_str
|
||||||
|
unsigned char *data_digest
|
||||||
|
size_t digest_size
|
||||||
|
|
||||||
if not self._genesis_done:
|
if not self._genesis_done:
|
||||||
raise RuntimeError("Create a genesis block first.")
|
raise RuntimeError("Create a genesis block first.")
|
||||||
|
if not isinstance(data, str):
|
||||||
|
raise TypeError("Data must be a string")
|
||||||
|
|
||||||
cdef Block *prev_block = self.get_block_c(self._index)
|
data_str = self.hash_data(data)
|
||||||
cdef string prev_hash = prev_block.prev_hash
|
prev_block = self.get_block_c(self._index)
|
||||||
cdef uint64_t new_idx = self._index + 1
|
prev_hash = prev_block.prev_hash
|
||||||
|
new_idx = self._index + 1
|
||||||
|
|
||||||
cdef Block *block = new Block(
|
cdef Block *block = new Block(
|
||||||
new_idx,
|
new_idx,
|
||||||
int(datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()),
|
int(datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()),
|
||||||
0,
|
0,
|
||||||
data.encode("UTF-8"),
|
data_str,
|
||||||
prev_hash,
|
prev_hash,
|
||||||
"".encode("UTF-8"),
|
"".encode("UTF-8"),
|
||||||
)
|
)
|
||||||
self.add_block(block)
|
cdef int res = self.add_block(block)
|
||||||
|
if res != 0:
|
||||||
|
raise RuntimeError("Could not mine block. No nonce found")
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user