zexus 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Zexus Stack Trace Formatter
|
|
3
|
+
|
|
4
|
+
Provides beautiful, informative stack traces for runtime errors.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional, Dict, Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StackFrame:
|
|
11
|
+
"""Represents a single frame in the call stack"""
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
function_name: str,
|
|
16
|
+
filename: Optional[str] = None,
|
|
17
|
+
line: Optional[int] = None,
|
|
18
|
+
column: Optional[int] = None,
|
|
19
|
+
source_line: Optional[str] = None,
|
|
20
|
+
node_type: Optional[str] = None
|
|
21
|
+
):
|
|
22
|
+
self.function_name = function_name
|
|
23
|
+
self.filename = filename or "<unknown>"
|
|
24
|
+
self.line = line
|
|
25
|
+
self.column = column
|
|
26
|
+
self.source_line = source_line
|
|
27
|
+
self.node_type = node_type
|
|
28
|
+
|
|
29
|
+
def __str__(self):
|
|
30
|
+
location = f"{self.filename}"
|
|
31
|
+
if self.line:
|
|
32
|
+
location += f":{self.line}"
|
|
33
|
+
if self.column:
|
|
34
|
+
location += f":{self.column}"
|
|
35
|
+
|
|
36
|
+
result = f" at {self.function_name} ({location})"
|
|
37
|
+
|
|
38
|
+
if self.source_line and self.line:
|
|
39
|
+
# Show source context
|
|
40
|
+
result += f"\n {self.line} | {self.source_line.strip()}"
|
|
41
|
+
if self.column:
|
|
42
|
+
# Add pointer
|
|
43
|
+
padding = len(str(self.line)) + 3 + self.column
|
|
44
|
+
result += f"\n {' ' * padding}^"
|
|
45
|
+
|
|
46
|
+
return result
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class StackTraceFormatter:
|
|
50
|
+
"""Formats stack traces for display"""
|
|
51
|
+
|
|
52
|
+
def __init__(self):
|
|
53
|
+
self.max_frames = 10 # Maximum frames to display
|
|
54
|
+
self.context_lines = 1 # Lines of context around error
|
|
55
|
+
|
|
56
|
+
def format_stack_trace(
|
|
57
|
+
self,
|
|
58
|
+
frames: List[StackFrame],
|
|
59
|
+
error_message: str,
|
|
60
|
+
show_full: bool = False
|
|
61
|
+
) -> str:
|
|
62
|
+
"""
|
|
63
|
+
Format a complete stack trace.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
frames: List of stack frames
|
|
67
|
+
error_message: The error message
|
|
68
|
+
show_full: Show all frames or truncate
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Formatted stack trace string
|
|
72
|
+
"""
|
|
73
|
+
if not frames:
|
|
74
|
+
return error_message
|
|
75
|
+
|
|
76
|
+
parts = []
|
|
77
|
+
parts.append(f"Traceback (most recent call last):")
|
|
78
|
+
|
|
79
|
+
# Limit frames if not showing full
|
|
80
|
+
display_frames = frames
|
|
81
|
+
if not show_full and len(frames) > self.max_frames:
|
|
82
|
+
# Show first few and last few
|
|
83
|
+
first_half = self.max_frames // 2
|
|
84
|
+
second_half = self.max_frames - first_half
|
|
85
|
+
display_frames = (
|
|
86
|
+
frames[:first_half] +
|
|
87
|
+
[None] + # Marker for truncation
|
|
88
|
+
frames[-second_half:]
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for i, frame in enumerate(display_frames):
|
|
92
|
+
if frame is None:
|
|
93
|
+
parts.append(f" ... {len(frames) - self.max_frames} frames omitted ...")
|
|
94
|
+
else:
|
|
95
|
+
parts.append(str(frame))
|
|
96
|
+
|
|
97
|
+
parts.append(f"\n{error_message}")
|
|
98
|
+
|
|
99
|
+
return "\n".join(parts)
|
|
100
|
+
|
|
101
|
+
def format_simple_trace(self, frames: List[StackFrame], limit: int = 3) -> str:
|
|
102
|
+
"""
|
|
103
|
+
Format a simple stack trace (just function names and locations).
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
frames: List of stack frames
|
|
107
|
+
limit: Maximum frames to show
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Formatted trace string
|
|
111
|
+
"""
|
|
112
|
+
if not frames:
|
|
113
|
+
return ""
|
|
114
|
+
|
|
115
|
+
display_frames = frames[-limit:] if len(frames) > limit else frames
|
|
116
|
+
|
|
117
|
+
parts = ["Call stack:"]
|
|
118
|
+
for frame in display_frames:
|
|
119
|
+
location = f"{frame.filename}"
|
|
120
|
+
if frame.line:
|
|
121
|
+
location += f":{frame.line}"
|
|
122
|
+
parts.append(f" {frame.function_name} at {location}")
|
|
123
|
+
|
|
124
|
+
return "\n".join(parts)
|
|
125
|
+
|
|
126
|
+
def create_frame_from_node(
|
|
127
|
+
self,
|
|
128
|
+
node,
|
|
129
|
+
function_name: str,
|
|
130
|
+
error_reporter=None
|
|
131
|
+
) -> StackFrame:
|
|
132
|
+
"""
|
|
133
|
+
Create a stack frame from an AST node.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
node: AST node
|
|
137
|
+
function_name: Name of the function/context
|
|
138
|
+
error_reporter: Error reporter for source lookup
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
StackFrame instance
|
|
142
|
+
"""
|
|
143
|
+
filename = None
|
|
144
|
+
line = None
|
|
145
|
+
column = None
|
|
146
|
+
source_line = None
|
|
147
|
+
node_type = type(node).__name__ if node else None
|
|
148
|
+
|
|
149
|
+
# Extract location info from node
|
|
150
|
+
if hasattr(node, 'token') and node.token:
|
|
151
|
+
token = node.token
|
|
152
|
+
line = getattr(token, 'line', None)
|
|
153
|
+
column = getattr(token, 'column', None)
|
|
154
|
+
|
|
155
|
+
# Try to get source line if error reporter available
|
|
156
|
+
if error_reporter and line:
|
|
157
|
+
source_line = error_reporter.get_source_line(filename, line)
|
|
158
|
+
|
|
159
|
+
return StackFrame(
|
|
160
|
+
function_name=function_name,
|
|
161
|
+
filename=filename,
|
|
162
|
+
line=line,
|
|
163
|
+
column=column,
|
|
164
|
+
source_line=source_line,
|
|
165
|
+
node_type=node_type
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# Global formatter instance
|
|
170
|
+
_stack_trace_formatter = StackTraceFormatter()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_stack_trace_formatter() -> StackTraceFormatter:
|
|
174
|
+
"""Get the global stack trace formatter"""
|
|
175
|
+
return _stack_trace_formatter
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def format_call_stack(frames: List[str], limit: int = 5) -> str:
|
|
179
|
+
"""
|
|
180
|
+
Format a simple call stack from string frames.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
frames: List of frame strings
|
|
184
|
+
limit: Maximum frames to display
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Formatted stack string
|
|
188
|
+
"""
|
|
189
|
+
if not frames:
|
|
190
|
+
return ""
|
|
191
|
+
|
|
192
|
+
display_frames = frames[-limit:] if len(frames) > limit else frames
|
|
193
|
+
|
|
194
|
+
parts = ["Call stack:"]
|
|
195
|
+
for frame in display_frames:
|
|
196
|
+
parts.append(f" {frame}")
|
|
197
|
+
|
|
198
|
+
if len(frames) > limit:
|
|
199
|
+
parts.insert(1, f" ... {len(frames) - limit} frames omitted ...")
|
|
200
|
+
|
|
201
|
+
return "\n".join(parts)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def create_frame_info(
|
|
205
|
+
function_name: str,
|
|
206
|
+
filename: str = "<unknown>",
|
|
207
|
+
line: Optional[int] = None,
|
|
208
|
+
node_type: Optional[str] = None
|
|
209
|
+
) -> str:
|
|
210
|
+
"""
|
|
211
|
+
Create a simple frame info string.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
function_name: Name of function
|
|
215
|
+
filename: Source filename
|
|
216
|
+
line: Line number
|
|
217
|
+
node_type: Type of AST node
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Frame info string
|
|
221
|
+
"""
|
|
222
|
+
parts = [function_name]
|
|
223
|
+
|
|
224
|
+
if filename != "<unknown>" or line:
|
|
225
|
+
location = filename
|
|
226
|
+
if line:
|
|
227
|
+
location += f":{line}"
|
|
228
|
+
parts.append(f"({location})")
|
|
229
|
+
|
|
230
|
+
if node_type:
|
|
231
|
+
parts.append(f"[{node_type}]")
|
|
232
|
+
|
|
233
|
+
return " ".join(parts)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Zexus Standard Library."""
|
|
2
|
+
|
|
3
|
+
from .fs import FileSystemModule
|
|
4
|
+
from .http import HttpModule
|
|
5
|
+
from .json_module import JsonModule
|
|
6
|
+
from .datetime import DateTimeModule
|
|
7
|
+
from .crypto import CryptoModule
|
|
8
|
+
from .blockchain import BlockchainModule
|
|
9
|
+
from .os_module import OSModule
|
|
10
|
+
from .regex import RegexModule
|
|
11
|
+
from .math import MathModule
|
|
12
|
+
from .encoding import EncodingModule
|
|
13
|
+
from .compression import CompressionModule
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
'FileSystemModule',
|
|
17
|
+
'HttpModule',
|
|
18
|
+
'JsonModule',
|
|
19
|
+
'DateTimeModule',
|
|
20
|
+
'CryptoModule',
|
|
21
|
+
'BlockchainModule',
|
|
22
|
+
'OSModule',
|
|
23
|
+
'RegexModule',
|
|
24
|
+
'MathModule',
|
|
25
|
+
'EncodingModule',
|
|
26
|
+
'CompressionModule'
|
|
27
|
+
]
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"""Blockchain utilities module for Zexus standard library."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
import hashlib
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Proof of work maximum iterations constant
|
|
9
|
+
MAX_POW_ITERATIONS = 10_000_000
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BlockchainModule:
|
|
13
|
+
"""Provides blockchain utility functions."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def quantum_resistant_hash(data: str, algorithm: str = 'shake256', output_length: int = 64) -> str:
|
|
17
|
+
"""Calculate quantum-resistant hash using SHAKE256 or SHA3.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
data: Data to hash
|
|
21
|
+
algorithm: 'shake256', 'shake128', 'sha3_512', 'sha3_384', 'sha3_256'
|
|
22
|
+
output_length: Output length in bytes for SHAKE (default: 64)
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Hexadecimal hash string
|
|
26
|
+
|
|
27
|
+
Note: SHAKE256 and SHA3 are quantum-resistant hash functions from the SHA-3 family.
|
|
28
|
+
"""
|
|
29
|
+
if algorithm == 'shake256':
|
|
30
|
+
return hashlib.shake_256(data.encode()).hexdigest(output_length)
|
|
31
|
+
elif algorithm == 'shake128':
|
|
32
|
+
return hashlib.shake_128(data.encode()).hexdigest(output_length)
|
|
33
|
+
elif algorithm == 'sha3_512':
|
|
34
|
+
return hashlib.sha3_512(data.encode()).hexdigest()
|
|
35
|
+
elif algorithm == 'sha3_384':
|
|
36
|
+
return hashlib.sha3_384(data.encode()).hexdigest()
|
|
37
|
+
elif algorithm == 'sha3_256':
|
|
38
|
+
return hashlib.sha3_256(data.encode()).hexdigest()
|
|
39
|
+
elif algorithm == 'sha3_224':
|
|
40
|
+
return hashlib.sha3_224(data.encode()).hexdigest()
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError(f"Unknown algorithm: {algorithm}")
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def quantum_safe_address(public_key: str, prefix: str = "0x") -> str:
|
|
46
|
+
"""Create quantum-safe address from public key using SHAKE256.
|
|
47
|
+
|
|
48
|
+
Uses SHAKE256 (SHA-3 family) which is quantum-resistant.
|
|
49
|
+
"""
|
|
50
|
+
# Use SHAKE256 for quantum resistance
|
|
51
|
+
shake_hash = hashlib.shake_256(public_key.encode()).hexdigest(20) # 20 bytes = 40 hex chars
|
|
52
|
+
return f"{prefix}{shake_hash}"
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def create_quantum_block(index: int, timestamp: float, data: Any,
|
|
56
|
+
previous_hash: str, nonce: int = 0) -> Dict[str, Any]:
|
|
57
|
+
"""Create a quantum-resistant blockchain block using SHA3-256."""
|
|
58
|
+
block = {
|
|
59
|
+
'index': index,
|
|
60
|
+
'timestamp': timestamp,
|
|
61
|
+
'data': data,
|
|
62
|
+
'previous_hash': previous_hash,
|
|
63
|
+
'nonce': nonce
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Calculate block hash using SHA3-256 (quantum-resistant)
|
|
67
|
+
block_string = str(block['index']) + str(block['timestamp']) + \
|
|
68
|
+
str(block['data']) + block['previous_hash'] + str(block['nonce'])
|
|
69
|
+
block['hash'] = hashlib.sha3_256(block_string.encode()).hexdigest()
|
|
70
|
+
|
|
71
|
+
return block
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def quantum_proof_of_work(block_data: str, difficulty: int = 4,
|
|
75
|
+
max_iterations: int = MAX_POW_ITERATIONS) -> tuple:
|
|
76
|
+
"""Quantum-resistant proof-of-work using SHA3-256.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
block_data: Data to hash
|
|
80
|
+
difficulty: Number of leading zeros required
|
|
81
|
+
max_iterations: Maximum iterations before giving up
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Tuple of (nonce, hash) or (nonce, "") if max iterations reached
|
|
85
|
+
"""
|
|
86
|
+
nonce = 0
|
|
87
|
+
prefix = '0' * difficulty
|
|
88
|
+
|
|
89
|
+
while nonce < max_iterations:
|
|
90
|
+
hash_attempt = hashlib.sha3_256(f"{block_data}{nonce}".encode()).hexdigest()
|
|
91
|
+
|
|
92
|
+
if hash_attempt.startswith(prefix):
|
|
93
|
+
return nonce, hash_attempt
|
|
94
|
+
|
|
95
|
+
nonce += 1
|
|
96
|
+
|
|
97
|
+
return nonce, ""
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def validate_quantum_proof_of_work(block_data: str, nonce: int, hash_value: str,
|
|
101
|
+
difficulty: int = 4) -> bool:
|
|
102
|
+
"""Validate quantum-resistant proof-of-work."""
|
|
103
|
+
prefix = '0' * difficulty
|
|
104
|
+
calculated_hash = hashlib.sha3_256(f"{block_data}{nonce}".encode()).hexdigest()
|
|
105
|
+
return calculated_hash == hash_value and hash_value.startswith(prefix)
|
|
106
|
+
|
|
107
|
+
@staticmethod
|
|
108
|
+
def create_address(public_key: str, prefix: str = "0x") -> str:
|
|
109
|
+
"""Create address from public key (Ethereum-style).
|
|
110
|
+
|
|
111
|
+
Note: Requires pycryptodome for true Keccak-256 hashing.
|
|
112
|
+
Raises RuntimeError if pycryptodome is not available.
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
# Try to use Keccak-256 (Ethereum standard)
|
|
116
|
+
from Crypto.Hash import keccak
|
|
117
|
+
k = keccak.new(digest_bits=256)
|
|
118
|
+
k.update(public_key.encode())
|
|
119
|
+
hash_hex = k.hexdigest()
|
|
120
|
+
except ImportError as exc:
|
|
121
|
+
# Keccak-256 implementation not available; cannot create
|
|
122
|
+
# Ethereum-compatible address without pycryptodome.
|
|
123
|
+
raise RuntimeError(
|
|
124
|
+
"Ethereum-compatible address generation requires the "
|
|
125
|
+
"'pycryptodome' package providing Crypto.Hash.keccak. "
|
|
126
|
+
"Install with: pip install pycryptodome"
|
|
127
|
+
) from exc
|
|
128
|
+
|
|
129
|
+
address = hash_hex[-40:] # Last 20 bytes (40 hex chars)
|
|
130
|
+
return f"{prefix}{address}"
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def validate_address(address: str, prefix: str = "0x") -> bool:
|
|
134
|
+
"""Validate blockchain address format."""
|
|
135
|
+
if not address.startswith(prefix):
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
hex_part = address[len(prefix):]
|
|
139
|
+
|
|
140
|
+
# Check if it's valid hex
|
|
141
|
+
try:
|
|
142
|
+
int(hex_part, 16)
|
|
143
|
+
except ValueError:
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
# Check length (40 hex chars for Ethereum-style)
|
|
147
|
+
return len(hex_part) == 40
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def calculate_merkle_root(hashes: List[str]) -> str:
|
|
151
|
+
"""Calculate Merkle root from list of hashes."""
|
|
152
|
+
if not hashes:
|
|
153
|
+
return hashlib.sha256(b'').hexdigest()
|
|
154
|
+
|
|
155
|
+
if len(hashes) == 1:
|
|
156
|
+
return hashes[0]
|
|
157
|
+
|
|
158
|
+
# Build merkle tree
|
|
159
|
+
current_level = hashes[:]
|
|
160
|
+
|
|
161
|
+
while len(current_level) > 1:
|
|
162
|
+
next_level = []
|
|
163
|
+
|
|
164
|
+
for i in range(0, len(current_level), 2):
|
|
165
|
+
if i + 1 < len(current_level):
|
|
166
|
+
# Combine two hashes
|
|
167
|
+
combined = current_level[i] + current_level[i + 1]
|
|
168
|
+
parent_hash = hashlib.sha256(combined.encode()).hexdigest()
|
|
169
|
+
else:
|
|
170
|
+
# Odd number, duplicate last hash
|
|
171
|
+
combined = current_level[i] + current_level[i]
|
|
172
|
+
parent_hash = hashlib.sha256(combined.encode()).hexdigest()
|
|
173
|
+
|
|
174
|
+
next_level.append(parent_hash)
|
|
175
|
+
|
|
176
|
+
current_level = next_level
|
|
177
|
+
|
|
178
|
+
return current_level[0]
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def create_block(index: int, timestamp: float, data: Any,
|
|
182
|
+
previous_hash: str, nonce: int = 0) -> Dict[str, Any]:
|
|
183
|
+
"""Create a blockchain block."""
|
|
184
|
+
block = {
|
|
185
|
+
'index': index,
|
|
186
|
+
'timestamp': timestamp,
|
|
187
|
+
'data': data,
|
|
188
|
+
'previous_hash': previous_hash,
|
|
189
|
+
'nonce': nonce
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# Calculate block hash
|
|
193
|
+
block_string = str(block['index']) + str(block['timestamp']) + \
|
|
194
|
+
str(block['data']) + block['previous_hash'] + str(block['nonce'])
|
|
195
|
+
block['hash'] = hashlib.sha256(block_string.encode()).hexdigest()
|
|
196
|
+
|
|
197
|
+
return block
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
def hash_block(block: Dict[str, Any]) -> str:
|
|
201
|
+
"""Calculate hash of a block."""
|
|
202
|
+
block_string = str(block.get('index', 0)) + \
|
|
203
|
+
str(block.get('timestamp', 0)) + \
|
|
204
|
+
str(block.get('data', '')) + \
|
|
205
|
+
str(block.get('previous_hash', '')) + \
|
|
206
|
+
str(block.get('nonce', 0))
|
|
207
|
+
return hashlib.sha256(block_string.encode()).hexdigest()
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def validate_block(block: Dict[str, Any], previous_block: Optional[Dict[str, Any]] = None) -> bool:
|
|
211
|
+
"""Validate a blockchain block."""
|
|
212
|
+
# Check if block has required fields
|
|
213
|
+
required_fields = ['index', 'timestamp', 'data', 'previous_hash', 'hash']
|
|
214
|
+
if not all(field in block for field in required_fields):
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
# Verify hash is correct
|
|
218
|
+
calculated_hash = BlockchainModule.hash_block(block)
|
|
219
|
+
if calculated_hash != block['hash']:
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
# If previous block provided, check linkage
|
|
223
|
+
if previous_block:
|
|
224
|
+
if block['previous_hash'] != previous_block['hash']:
|
|
225
|
+
return False
|
|
226
|
+
if block['index'] != previous_block['index'] + 1:
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
return True
|
|
230
|
+
|
|
231
|
+
@staticmethod
|
|
232
|
+
def proof_of_work(block_data: str, difficulty: int = 4, max_iterations: int = MAX_POW_ITERATIONS) -> tuple:
|
|
233
|
+
"""Simple proof-of-work mining (find nonce).
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
block_data: Data to hash
|
|
237
|
+
difficulty: Number of leading zeros required
|
|
238
|
+
max_iterations: Maximum iterations before giving up (default: 10,000,000)
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
Tuple of (nonce, hash) or (nonce, "") if max iterations reached
|
|
242
|
+
"""
|
|
243
|
+
nonce = 0
|
|
244
|
+
prefix = '0' * difficulty
|
|
245
|
+
|
|
246
|
+
while nonce < max_iterations:
|
|
247
|
+
hash_attempt = hashlib.sha256(f"{block_data}{nonce}".encode()).hexdigest()
|
|
248
|
+
|
|
249
|
+
if hash_attempt.startswith(prefix):
|
|
250
|
+
return nonce, hash_attempt
|
|
251
|
+
|
|
252
|
+
nonce += 1
|
|
253
|
+
|
|
254
|
+
return nonce, ""
|
|
255
|
+
|
|
256
|
+
@staticmethod
|
|
257
|
+
def validate_proof_of_work(block_data: str, nonce: int, hash_value: str, difficulty: int = 4) -> bool:
|
|
258
|
+
"""Validate proof-of-work."""
|
|
259
|
+
prefix = '0' * difficulty
|
|
260
|
+
calculated_hash = hashlib.sha256(f"{block_data}{nonce}".encode()).hexdigest()
|
|
261
|
+
return calculated_hash == hash_value and hash_value.startswith(prefix)
|
|
262
|
+
|
|
263
|
+
@staticmethod
|
|
264
|
+
def create_transaction(sender: str, recipient: str, amount: float,
|
|
265
|
+
timestamp: Optional[float] = None) -> Dict[str, Any]:
|
|
266
|
+
"""Create a transaction."""
|
|
267
|
+
if timestamp is None:
|
|
268
|
+
timestamp = time.time()
|
|
269
|
+
|
|
270
|
+
tx = {
|
|
271
|
+
'sender': sender,
|
|
272
|
+
'recipient': recipient,
|
|
273
|
+
'amount': amount,
|
|
274
|
+
'timestamp': timestamp
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
# Calculate transaction hash
|
|
278
|
+
tx_string = f"{tx['sender']}{tx['recipient']}{tx['amount']}{tx['timestamp']}"
|
|
279
|
+
tx['hash'] = hashlib.sha256(tx_string.encode()).hexdigest()
|
|
280
|
+
|
|
281
|
+
return tx
|
|
282
|
+
|
|
283
|
+
@staticmethod
|
|
284
|
+
def hash_transaction(tx: Dict[str, Any]) -> str:
|
|
285
|
+
"""Calculate hash of a transaction."""
|
|
286
|
+
tx_string = f"{tx.get('sender', '')}{tx.get('recipient', '')}" \
|
|
287
|
+
f"{tx.get('amount', 0)}{tx.get('timestamp', 0)}"
|
|
288
|
+
return hashlib.sha256(tx_string.encode()).hexdigest()
|
|
289
|
+
|
|
290
|
+
@staticmethod
|
|
291
|
+
def create_genesis_block() -> Dict[str, Any]:
|
|
292
|
+
"""Create the genesis block (first block in chain)."""
|
|
293
|
+
return BlockchainModule.create_block(
|
|
294
|
+
index=0,
|
|
295
|
+
timestamp=time.time(),
|
|
296
|
+
data="Genesis Block",
|
|
297
|
+
previous_hash="0" * 64,
|
|
298
|
+
nonce=0
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
@staticmethod
|
|
302
|
+
def validate_chain(chain: List[Dict[str, Any]]) -> bool:
|
|
303
|
+
"""Validate entire blockchain."""
|
|
304
|
+
if not chain:
|
|
305
|
+
return False
|
|
306
|
+
|
|
307
|
+
# Validate genesis block
|
|
308
|
+
if chain[0]['previous_hash'] != "0" * 64:
|
|
309
|
+
return False
|
|
310
|
+
|
|
311
|
+
# Validate each block
|
|
312
|
+
for i in range(len(chain)):
|
|
313
|
+
if i == 0:
|
|
314
|
+
if not BlockchainModule.validate_block(chain[i]):
|
|
315
|
+
return False
|
|
316
|
+
else:
|
|
317
|
+
if not BlockchainModule.validate_block(chain[i], chain[i-1]):
|
|
318
|
+
return False
|
|
319
|
+
|
|
320
|
+
return True
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# Export functions for easy access
|
|
324
|
+
create_address = BlockchainModule.create_address
|
|
325
|
+
validate_address = BlockchainModule.validate_address
|
|
326
|
+
calculate_merkle_root = BlockchainModule.calculate_merkle_root
|
|
327
|
+
create_block = BlockchainModule.create_block
|
|
328
|
+
hash_block = BlockchainModule.hash_block
|
|
329
|
+
validate_block = BlockchainModule.validate_block
|
|
330
|
+
proof_of_work = BlockchainModule.proof_of_work
|
|
331
|
+
validate_proof_of_work = BlockchainModule.validate_proof_of_work
|
|
332
|
+
create_transaction = BlockchainModule.create_transaction
|
|
333
|
+
hash_transaction = BlockchainModule.hash_transaction
|
|
334
|
+
create_genesis_block = BlockchainModule.create_genesis_block
|
|
335
|
+
validate_chain = BlockchainModule.validate_chain
|
|
336
|
+
# Quantum-resistant functions
|
|
337
|
+
quantum_resistant_hash = BlockchainModule.quantum_resistant_hash
|
|
338
|
+
quantum_safe_address = BlockchainModule.quantum_safe_address
|
|
339
|
+
create_quantum_block = BlockchainModule.create_quantum_block
|
|
340
|
+
quantum_proof_of_work = BlockchainModule.quantum_proof_of_work
|
|
341
|
+
validate_quantum_proof_of_work = BlockchainModule.validate_quantum_proof_of_work
|