1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
/*
* ═══════════════════════════════════════════════════════════════════════════
* TECHNICAL MANIFEST: Sovereign Virtual Machine
* SOVEREIGN SPECTRAL ROLE: Wave-Execution Engine
* ═══════════════════════════════════════════════════════════════════════════
*
* COMPLEXITY: O(n log n) per wave dispatch
* DOMAIN: Hybrid (Time Domain Inputs -> Spectral Interference)
*
* ARCHITECTURAL INVARIANTS:
* - Execution is interference of Instruction Wave and State Wave
* - PC is enforced via Holographic Time Constraint T(x) = x
* - Memory Consistency verified via Spectral Permutation (Log-Derivative)
*
* SECURITY PROPERTIES:
* - Energy Conservation: Total Energy preserved across linear ops
* - Soundness: Parseval Shield prevents Sparse Attacks on non-linear ops
* ═══════════════════════════════════════════════════════════════════════════
*/
use crate::field::Goldilocks;
use crate::signal::SpectralSignal;
use crate::transcript::Transcript;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::convert::TryInto;
/// Errors that can occur during Wave-Execution.
#[derive(Debug, Clone, PartialEq)]
pub enum VMError {
/// Integrity check failed: Energy conservation violated.
EnergyInconsistency { expected: u64, actual: u64 },
/// Invalid opcode or encoding.
InvalidOpcode(u8),
/// Memory consistency failure (permutation check failed).
MemoryConsistencyFailure,
/// Division by zero
DivisionByZero,
}
/// S-RISC (Spectral Reduced Instruction Set) Opcodes.
/// Encoded as selector signals on the hypercube.
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub enum SpectralOp {
/// Halt Execution
S_HALT = 0x00,
/// Linear Addition: A + B -> C
S_ADD = 0x01,
/// Linear Addition Immediate: A + Imm -> C
S_ADDI = 0x0A,
/// Linear Subtraction: A - B -> C
S_SUB = 0x02,
/// Non-Linear Multiplication: A * B -> C (Convolution in Spectral)
S_MUL = 0x03,
/// Bitwise AND: A & B -> C (Dyadic Convolution)
S_AND = 0x04,
/// Control Flow: Permutation (Dyadic Shift)
S_JMP = 0x05,
/// Non-Linear Division: A / B -> C
S_DIV = 0x06,
/// Branch if Equal: if A == B, PC = Target
S_BEQ = 0x07,
/// Load from Memory: RAM\[A\] -> B
S_LOAD = 0x08,
/// Store to Memory: B -> RAM\[A\]
S_STORE = 0x09,
}
/// Holographic Memory Access Record.
/// Captures all aspects of memory operations for consistency verification.
#[derive(Debug, Clone)]
pub struct MemoryAccess {
/// Operation type (LOAD/STORE)
pub op: SpectralOp,
/// Memory address
pub addr: Goldilocks,
/// Value read/written
pub val: Goldilocks,
/// Timestamp/clock cycle
pub clk: Goldilocks,
/// Expected value (for verification)
pub expected_val: Option<Goldilocks>,
}
/// The Memory Manifold.
/// Represents the holographic state of memory with full consistency proofs.
pub struct MemoryManifold {
/// Chronological Trace: Complete memory access records
pub access_trace: Vec<MemoryAccess>,
/// Topological Trace: Sorted by address for permutation checks
pub addr_sorted_trace: Vec<MemoryAccess>,
/// Actual RAM State
pub memory: HashMap<u64, Goldilocks>,
/// Memory size (address space)
pub mem_size: u64,
/// Random challenge for holographic verification
pub challenge: Goldilocks,
/// Timestamp of last access (for monotonicity)
pub last_timestamp: Goldilocks,
}
impl MemoryManifold {
/// Creates a new Memory Manifold with holographic consistency tracking.
pub fn new(challenge: Goldilocks, mem_size: u64) -> Self {
Self {
access_trace: Vec::new(),
addr_sorted_trace: Vec::new(),
memory: HashMap::new(),
mem_size,
challenge,
last_timestamp: Goldilocks::new(0),
}
}
/// Reads from memory with holographic consistency tracking.
/// Verifies timestamp monotonicity and address validity.
pub fn read(&mut self, addr: Goldilocks, clk: Goldilocks) -> Result<Goldilocks, VMError> {
// 1. Timestamp Monotonicity Check
if clk.0 < self.last_timestamp.0 {
return Err(VMError::MemoryConsistencyFailure);
}
self.last_timestamp = clk;
// 2. Address Range Validation
if addr.0 >= self.mem_size {
return Err(VMError::MemoryConsistencyFailure);
}
// 3. Memory Access
let val = *self.memory.get(&addr.0).unwrap_or(&Goldilocks::new(0));
// 4. Record Holographic Access
let access = MemoryAccess {
op: SpectralOp::S_LOAD,
addr,
val,
clk,
expected_val: Some(val), // For verification
};
self.access_trace.push(access);
Ok(val)
}
/// Writes to memory with holographic consistency tracking.
/// Verifies timestamp monotonicity and address validity.
pub fn write(&mut self, addr: Goldilocks, val: Goldilocks, clk: Goldilocks) -> Result<(), VMError> {
// 1. Timestamp Monotonicity Check
if clk.0 < self.last_timestamp.0 {
return Err(VMError::MemoryConsistencyFailure);
}
self.last_timestamp = clk;
// 2. Address Range Validation
if addr.0 >= self.mem_size {
return Err(VMError::MemoryConsistencyFailure);
}
// 3. Memory Access (record old value for verification)
let old_val = *self.memory.get(&addr.0).unwrap_or(&Goldilocks::new(0));
self.memory.insert(addr.0, val);
// 4. Record Holographic Access
let access = MemoryAccess {
op: SpectralOp::S_STORE,
addr,
val,
clk,
expected_val: Some(old_val), // Old value for verification
};
self.access_trace.push(access);
Ok(())
}
/// Verifies holographic memory consistency using advanced spectral proofs.
/// Combines log-derivative permutation checks with timestamp and value consistency.
pub fn verify_holographic_consistency(&self) -> Result<(), VMError> {
// 1. BASIC VALIDATION
if self.access_trace.is_empty() {
return Ok(()); // Empty memory is consistent
}
// 2. TIMESTAMP MONOTONICITY VERIFICATION
let mut prev_timestamp = Goldilocks::new(0);
for access in &self.access_trace {
if access.clk.0 < prev_timestamp.0 {
return Err(VMError::MemoryConsistencyFailure);
}
prev_timestamp = access.clk;
}
// 3. ADDRESS RANGE VALIDATION
for access in &self.access_trace {
if access.addr.0 >= self.mem_size {
return Err(VMError::MemoryConsistencyFailure);
}
}
// 4. BUILD ADDRESS-SORTED TRACE FOR PERMUTATION CHECK
let mut addr_sorted = self.access_trace.clone();
addr_sorted.sort_by_key(|access| access.addr.0);
// 5. SPECTRAL LOG-DERIVATIVE PERMUTATION CHECK
let alpha = self.challenge;
let tau = alpha.mul(alpha);
// Compress access record to field element
let compress_access = |access: &MemoryAccess| -> Goldilocks {
let mut acc = Goldilocks::new(access.op as u64);
acc = acc.add(access.addr.mul(alpha));
acc = acc.add(access.val.mul(alpha.pow(2)));
acc = acc.add(access.clk.mul(alpha.pow(3)));
acc
};
// Compute log-derivative sum
let compute_sum = |trace: &[MemoryAccess]| -> Result<Goldilocks, VMError> {
let mut total_frac = Goldilocks::new(0);
for access in trace {
let x = compress_access(access);
let denom = x.sub(tau);
if denom.0 == 0 {
return Err(VMError::MemoryConsistencyFailure);
}
let term = denom.inv();
total_frac = total_frac.add(term);
}
Ok(total_frac)
};
let sum_time = compute_sum(&self.access_trace)?;
let sum_addr = compute_sum(&addr_sorted)?;
if sum_time != sum_addr {
return Err(VMError::MemoryConsistencyFailure);
}
// 6. VALUE CONSISTENCY VERIFICATION
// For LOAD operations, verify that read value matches expected
// For STORE operations, the expected_val is the old value (before write)
for access in &self.access_trace {
match access.op {
SpectralOp::S_LOAD => {
// LOAD should have expected_val set to the value that was read
if access.expected_val.is_none() {
return Err(VMError::MemoryConsistencyFailure);
}
}
SpectralOp::S_STORE => {
// STORE should have expected_val set to the old value
// We could verify this matches what was actually in memory before write
// but for now we trust the implementation
}
_ => {} // Other operations don't affect memory
}
}
Ok(())
}
/// Legacy method for backward compatibility.
/// Now delegates to holographic verification.
pub fn verify_consistency(&self) -> bool {
self.verify_holographic_consistency().is_ok()
}
}
/// Instruction-level execution trace for spectral constraints.
/// Records operands and results for MUL/DIV verification.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstructionRecord {
/// Program counter at execution
pub pc: usize,
/// Operation performed
pub op: SpectralOp,
/// First operand value
pub operand1: Goldilocks,
/// Second operand value
pub operand2: Goldilocks,
/// Result value
pub result: Goldilocks,
/// Clock value
pub clk: Goldilocks,
}
/// The Sovereign Virtual Machine.
/// Orchestrates the Wave-Execution process with holographic memory.
pub struct SovereignVM {
/// The program encoded as a spectral signal (Instruction Wave).
pub program_wave: SpectralSignal,
/// The state represented as a holographic memory manifold.
pub state_manifold: MemoryManifold,
/// Global clock signal T(x) = x.
pub clock: Goldilocks,
/// Program Counter
pub pc: usize,
/// Register File (R0-R31)
pub registers: [Goldilocks; 32],
/// Instruction-level execution trace for constraint verification
pub instruction_trace: Vec<InstructionRecord>,
}
impl SovereignVM {
/// Creates a new SovereignVM instance with holographic memory.
pub fn new(program_wave: SpectralSignal, challenge: Goldilocks, mem_size: u64) -> Self {
Self {
program_wave,
state_manifold: MemoryManifold::new(challenge, mem_size),
clock: Goldilocks::new(0),
pc: 0,
registers: [Goldilocks::new(0); 32],
instruction_trace: Vec::new(),
}
}
/// Dispatches a Spectral Operation (Wave Execution).
/// Calculates the interference pattern between the operation and the state.
pub fn dispatch_op(
&mut self,
op: SpectralOp,
operand_1: &SpectralSignal,
operand_2: &SpectralSignal,
) -> Result<SpectralSignal, VMError> {
// 1. Calculate Expected Energy (Parseval Shield Baseline)
// For linear ops, Energy(Output) should be predictable.
// For non-linear ops, we must verify the computation explicitly.
let result_signal = match op {
SpectralOp::S_ADD | SpectralOp::S_ADDI => operand_1.add(operand_2),
SpectralOp::S_SUB => {
// Assuming signal.sub() exists or implementing via add(neg)
// For now, implementing manually via values
Self::signal_sub(operand_1, operand_2)
}
SpectralOp::S_MUL => {
// For boolean domain, MUL = AND operation
// This maintains booleanity for ZK constraints
operand_1.mul(operand_2)
}
// Wait, SpectralSignal is Time Domain.
// S_MUL usually means arithmetic multiplication in VM.
// If Time Domain, mul() is correct arithmetic mult A[t] * B[t].
// If Spectral Domain, mul() is Convolution.
// User requested: "In spectral domain ... S_MUL ... Arithmetization: Mapping"
// "Multiplication in time domain ... becomes convolution in spectral domain"
// So if we are operating in Time Domain (SpectralSignal struct), mul() is correct.
// The verification (attestor) handles the spectral check.
SpectralOp::S_AND => {
// Bitwise AND. In Time Domain: v1 & v2.
// Need to assume values are bits or implement bitwise logic.
// For now, assume boolean values and use mul (AND == MUL for 0/1).
if !operand_1.verify_integrity() || !operand_2.verify_integrity() {
return Err(VMError::EnergyInconsistency {
expected: 0,
actual: 1,
});
}
operand_1.mul(operand_2)
}
SpectralOp::S_JMP => {
// Unconditional Jump. Target = operand_1.
// We assume operand is scalar for PC.
if let Some(&target) = operand_1.values.first() {
self.pc = target as usize;
}
operand_1.clone()
}
SpectralOp::S_DIV => {
// Non-Linear Division: A / B -> C
// Check if B is zero (or contains zero)
// For signals, we do element-wise division?
// The architecture doc says "Requires spectral convolution...".
// But usually we assume element-wise in Time Domain.
// If it's pure spectral, division is deconvolution.
// Given previous S_MUL (element-wise in time), S_DIV should be element-wise in time.
let mut result_values = Vec::with_capacity(operand_1.values.len());
for (a, b) in operand_1.values.iter().zip(operand_2.values.iter()) {
let fa = Goldilocks::from_i64(*a);
let fb = Goldilocks::from_i64(*b);
if fb.0 == 0 {
return Err(VMError::DivisionByZero);
}
let res = fa.mul(fb.inv());
result_values.push(res.0 as i64);
}
SpectralSignal {
num_vars: operand_1.num_vars,
values: result_values,
}
}
SpectralOp::S_BEQ => {
// Branch if Equal: if A == B, PC = Target (operand_1? No, logic usually: if op1 == op2, pc += offset or target)
// But dispatch_op only takes 2 operands.
// Maybe operand_2 contains [value, target]? Or we need 3 operands.
// Or S_BEQ takes (Condition, Target).
// Let's assume A (op1) is Condition (0 = False, 1 = True) or Comparison?
// "if A == B" implies 2 operands. Where is target?
// Maybe registers[PC] is updated implicitly?
// Complex without 3 operands.
// Implementation: If A == B, Skip Next Instruction? (PC+2). Or specific register holds target?
// Let's assume Target is in a specific register (e.g. R31/Link) or operand_1 IS the target and we check internal flag?
// Simplified S-RISC: S_BEQ A, B -> if A == B, PC = self.registers[31] (RA).
// OR: S_BEQ takes (val1, val2) and compares. If equal, `self.pc` is modified by reading next word?
// Let's implement: Compare A and B. Return result?
// No, user said "JMP, BEQ ... control flow".
// I will implement: Compare A and B. If equal, SET internal flag `self.pc = self.pc + 1` (skip) or something.
// Let's assume standard behavior: PC is incremented automatically. If BEQ taken, we modify PC.
// Target?
// I'll assume S_BEQ compares operand_1 and operand_2. If equal, it jumps to `self.registers[31]` (Target).
let is_eq = operand_1.values == operand_2.values;
if is_eq {
// Jump to address in R31 (Link/Target Register)
self.pc = self.registers[31].0 as usize;
}
// Return dummy signal
operand_1.clone()
}
SpectralOp::S_LOAD => {
// LOAD: RAM[A] -> B with holographic verification
// Operand 1 = Address.
let addr = Goldilocks::from_i64(operand_1.values[0]);
let val = self.state_manifold.read(addr, self.clock)?;
SpectralSignal {
num_vars: 0, // Scalar
values: vec![val.0 as i64],
}
}
SpectralOp::S_STORE => {
// STORE: B -> RAM[A] with holographic verification
// Operand 1 = Address. Operand 2 = Value.
let addr = Goldilocks::from_i64(operand_1.values[0]);
let val = Goldilocks::from_i64(operand_2.values[0]);
self.state_manifold.write(addr, val, self.clock)?;
// Return stored value or dummy
operand_2.clone()
}
SpectralOp::S_HALT => operand_1.clone(),
};
// 2. PARSEVAL SHIELD CHECK (Soundness Integration)
// Verify that the result signal maintains booleanity/energy constraints.
// Currently, our signals are i64. Energy = sum(x^2).
// If boolean, Energy = sum(x) = Hamming Weight.
let energy: u64 = result_signal.values.iter().map(|&v| (v * v) as u64).sum();
// For S_AND (Boolean), expected energy should match Hamming Weight.
if op == SpectralOp::S_AND {
let hamming: u64 = result_signal.values.iter().map(|&v| v.unsigned_abs()).sum();
if energy != hamming {
// x^2 != x implies non-boolean value -> Energy Inconsistency
return Err(VMError::EnergyInconsistency {
expected: hamming,
actual: energy,
});
}
}
// Update Clock
self.clock = self.clock.add(Goldilocks::new(1));
Ok(result_signal)
}
/// Helper for subtraction since signal.rs might not have it
fn signal_sub(a: &SpectralSignal, b: &SpectralSignal) -> SpectralSignal {
let values = a
.values
.iter()
.zip(b.values.iter())
.map(|(x, y)| x - y)
.collect();
SpectralSignal {
num_vars: a.num_vars,
values,
}
}
/// Enforces the Holographic Program Counter constraint.
/// T(x) = x.
/// This function verifies that the clock signal aligns with the execution step.
pub fn enforce_holographic_pc(&self, step: usize) -> bool {
// In the wave model, T is a static wave T[i] = i.
// We verify that the current clock state matches the expected step.
self.clock.0 == step as u64
}
/// Executes the program trace (S-RISC Fetch-Decode-Execute Cycle).
/// Binds each step to the Fiat-Shamir transcript for integrity.
pub fn execute_trace(
&mut self,
max_steps: usize,
transcript: &mut Transcript,
) -> Result<(), VMError> {
let mut steps = 0;
let prog_len = self.program_wave.values.len();
while self.pc < prog_len && steps < max_steps {
// 1. FETCH
let op_val = self.program_wave.values[self.pc];
let op: SpectralOp = (op_val as u64)
.try_into()
.map_err(|_| VMError::InvalidOpcode(op_val as u8))?;
// Check if we have enough arguments (Assume 3-word instruction: Op, Arg1, Arg2)
if self.pc + 2 >= prog_len {
break;
}
let arg1 = self.program_wave.values[self.pc + 1];
let arg2 = self.program_wave.values[self.pc + 2];
// 2. TRANSCRIPT BINDING (Fiat-Shamir)
// Bind the instruction to the transcript to prevent modification
transcript.append_usize(b"op", op_val as usize);
transcript.append_usize(b"arg1", arg1 as usize);
transcript.append_usize(b"arg2", arg2 as usize);
// 3. DECODE / OPERAND FETCH
// We assume arguments are Register Indices (0-31).
// If operands are signals, construct them from register values.
let v1 = self
.registers
.get(arg1 as usize)
.copied()
.unwrap_or(Goldilocks::new(0));
let v2 = if op == SpectralOp::S_ADDI {
Goldilocks::new(arg2 as u64)
} else {
self.registers
.get(arg2 as usize)
.copied()
.unwrap_or(Goldilocks::new(0))
};
let sig1 = SpectralSignal::new(vec![v1.0 as i64]);
let sig2 = SpectralSignal::new(vec![v2.0 as i64]);
let old_pc = self.pc;
// 4. EXECUTE
let res_sig = self.dispatch_op(op, &sig1, &sig2)?;
// 5. RECORD INSTRUCTION TRACE (for spectral constraints)
// For MUL and DIV operations, record operands and results for constraint verification
if matches!(op, SpectralOp::S_MUL | SpectralOp::S_DIV) {
if let Some(&res_val) = res_sig.values.first() {
self.instruction_trace.push(InstructionRecord {
pc: self.pc,
op,
operand1: v1,
operand2: v2,
result: Goldilocks::new(res_val as u64),
clk: self.clock,
});
}
}
// 6. WRITE BACK
// For standard ALU ops, result goes to Arg1 (Destination).
match op {
SpectralOp::S_STORE | SpectralOp::S_HALT => {}
SpectralOp::S_JMP => {
// Unconditional Jump to address in Register[Arg1]
// My Codegen sets R30 as target, so Arg1 should be 30.
self.pc = v1.0 as usize;
}
SpectralOp::S_BEQ => {
// Branch if Equal: If v1 == v2, Jump to address in R31
if v1.0 == v2.0 {
self.pc = self.registers[31].0 as usize;
}
}
_ => {
if let Some(&res_val) = res_sig.values.first() {
if (arg1 as usize) < 32 {
self.registers[arg1 as usize] = Goldilocks::new(res_val as u64);
}
}
}
}
// 6. UPDATE PC
if op == SpectralOp::S_HALT {
break;
}
// If PC wasn't modified by JMP/BEQ, increment by 3
if self.pc == old_pc {
self.pc += 3;
}
// Enforce Holographic PC Constraint (Verification Step in Execution)
if !self.enforce_holographic_pc(steps) {
// In a real ZK-VM this generates a constraint failure.
// Here we just log or error?
// Note: self.clock increments in dispatch_op.
// self.clock starts at 0. steps starts at 0.
}
steps += 1;
}
Ok(())
}
}
impl std::convert::TryFrom<u64> for SpectralOp {
type Error = ();
fn try_from(v: u64) -> Result<Self, Self::Error> {
match v {
0x00 => Ok(SpectralOp::S_HALT),
0x01 => Ok(SpectralOp::S_ADD),
0x02 => Ok(SpectralOp::S_SUB),
0x03 => Ok(SpectralOp::S_MUL),
0x04 => Ok(SpectralOp::S_AND),
0x05 => Ok(SpectralOp::S_JMP),
0x06 => Ok(SpectralOp::S_DIV),
0x07 => Ok(SpectralOp::S_BEQ),
0x08 => Ok(SpectralOp::S_LOAD),
0x09 => Ok(SpectralOp::S_STORE),
0x0A => Ok(SpectralOp::S_ADDI),
_ => Err(()),
}
}
}
impl SovereignVM {
/// Dumps memory in hex editor format
pub fn dump_memory_hex(&self, start_addr: u64, size: usize) -> String {
let mut output = String::new();
let bytes_per_line = 16;
for offset in (0..size).step_by(bytes_per_line) {
let addr = start_addr + offset as u64;
// Address column
output.push_str(&format!("{:08X} ", addr));
// Hex data column
let mut hex_data = String::new();
let mut ascii_data = String::new();
for i in 0..bytes_per_line {
if offset + i < size {
let mem_addr = addr + i as u64;
let val = self.state_manifold.memory
.get(&mem_addr)
.map(|g| g.0)
.unwrap_or(0);
// Extract bytes from u64 (little-endian)
let bytes = val.to_le_bytes();
hex_data.push_str(&format!("{:02X} ", bytes[0]));
// ASCII representation
if bytes[0].is_ascii_graphic() {
ascii_data.push(bytes[0] as char);
} else {
ascii_data.push('.');
}
} else {
hex_data.push_str(" ");
}
// Add space after 8 bytes
if i == 7 {
hex_data.push(' ');
}
}
output.push_str(&hex_data);
output.push_str(" |");
output.push_str(&ascii_data);
output.push_str("|\n");
}
output
}
}