generated from dopt-python/py311-cython
basic functionality
This commit is contained in:
parent
245b9532b9
commit
8a536a2111
7
setup.py
7
setup.py
@ -17,11 +17,14 @@ if DEBUG:
|
|||||||
linetrace_opt = True
|
linetrace_opt = True
|
||||||
|
|
||||||
ext_modules = cythonize(
|
ext_modules = cythonize(
|
||||||
["src/polluck_blockchain/placeholder.py"],
|
[
|
||||||
|
"src/polluck_blockchain/placeholder.py",
|
||||||
|
"src/polluck_blockchain/python_translate.py",
|
||||||
|
],
|
||||||
compiler_directives={
|
compiler_directives={
|
||||||
"language_level": 3,
|
"language_level": 3,
|
||||||
"boundscheck": False,
|
"boundscheck": False,
|
||||||
"wraparound": False,
|
"wraparound": True,
|
||||||
"embedsignature": False,
|
"embedsignature": False,
|
||||||
"annotation_typing": True,
|
"annotation_typing": True,
|
||||||
"linetrace": linetrace_opt,
|
"linetrace": linetrace_opt,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
import cython
|
import cython
|
||||||
import dopt_basics.datetime
|
import dopt_basics.datetime
|
||||||
@ -73,6 +76,11 @@ class StringHolder:
|
|||||||
# )
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
@cython.cfunc
|
||||||
|
def float_to_bytes(num: cython.double):
|
||||||
|
return struct.pack(">d", num)
|
||||||
|
|
||||||
|
|
||||||
@cython.cclass
|
@cython.cclass
|
||||||
class Block:
|
class Block:
|
||||||
_index = cython.declare(cython.ulong, visibility="private")
|
_index = cython.declare(cython.ulong, visibility="private")
|
||||||
@ -80,6 +88,7 @@ class Block:
|
|||||||
_data = cython.declare(StringHolder, visibility="private")
|
_data = cython.declare(StringHolder, visibility="private")
|
||||||
_prev_hash = cython.declare(StringHolder, visibility="private")
|
_prev_hash = cython.declare(StringHolder, visibility="private")
|
||||||
_nonce = cython.declare(cython.ulong, visibility="private")
|
_nonce = cython.declare(cython.ulong, visibility="private")
|
||||||
|
_hash = cython.declare(StringHolder, visibility="private")
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -89,11 +98,31 @@ class Block:
|
|||||||
nonce: int,
|
nonce: int,
|
||||||
):
|
):
|
||||||
self._index = index
|
self._index = index
|
||||||
self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
|
# self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
|
||||||
|
self._timestamp = datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()
|
||||||
self._data = StringHolder.__new__(StringHolder, data)
|
self._data = StringHolder.__new__(StringHolder, data)
|
||||||
self._prev_hash = StringHolder.__new__(StringHolder, previous_hash)
|
self._prev_hash = StringHolder.__new__(StringHolder, previous_hash)
|
||||||
self._nonce = nonce
|
self._nonce = nonce
|
||||||
|
self._hash = StringHolder.__new__(StringHolder, "")
|
||||||
|
|
||||||
|
@cython.ccall
|
||||||
|
def _perform_hash(self):
|
||||||
|
parts = bytearray()
|
||||||
|
parts.extend(self._index.to_bytes(8, "big"))
|
||||||
|
parts.extend(float_to_bytes(self._timestamp))
|
||||||
|
parts.extend(self._data.py_bytes)
|
||||||
|
parts.extend(self._prev_hash.py_bytes)
|
||||||
|
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
|
@property
|
||||||
def index(self):
|
def index(self):
|
||||||
return self._index
|
return self._index
|
||||||
@ -117,3 +146,62 @@ class Block:
|
|||||||
@nonce.setter
|
@nonce.setter
|
||||||
def nonce(self, value: int):
|
def nonce(self, value: int):
|
||||||
self._nonce = value
|
self._nonce = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hash(self):
|
||||||
|
return self._hash.py_string
|
||||||
|
|
||||||
|
@hash.setter
|
||||||
|
def hash(self, value: str):
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError("No string")
|
||||||
|
self._hash = StringHolder.__new__(StringHolder, value)
|
||||||
|
|
||||||
|
|
||||||
|
class Blockchain:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
difficulty: int = 1,
|
||||||
|
) -> None:
|
||||||
|
self.chain: list[Block] = []
|
||||||
|
# self.difficulty = difficulty.to_bytes(8, "big")
|
||||||
|
self.difficulty = difficulty
|
||||||
|
|
||||||
|
def create_genesis_block(self):
|
||||||
|
genesis = Block(
|
||||||
|
index=0,
|
||||||
|
data="Genesis Block",
|
||||||
|
previous_hash="0",
|
||||||
|
nonce=0,
|
||||||
|
)
|
||||||
|
genesis.hash = genesis.compute_hash()
|
||||||
|
self.chain.append(genesis)
|
||||||
|
|
||||||
|
def proof_of_work(
|
||||||
|
self,
|
||||||
|
block: Block,
|
||||||
|
) -> str:
|
||||||
|
prefix = "0" * self.difficulty
|
||||||
|
while True:
|
||||||
|
block_hash = block.compute_hash()
|
||||||
|
if block_hash.startswith(prefix):
|
||||||
|
return block_hash
|
||||||
|
block.nonce += 1
|
||||||
|
|
||||||
|
def add_block(self, data: str) -> Block:
|
||||||
|
new_block = Block(
|
||||||
|
index=len(self.chain),
|
||||||
|
data=data,
|
||||||
|
previous_hash=self.chain[-1].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)
|
||||||
|
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
|
||||||
|
|||||||
139
src/polluck_blockchain/python.py
Normal file
139
src/polluck_blockchain/python.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
"""placeholder module for compilation"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
|
import dopt_basics.datetime
|
||||||
|
|
||||||
|
|
||||||
|
def float_to_bytes(num: float):
|
||||||
|
return struct.pack(">d", num)
|
||||||
|
|
||||||
|
|
||||||
|
class Block:
|
||||||
|
__slots__ = (
|
||||||
|
"_index",
|
||||||
|
"_timestamp",
|
||||||
|
"_data",
|
||||||
|
"_prev_hash",
|
||||||
|
"_nonce",
|
||||||
|
"_hash",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
index: int,
|
||||||
|
data: str,
|
||||||
|
previous_hash: str,
|
||||||
|
nonce: int,
|
||||||
|
):
|
||||||
|
self._index = index
|
||||||
|
self._timestamp = datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()
|
||||||
|
# self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
|
||||||
|
self._data = data
|
||||||
|
self._prev_hash = previous_hash
|
||||||
|
self._nonce = nonce
|
||||||
|
self._hash = ""
|
||||||
|
|
||||||
|
def _perform_hash(self):
|
||||||
|
parts = bytearray()
|
||||||
|
parts.extend(self._index.to_bytes(8, "big"))
|
||||||
|
parts.extend(float_to_bytes(self._timestamp))
|
||||||
|
parts.extend(self._data.encode("UTF-8"))
|
||||||
|
parts.extend(self._prev_hash.encode("UTF-8"))
|
||||||
|
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) -> int:
|
||||||
|
return self._index
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timestamp(self) -> datetime.datetime:
|
||||||
|
return datetime.datetime.fromtimestamp(self._timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self) -> str:
|
||||||
|
return self._data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prev_hash(self) -> str:
|
||||||
|
return self._prev_hash
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nonce(self):
|
||||||
|
return self._nonce
|
||||||
|
|
||||||
|
@nonce.setter
|
||||||
|
def nonce(self, value: int):
|
||||||
|
self._nonce = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hash(self) -> str:
|
||||||
|
return self._hash
|
||||||
|
|
||||||
|
@hash.setter
|
||||||
|
def hash(self, value: str) -> None:
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError("No string")
|
||||||
|
self._hash = value
|
||||||
|
|
||||||
|
|
||||||
|
class Blockchain:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
difficulty: int = 1,
|
||||||
|
) -> None:
|
||||||
|
self.chain: list[Block] = []
|
||||||
|
# self.difficulty = difficulty.to_bytes(8, "big")
|
||||||
|
self.difficulty = difficulty
|
||||||
|
|
||||||
|
def create_genesis_block(self):
|
||||||
|
genesis = Block(
|
||||||
|
index=0,
|
||||||
|
data="Genesis Block",
|
||||||
|
previous_hash="0",
|
||||||
|
nonce=0,
|
||||||
|
)
|
||||||
|
genesis.hash = genesis.compute_hash()
|
||||||
|
self.chain.append(genesis)
|
||||||
|
|
||||||
|
def proof_of_work(
|
||||||
|
self,
|
||||||
|
block: Block,
|
||||||
|
) -> str:
|
||||||
|
prefix = "0" * self.difficulty
|
||||||
|
while True:
|
||||||
|
block_hash = block.compute_hash()
|
||||||
|
if block_hash.startswith(prefix):
|
||||||
|
return block_hash
|
||||||
|
block.nonce += 1
|
||||||
|
|
||||||
|
def add_block(self, data: str) -> Block:
|
||||||
|
new_block = Block(
|
||||||
|
index=len(self.chain),
|
||||||
|
data=data,
|
||||||
|
previous_hash=self.chain[-1].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)
|
||||||
|
print(f"Mined block {new_block.index} in {elapsed:.3f}s with nonce={new_block.nonce}")
|
||||||
|
|
||||||
|
return new_block
|
||||||
12746
src/polluck_blockchain/python_translate.c
Normal file
12746
src/polluck_blockchain/python_translate.c
Normal file
File diff suppressed because it is too large
Load Diff
140
src/polluck_blockchain/python_translate.py
Normal file
140
src/polluck_blockchain/python_translate.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
"""placeholder module for compilation"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
|
import dopt_basics.datetime
|
||||||
|
|
||||||
|
|
||||||
|
def float_to_bytes(num: float):
|
||||||
|
return struct.pack(">d", num)
|
||||||
|
|
||||||
|
|
||||||
|
class Block:
|
||||||
|
__slots__ = (
|
||||||
|
"_index",
|
||||||
|
"_timestamp",
|
||||||
|
"_data",
|
||||||
|
"_prev_hash",
|
||||||
|
"_nonce",
|
||||||
|
"_hash",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
index: int,
|
||||||
|
data: str,
|
||||||
|
previous_hash: str,
|
||||||
|
nonce: int,
|
||||||
|
):
|
||||||
|
self._index = index
|
||||||
|
self._timestamp = datetime.datetime(2025, 12, 1, 12, 0, 0).timestamp()
|
||||||
|
# self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
|
||||||
|
self._data = data
|
||||||
|
self._prev_hash = previous_hash
|
||||||
|
self._nonce = nonce
|
||||||
|
self._hash = ""
|
||||||
|
|
||||||
|
def _perform_hash(self):
|
||||||
|
parts = bytearray()
|
||||||
|
parts.extend(self._index.to_bytes(8, "big"))
|
||||||
|
parts.extend(float_to_bytes(self._timestamp))
|
||||||
|
parts.extend(self._data.encode("UTF-8"))
|
||||||
|
parts.extend(self._prev_hash.encode("UTF-8"))
|
||||||
|
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) -> int:
|
||||||
|
return self._index
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timestamp(self) -> datetime.datetime:
|
||||||
|
return datetime.datetime.fromtimestamp(self._timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self) -> str:
|
||||||
|
return self._data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prev_hash(self) -> str:
|
||||||
|
return self._prev_hash
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nonce(self):
|
||||||
|
return self._nonce
|
||||||
|
|
||||||
|
@nonce.setter
|
||||||
|
def nonce(self, value: int):
|
||||||
|
self._nonce = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hash(self) -> str:
|
||||||
|
return self._hash
|
||||||
|
|
||||||
|
@hash.setter
|
||||||
|
def hash(self, value: str) -> None:
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError("No string")
|
||||||
|
self._hash = value
|
||||||
|
|
||||||
|
|
||||||
|
class Blockchain:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
difficulty: int = 1,
|
||||||
|
) -> None:
|
||||||
|
self.chain: list[Block] = []
|
||||||
|
# self.difficulty = difficulty.to_bytes(8, "big")
|
||||||
|
self.difficulty = difficulty
|
||||||
|
|
||||||
|
def create_genesis_block(self):
|
||||||
|
genesis = Block(
|
||||||
|
index=0,
|
||||||
|
data="Genesis Block",
|
||||||
|
previous_hash="0",
|
||||||
|
nonce=0,
|
||||||
|
)
|
||||||
|
genesis.hash = genesis.compute_hash()
|
||||||
|
self.chain.append(genesis)
|
||||||
|
|
||||||
|
def proof_of_work(
|
||||||
|
self,
|
||||||
|
block: Block,
|
||||||
|
) -> str:
|
||||||
|
prefix = "0" * self.difficulty
|
||||||
|
while True:
|
||||||
|
block_hash = block.compute_hash()
|
||||||
|
if block_hash.startswith(prefix):
|
||||||
|
return block_hash
|
||||||
|
block.nonce += 1
|
||||||
|
|
||||||
|
def add_block(self, data: str) -> Block:
|
||||||
|
new_block = Block(
|
||||||
|
index=len(self.chain),
|
||||||
|
data=data,
|
||||||
|
previous_hash=self.chain[-1].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)
|
||||||
|
# print(f"Mined block {new_block.index} in {elapsed:.3f}s with nonce={new_block.nonce}")
|
||||||
|
print(f"Mined block {new_block.index} with nonce={new_block.nonce}")
|
||||||
|
|
||||||
|
return new_block
|
||||||
Loading…
x
Reference in New Issue
Block a user