zexus 1.7.2 → 1.8.1

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.
Files changed (49) hide show
  1. package/README.md +57 -6
  2. package/package.json +2 -1
  3. package/rust_core/Cargo.lock +603 -0
  4. package/rust_core/Cargo.toml +26 -0
  5. package/rust_core/README.md +15 -0
  6. package/rust_core/pyproject.toml +25 -0
  7. package/rust_core/src/binary_bytecode.rs +543 -0
  8. package/rust_core/src/contract_vm.rs +643 -0
  9. package/rust_core/src/executor.rs +847 -0
  10. package/rust_core/src/hasher.rs +90 -0
  11. package/rust_core/src/lib.rs +71 -0
  12. package/rust_core/src/merkle.rs +128 -0
  13. package/rust_core/src/rust_vm.rs +2313 -0
  14. package/rust_core/src/signature.rs +79 -0
  15. package/rust_core/src/state_adapter.rs +281 -0
  16. package/rust_core/src/validator.rs +116 -0
  17. package/scripts/postinstall.js +34 -2
  18. package/src/zexus/__init__.py +1 -1
  19. package/src/zexus/blockchain/accelerator.py +27 -0
  20. package/src/zexus/blockchain/contract_vm.py +409 -3
  21. package/src/zexus/blockchain/rust_bridge.py +64 -0
  22. package/src/zexus/cli/main.py +1 -1
  23. package/src/zexus/cli/zpm.py +1 -1
  24. package/src/zexus/evaluator/bytecode_compiler.py +150 -52
  25. package/src/zexus/evaluator/core.py +151 -809
  26. package/src/zexus/evaluator/expressions.py +27 -22
  27. package/src/zexus/evaluator/functions.py +171 -126
  28. package/src/zexus/evaluator/statements.py +55 -112
  29. package/src/zexus/module_cache.py +20 -9
  30. package/src/zexus/object.py +330 -38
  31. package/src/zexus/parser/parser.py +69 -14
  32. package/src/zexus/parser/strategy_context.py +228 -5
  33. package/src/zexus/parser/strategy_structural.py +2 -2
  34. package/src/zexus/persistence.py +46 -17
  35. package/src/zexus/security.py +140 -234
  36. package/src/zexus/type_checker.py +44 -5
  37. package/src/zexus/vm/binary_bytecode.py +7 -3
  38. package/src/zexus/vm/bytecode.py +6 -0
  39. package/src/zexus/vm/cache.py +24 -46
  40. package/src/zexus/vm/compiler.py +80 -20
  41. package/src/zexus/vm/fastops.c +1093 -2975
  42. package/src/zexus/vm/gas_metering.py +2 -2
  43. package/src/zexus/vm/memory_pool.py +21 -9
  44. package/src/zexus/vm/vm.py +527 -67
  45. package/src/zexus/zpm/package_manager.py +1 -1
  46. package/src/zexus.egg-info/PKG-INFO +79 -12
  47. package/src/zexus.egg-info/SOURCES.txt +23 -1
  48. package/src/zexus.egg-info/requires.txt +26 -0
  49. package/src/zexus.egg-info/entry_points.txt +0 -4
