Include prototyping steps #1

Merged
foefl merged 15 commits from native_hashing into main 2025-12-16 12:50:07 +00:00
4 changed files with 1225 additions and 565 deletions
Showing only changes of commit b3324182f7 - Show all commits

View File

@ -1,25 +1,44 @@
import os
import sys
from pathlib import Path
from Cython.Build import cythonize
from Cython.Compiler import Options
from setuptools import setup
from setuptools import Extension, setup
# Cython compilation options
Options.docstrings = False
Options.embed_pos_in_docstring = False
Options.annotate = False
Options.fast_fail = True
DEBUG = bool(os.getenv("DOPT_DEBUG", None))
linetrace_opt: bool = False
if DEBUG:
linetrace_opt = True
# includes
OPENSSL_DIR = (Path(__file__).parent / "openssl").resolve()
assert OPENSSL_DIR.exists()
openssl_include = OPENSSL_DIR / "include"
assert openssl_include.exists()
openssl_lib = OPENSSL_DIR / "lib"
assert openssl_lib.exists()
ext = Extension(
name="polluck_blockchain.placeholder_native",
sources=["src/polluck_blockchain/placeholder_native.pyx"],
include_dirs=[str(openssl_include)],
library_dirs=[str(openssl_lib)],
libraries=["libssl", "libcrypto"],
)
ext_modules = cythonize(
[
ext,
# "src/polluck_blockchain/placeholder.py",
"src/polluck_blockchain/placeholder_native.pyx",
# "src/polluck_blockchain/placeholder_native.pyx",
# "src/polluck_blockchain/python_translate.py",
],
compiler_directives={

View File

@ -0,0 +1,15 @@
cdef extern from "openssl/evp.h":
ctypedef struct EVP_MD_CTX:
pass
ctypedef struct EVP_MD:
pass
EVP_MD_CTX *EVP_MD_CTX_new()
void EVP_MD_CTX_free(EVP_MD_CTX *)
const EVP_MD *EVP_sha256()
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, void *impl)
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt)
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md,
unsigned int *s)
int EVP_MD_size(const EVP_MD *md)
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@ from libc.stdint cimport uint64_t
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy
from cython.operator import postincrement, dereference
cimport polluck_blockchain.openssl_evp as ossl
ctypedef unsigned long ULong
@ -48,9 +49,13 @@ cdef int serialize_uint64(unsigned char* out, unsigned long long v) except -1 no
out[6] = (v >> 8) & 0xFF
out[7] = v & 0xFF
cdef struct SerializeResult:
unsigned char *ptr
size_t size
# cdef struct SerializeResult:
# unsigned char *ptr
# size_t size
# cdef struct DigestResult:
# unsigned char *ptr
# size_t size
cdef class PyBlock:
cdef:
@ -159,19 +164,19 @@ cdef class PyBlock:
def hash(self):
return self.BlockC.hash.decode("UTF-8")
cdef SerializeResult bytes_serialize_c(self):
cdef unsigned char* bytes_serialize_c(self, size_t *size):
cdef:
size_t total_len
unsigned char* buf
size_t pos = 0
# index (8), timestamp (8), nonce (8), data, prev_hash
total_len = (
size[0] = (
<size_t>(8 * 3) +
self.BlockC.data.size() +
self.BlockC.prev_hash.size()
)
buf = <unsigned char*>malloc(total_len * sizeof(unsigned char))
buf = <unsigned char*>malloc(size[0] * sizeof(unsigned char))
if buf == NULL:
raise MemoryError()
@ -197,15 +202,65 @@ cdef class PyBlock:
)
pos += self.BlockC.prev_hash.size()
return SerializeResult(buf, total_len)
return buf
def bytes_serialize(self):
cdef SerializeResult serialize_res
cdef:
unsigned char *serialize_res
size_t serialize_size
try:
serialize_res = self.bytes_serialize_c()
return serialize_res.ptr[:serialize_res.size]
serialize_res = self.bytes_serialize_c(&serialize_size)
return serialize_res[:serialize_size]
finally:
free(serialize_res.ptr)
free(serialize_res)
cdef unsigned char* digest(self, unsigned char *data, size_t data_size, size_t *digest_size):
cdef ossl.EVP_MD_CTX *ctx = ossl.EVP_MD_CTX_new()
if ctx == NULL:
raise MemoryError()
cdef const ossl.EVP_MD *algo = ossl.EVP_sha256()
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
cdef unsigned char* perform_hash_c(self, size_t *digest_size):
cdef:
unsigned char *serialize_res
size_t serialize_size
unsigned char *digest
serialize_res = self.bytes_serialize_c(&serialize_size)
digest = self.digest(serialize_res, serialize_size, digest_size)
return digest
cpdef perform_hash(self):
cdef:
unsigned char *digest
size_t digest_size
try:
digest = self.perform_hash_c(&digest_size)
self.BlockC.hash = bytes(digest[:digest_size]).hex().encode("UTF-8")
finally:
free(digest)
return self.hash