@@ -0,0 +1,79 @@
1
+ // ─────────────────────────────────────────────────────────────────────
2
+ // ECDSA-secp256k1 Signature Verification (batch-parallel)
3
+ // ─────────────────────────────────────────────────────────────────────
4
+
5
+ use k256::ecdsa::{
6
+ signature::Verifier, Signature, VerifyingKey,
7
+ };
8
+ use pyo3::prelude::*;
9
+ use rayon::prelude::*;
10
+ use sha2::{Digest, Sha256};
11
+
12
+ #[pyclass]
13
+ pub struct RustSignature;
14
+
15
+ #[pymethods]
16
+ impl RustSignature {
17
+ #[new]
18
+ fn new() -> Self {
19
+ RustSignature
20
+ }
21
+
22
+ /// Verify a single ECDSA-secp256k1 signature.
23
+ ///
24
+ /// * `message` — the raw message bytes that were signed
25
+ /// * `signature` — 64-byte DER or compact signature
26
+ /// * `public_key`— 33-byte (compressed) or 65-byte (uncompressed) public key
27
+ ///
28
+ /// Returns `true` if the signature is valid.
29
+ #[staticmethod]
30
+ fn verify(message: Vec<u8>, signature: Vec<u8>, public_key: Vec<u8>) -> bool {
31
+ Self::_verify_inner(&message, &signature, &public_key)
32
+ }
33
+
34
+ /// Batch-verify multiple signatures in parallel.
35
+ ///
36
+ /// Each item is a tuple `(message_bytes, signature_bytes, pubkey_bytes)`.
37
+ /// Returns a list of booleans (one per signature).
38
+ #[staticmethod]
39
+ fn verify_batch(
40
+ py: Python<'_>,
41
+ items: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>,
42
+ ) -> Vec<bool> {
43
+ py.allow_threads(|| {
44
+ items
45
+ .par_iter()
46
+ .map(|(msg, sig, pk)| Self::_verify_inner(msg, sig, pk))
47
+ .collect()
48
+ })
49
+ }
50
+
51
+ /// Hash a message with SHA-256 then verify the signature against the
52
+ /// hash. This matches the common blockchain pattern of sign(sha256(msg)).
53
+ #[staticmethod]
54
+ fn verify_hashed(message: Vec<u8>, signature: Vec<u8>, public_key: Vec<u8>) -> bool {
55
+ let hash = Sha256::digest(&message);
56
+ Self::_verify_inner(&hash, &signature, &public_key)
57
+ }
58
+ }
59
+
60
+ impl RustSignature {
61
+ fn _verify_inner(message: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
62
+ verify_single(message, signature, public_key)
63
+ }
64
+ }
65
+
66
+ /// Public helper so other modules (validator) can call it directly.
67
+ pub fn verify_single(message: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
68
+ let vk = match VerifyingKey::from_sec1_bytes(public_key) {
69
+ Ok(vk) => vk,
70
+ Err(_) => return false,
71
+ };
72
+
73
+ let sig = match Signature::from_slice(signature) {
74
+ Ok(s) => s,
75
+ Err(_) => return false,
76
+ };
77
+
78
+ vk.verify(message, &sig).is_ok()
79
+ }
@@ -0,0 +1,281 @@
1
+ // ─────────────────────────────────────────────────────────────────────
2
+ // Zexus Blockchain — Rust State Adapter (Phase 3)
3
+ // ─────────────────────────────────────────────────────────────────────
4
+ //
5
+ // In-memory state cache that batches reads/writes in Rust to minimise
6
+ // GIL crossings when the Rust VM operates on blockchain state.
7
+ //
8
+ // Architecture:
9
+ //
10
+ // 1. Pre-load state from Python dict → Rust HashMap ("warm cache")
11
+ // 2. STATE_READ/STATE_WRITE hit the Rust cache — zero Python calls
12
+ // 3. After execution, flush dirty keys back to Python in one batch
13
+ // 4. TX_BEGIN/TX_COMMIT/TX_REVERT use Rust-side snapshots
14
+ //
15
+ // This avoids per-opcode GIL acquisition for state operations,
16
+ // delivering ~50x speedup on state-heavy contracts.
17
+
18
+ use pyo3::prelude::*;
19
+ use pyo3::types::{PyDict, PyList};
20
+ use pyo3::ToPyObject;
21
+ use std::collections::{HashMap, HashSet};
22
+
23
+ /// A single value in the state cache.
24
+ #[derive(Debug, Clone)]
25
+ pub enum StateValue {
26
+ Null,
27
+ Bool(bool),
28
+ Int(i64),
29
+ Float(f64),
30
+ Str(String),
31
+ Bytes(Vec<u8>),
32
+ List(Vec<StateValue>),
33
+ Map(Vec<(String, StateValue)>),
34
+ }
35
+
36
+ impl StateValue {
37
+ /// Convert a Python object to a StateValue.
38
+ pub fn from_py(py: Python<'_>, obj: &PyObject) -> Self {
39
+ let bound = obj.bind(py);
40
+ if bound.is_none() {
41
+ return StateValue::Null;
42
+ }
43
+ if let Ok(b) = bound.extract::<bool>() {
44
+ return StateValue::Bool(b);
45
+ }
46
+ if let Ok(i) = bound.extract::<i64>() {
47
+ return StateValue::Int(i);
48
+ }
49
+ if let Ok(f) = bound.extract::<f64>() {
50
+ return StateValue::Float(f);
51
+ }
52
+ if let Ok(s) = bound.extract::<String>() {
53
+ return StateValue::Str(s);
54
+ }
55
+ if let Ok(list) = bound.downcast::<PyList>() {
56
+ let items: Vec<StateValue> = list
57
+ .iter()
58
+ .map(|item| StateValue::from_py(py, &item.to_object(py)))
59
+ .collect();
60
+ return StateValue::List(items);
61
+ }
62
+ if let Ok(dict) = bound.downcast::<PyDict>() {
63
+ let items: Vec<(String, StateValue)> = dict
64
+ .iter()
65
+ .filter_map(|(k, v)| {
66
+ k.extract::<String>()
67
+ .ok()
68
+ .map(|key| (key, StateValue::from_py(py, &v.to_object(py))))
69
+ })
70
+ .collect();
71
+ return StateValue::Map(items);
72
+ }
73
+ // Fallback: try string representation
74
+ if let Ok(s) = bound.str().and_then(|s| s.extract::<String>()) {
75
+ return StateValue::Str(s);
76
+ }
77
+ StateValue::Null
78
+ }
79
+
80
+ /// Convert to a Python object.
81
+ pub fn to_py(&self, py: Python<'_>) -> PyObject {
82
+ match self {
83
+ StateValue::Null => py.None(),
84
+ StateValue::Bool(b) => b.to_object(py),
85
+ StateValue::Int(i) => i.to_object(py),
86
+ StateValue::Float(f) => f.to_object(py),
87
+ StateValue::Str(s) => s.to_object(py),
88
+ StateValue::Bytes(b) => {
89
+ pyo3::types::PyBytes::new_bound(py, b).to_object(py)
90
+ }
91
+ StateValue::List(items) => {
92
+ let py_list = PyList::empty_bound(py);
93
+ for item in items {
94
+ let _ = py_list.append(item.to_py(py));
95
+ }
96
+ py_list.to_object(py)
97
+ }
98
+ StateValue::Map(items) => {
99
+ let py_dict = PyDict::new_bound(py);
100
+ for (k, v) in items {
101
+ let _ = py_dict.set_item(k, v.to_py(py));
102
+ }
103
+ py_dict.to_object(py)
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ /// Transaction snapshot for nested transaction support.
110
+ struct TxSnapshot {
111
+ cache: HashMap<String, StateValue>,
112
+ dirty: HashSet<String>,
113
+ }
114
+
115
+ /// Rust-side state cache with batch flush capability.
116
+ ///
117
+ /// Usage from Python:
118
+ /// ```python
119
+ /// from zexus_core import RustStateAdapter
120
+ /// adapter = RustStateAdapter()
121
+ /// adapter.load_from_dict({"key": "value", "counter": 42})
122
+ /// adapter.set("counter", 43)
123
+ /// val = adapter.get("counter")
124
+ /// dirty = adapter.flush_dirty() # returns dict of changed keys
125
+ /// ```
126
+ #[pyclass]
127
+ pub struct RustStateAdapter {
128
+ /// In-memory state cache (key → value).
129
+ cache: HashMap<String, StateValue>,
130
+
131
+ /// Set of keys that have been written (dirty) since last flush.
132
+ dirty: HashSet<String>,
133
+
134
+ /// Transaction snapshot stack for TX_BEGIN/TX_COMMIT/TX_REVERT.
135
+ tx_stack: Vec<TxSnapshot>,
136
+
137
+ /// Total reads served from cache (no Python call).
138
+ cache_hits: u64,
139
+
140
+ /// Total writes batched (no Python call until flush).
141
+ cache_writes: u64,
142
+ }
143
+
144
+ #[pymethods]
145
+ impl RustStateAdapter {
146
+ #[new]
147
+ fn new() -> Self {
148
+ RustStateAdapter {
149
+ cache: HashMap::new(),
150
+ dirty: HashSet::new(),
151
+ tx_stack: Vec::new(),
152
+ cache_hits: 0,
153
+ cache_writes: 0,
154
+ }
155
+ }
156
+
157
+ /// Bulk-load state from a Python dict into the Rust cache.
158
+ /// This is the "warm-up" step — called once before Rust VM execution.
159
+ fn load_from_dict(&mut self, py: Python<'_>, data: &Bound<'_, PyDict>) -> PyResult<u64> {
160
+ let mut count: u64 = 0;
161
+ for (k, v) in data.iter() {
162
+ let key = k.extract::<String>()?;
163
+ let val = StateValue::from_py(py, &v.to_object(py));
164
+ self.cache.insert(key, val);
165
+ count += 1;
166
+ }
167
+ Ok(count)
168
+ }
169
+
170
+ /// Read a value from the cache.
171
+ fn get(&mut self, py: Python<'_>, key: &str) -> PyObject {
172
+ self.cache_hits += 1;
173
+ match self.cache.get(key) {
174
+ Some(val) => val.to_py(py),
175
+ None => py.None(),
176
+ }
177
+ }
178
+
179
+ /// Write a value to the cache and mark it dirty.
180
+ fn set(&mut self, py: Python<'_>, key: String, value: PyObject) {
181
+ let sv = StateValue::from_py(py, &value);
182
+ self.cache.insert(key.clone(), sv);
183
+ self.dirty.insert(key);
184
+ self.cache_writes += 1;
185
+ }
186
+
187
+ /// Check if a key exists in the cache.
188
+ fn contains(&self, key: &str) -> bool {
189
+ self.cache.contains_key(key)
190
+ }
191
+
192
+ /// Delete a key from the cache and mark it dirty (sets to Null).
193
+ fn delete(&mut self, key: &str) {
194
+ self.cache.insert(key.to_string(), StateValue::Null);
195
+ self.dirty.insert(key.to_string());
196
+ self.cache_writes += 1;
197
+ }
198
+
199
+ /// Return all dirty (modified) keys as a Python dict.
200
+ /// Clears the dirty set after flushing.
201
+ fn flush_dirty(&mut self, py: Python<'_>) -> PyResult<PyObject> {
202
+ let result = PyDict::new_bound(py);
203
+ for key in self.dirty.drain() {
204
+ if let Some(val) = self.cache.get(&key) {
205
+ result.set_item(&key, val.to_py(py))?;
206
+ }
207
+ }
208
+ Ok(result.to_object(py))
209
+ }
210
+
211
+ /// Return the full cache as a Python dict.
212
+ fn to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
213
+ let result = PyDict::new_bound(py);
214
+ for (k, v) in &self.cache {
215
+ result.set_item(k, v.to_py(py))?;
216
+ }
217
+ Ok(result.to_object(py))
218
+ }
219
+
220
+ /// Get the number of keys in the cache.
221
+ fn len(&self) -> usize {
222
+ self.cache.len()
223
+ }
224
+
225
+ /// Get the number of dirty keys pending flush.
226
+ fn dirty_count(&self) -> usize {
227
+ self.dirty.len()
228
+ }
229
+
230
+ /// Begin a transaction — snapshot current state.
231
+ fn tx_begin(&mut self) {
232
+ let snapshot = TxSnapshot {
233
+ cache: self.cache.clone(),
234
+ dirty: self.dirty.clone(),
235
+ };
236
+ self.tx_stack.push(snapshot);
237
+ }
238
+
239
+ /// Commit a transaction — discard the snapshot, keep changes.
240
+ fn tx_commit(&mut self) -> bool {
241
+ if self.tx_stack.is_empty() {
242
+ return false;
243
+ }
244
+ // Pop snapshot but keep current state — changes are committed
245
+ let _snapshot = self.tx_stack.pop().unwrap();
246
+ // Merge dirty keys from this transaction into the parent
247
+ // (dirty set already contains all writes — nothing extra needed)
248
+ true
249
+ }
250
+
251
+ /// Revert a transaction — restore the snapshot.
252
+ fn tx_revert(&mut self) -> bool {
253
+ if let Some(snapshot) = self.tx_stack.pop() {
254
+ self.cache = snapshot.cache;
255
+ self.dirty = snapshot.dirty;
256
+ true
257
+ } else {
258
+ false
259
+ }
260
+ }
261
+
262
+ /// Return cache statistics.
263
+ fn stats(&self, py: Python<'_>) -> PyResult<PyObject> {
264
+ let result = PyDict::new_bound(py);
265
+ result.set_item("cache_size", self.cache.len())?;
266
+ result.set_item("dirty_count", self.dirty.len())?;
267
+ result.set_item("cache_hits", self.cache_hits)?;
268
+ result.set_item("cache_writes", self.cache_writes)?;
269
+ result.set_item("tx_depth", self.tx_stack.len())?;
270
+ Ok(result.to_object(py))
271
+ }
272
+
273
+ /// Reset the adapter.
274
+ fn clear(&mut self) {
275
+ self.cache.clear();
276
+ self.dirty.clear();
277
+ self.tx_stack.clear();
278
+ self.cache_hits = 0;
279
+ self.cache_writes = 0;
280
+ }
281
+ }
@@ -0,0 +1,116 @@
1
+ // ─────────────────────────────────────────────────────────────────────
2
+ // Block Validation — fast parallel checks
3
+ // ─────────────────────────────────────────────────────────────────────
4
+
5
+ use pyo3::prelude::*;
6
+ use rayon::prelude::*;
7
+ use sha2::{Digest, Sha256};
8
+ use std::collections::HashMap;
9
+
10
+ /// Validates block header integrity at native speed.
11
+ #[pyclass]
12
+ pub struct RustBlockValidator;
13
+
14
+ #[pymethods]
15
+ impl RustBlockValidator {
16
+ #[new]
17
+ fn new() -> Self {
18
+ RustBlockValidator
19
+ }
20
+
21
+ /// Verify a block hash matches its header contents.
22
+ ///
23
+ /// `header_json` — JSON-encoded block header
24
+ /// `expected_hash` — the hash claimed by the block
25
+ ///
26
+ /// Returns `true` if SHA-256(header_json) == expected_hash.
27
+ #[staticmethod]
28
+ fn verify_block_hash(header_json: &str, expected_hash: &str) -> bool {
29
+ let hash = Sha256::digest(header_json.as_bytes());
30
+ hex::encode(hash) == expected_hash
31
+ }
32
+
33
+ /// Validate a chain of block hashes in parallel.
34
+ ///
35
+ /// `blocks` — list of (header_json, claimed_hash, prev_hash) tuples.
36
+ /// Returns a list of booleans — one per block.
37
+ ///
38
+ /// Checks:
39
+ /// 1. SHA-256(header) == claimed_hash
40
+ /// 2. prev_hash links correctly (sequential check)
41
+ #[staticmethod]
42
+ fn validate_chain(
43
+ py: Python<'_>,
44
+ blocks: Vec<(String, String, String)>,
45
+ ) -> Vec<bool> {
46
+ if blocks.is_empty() {
47
+ return vec![];
48
+ }
49
+
50
+ // Step 1: verify hashes in parallel
51
+ let hash_checks: Vec<bool> = py.allow_threads(|| {
52
+ blocks
53
+ .par_iter()
54
+ .map(|(header, claimed, _)| {
55
+ let hash = Sha256::digest(header.as_bytes());
56
+ hex::encode(hash) == *claimed
57
+ })
58
+ .collect()
59
+ });
60
+
61
+ // Step 2: verify chain linkage (sequential — inherently ordered)
62
+ let mut results = hash_checks;
63
+ for i in 1..blocks.len() {
64
+ let expected_prev = &blocks[i - 1].1; // previous block's hash
65
+ let actual_prev = &blocks[i].2; // this block's prev_hash
66
+ if expected_prev != actual_prev {
67
+ results[i] = false;
68
+ }
69
+ }
70
+
71
+ results
72
+ }
73
+
74
+ /// Check Proof-of-Work difficulty: does the block hash have the
75
+ /// required number of leading zero bits?
76
+ #[staticmethod]
77
+ fn check_pow_difficulty(block_hash: &str, difficulty: u32) -> bool {
78
+ let bytes = match hex::decode(block_hash) {
79
+ Ok(b) => b,
80
+ Err(_) => return false,
81
+ };
82
+
83
+ let mut leading_zeros = 0u32;
84
+ for byte in &bytes {
85
+ if *byte == 0 {
86
+ leading_zeros += 8;
87
+ } else {
88
+ leading_zeros += byte.leading_zeros();
89
+ break;
90
+ }
91
+ }
92
+
93
+ leading_zeros >= difficulty
94
+ }
95
+
96
+ /// Batch-validate transaction signatures within a block.
97
+ ///
98
+ /// `tx_data` — list of (message_bytes, signature_bytes, pubkey_bytes).
99
+ /// Returns the number of valid signatures.
100
+ #[staticmethod]
101
+ fn validate_tx_signatures(
102
+ py: Python<'_>,
103
+ tx_data: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>,
104
+ ) -> usize {
105
+ let results: Vec<bool> = py.allow_threads(|| {
106
+ use rayon::prelude::*;
107
+ tx_data
108
+ .par_iter()
109
+ .map(|(msg, sig, pk)| {
110
+ crate::signature::verify_single(msg, sig, pk)
111
+ })
112
+ .collect()
113
+ });
114
+ results.iter().filter(|&&v| v).count()
115
+ }
116
+ }
@@ -28,14 +28,46 @@ try {
28
28
  // Install Zexus Python package
29
29
  console.log('\n📦 Installing Zexus Python package...');
30
30
  try {
31
- execSync('pip3 install zexus', { stdio: 'inherit' });
31
+ // Install with "full" extras so blockchain/network/security features work out of the box.
32
+ // Use --user to avoid permission issues on global Python installs.
33
+ execSync('pip3 install --user "zexus[full]"', { stdio: 'inherit' });
32
34
  console.log('\n✓ Zexus Python package installed successfully');
33
35
  } catch (error) {
34
36
  console.error('\n❌ Failed to install Zexus Python package.');
35
- console.error('Please run manually: pip3 install zexus');
37
+ console.error('Please run manually: pip3 install --user "zexus[full]"');
36
38
  process.exit(1);
37
39
  }
38
40
 
41
+ // Best-effort: build/install Rust VM extension from bundled sources when available.
42
+ // This requires a Rust toolchain and may fail on systems without build tooling.
43
+ function hasCommand(cmd) {
44
+ try {
45
+ execSync(`${cmd} --version`, { stdio: 'ignore' });
46
+ return true;
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ const pkgRoot = path.resolve(__dirname, '..');
53
+ const cargoToml = path.join(pkgRoot, 'rust_core', 'Cargo.toml');
54
+
55
+ if (fs.existsSync(cargoToml) && hasCommand('cargo')) {
56
+ console.log('\n🦀 Rust toolchain detected — attempting to build zexus_core...');
57
+ try {
58
+ execSync('python3 -m pip install --user --upgrade maturin', { stdio: 'inherit' });
59
+ execSync(`python3 -m maturin develop -m "${cargoToml}" --release`, { stdio: 'inherit' });
60
+ execSync('python3 -c "import zexus_core; print(\"zexus_core OK\", zexus_core.version())"', { stdio: 'inherit' });
61
+ console.log('✓ Rust VM extension built and installed');
62
+ } catch (error) {
63
+ console.warn('\n⚠️ Rust VM build failed; continuing with pure-Python VM.');
64
+ console.warn(' To retry manually (from source repo):');
65
+ console.warn(' pip install maturin && maturin develop -m rust_core/Cargo.toml --release');
66
+ }
67
+ } else {
68
+ console.log('\nℹ️ Skipping Rust VM build (cargo not found or rust_core not bundled).');
69
+ }
70
+
39
71
  console.log('\n✅ Zexus installed successfully!\n');
40
72
  console.log('Get started:');
41
73
  console.log(' zexus --help # Show help');
@@ -4,7 +4,7 @@ Zexus Programming Language
4
4
  A declarative, intent-based programming language for modern applications.
5
5
  """
6
6
 
7
- __version__ = "1.7.2"
7
+ __version__ = "1.8.1"
8
8
  __author__ = "Ziver Labs"
9
9
  __email__ = "ziverofficial567@gmail.com"
10
10
 
@@ -1008,6 +1008,7 @@ class ExecutionAccelerator:
1008
1008
  """Execute a batch of transactions with acceleration.
1009
1009
 
1010
1010
  Execution priority:
1011
+ 0. **GIL-free native** — pure-Rust Rayon parallel (Phase 5, requires .zxc bytecode)
1011
1012
  1. **Multiprocess** — separate OS processes (true GIL-free parallelism)
1012
1013
  2. **Rust batched-GIL** — Rayon parallel groups, one GIL per group
1013
1014
  3. **Python ThreadPool** — fallback when neither is available
@@ -1015,6 +1016,32 @@ class ExecutionAccelerator:
1015
1016
  Sustains 1,800+ TPS with Rust alone, 10,000+ TPS with
1016
1017
  multiprocess + Rust stacked.
1017
1018
  """
1019
+ # ── Priority 0: GIL-free native Rust execution (Phase 5) ──
1020
+ # If transactions carry pre-compiled .zxc bytecode, execute
1021
+ # entirely in Rust with zero GIL acquisitions.
1022
+ if self.rust_bridge and self.rust_bridge.is_native:
1023
+ native_txs = [tx for tx in transactions if "bytecode" in tx]
1024
+ if native_txs:
1025
+ try:
1026
+ raw = self.rust_bridge.execute_batch_native(native_txs)
1027
+ if raw is not None:
1028
+ result = TxBatchResult(total=raw["total"])
1029
+ result.succeeded = raw["succeeded"]
1030
+ result.failed = raw["failed"]
1031
+ result.gas_used = raw["gas_used"]
1032
+ result.elapsed = raw["elapsed_secs"]
1033
+ import json as _json
1034
+ result.receipts = [
1035
+ _json.loads(r) if isinstance(r, str) else r
1036
+ for r in raw.get("receipts", [])
1037
+ ]
1038
+ self._total_calls += raw["total"]
1039
+ self._accelerated_calls += raw["total"]
1040
+ self._total_time += raw["elapsed_secs"]
1041
+ return result
1042
+ except Exception as exc:
1043
+ logger.warning("GIL-free native batch failed, falling back: %s", exc)
1044
+
1018
1045
  # ── Priority 1: Multiprocess executor ─────────────────────
1019
1046
  if self.mp_executor:
1020
1047
  try: