zkmemory/
lib.rs

1//! This crate provides a simple RAM machine for use in the zkVM
2#![cfg_attr(not(feature = "std"), no_std)]
3#![deny(
4    unused,
5    warnings,
6    future_incompatible,
7    nonstandard_style,
8    rust_2018_idioms,
9    missing_docs,
10    unused_imports
11)]
12#![forbid(unsafe_code)]
13
14/// Base trait for generic type
15pub mod base;
16/// Define all configuration of [StateMachine](crate::machine::StateMachine) and [RawMemory](crate::memory::RawMemory)
17pub mod config;
18/// Define all errors of [StateMachine](crate::machine::StateMachine) and [RawMemory](crate::memory::RawMemory)
19pub mod error;
20/// A state machine with two instructions [Write](crate::machine::Instruction::Write) and [Read](crate::machine::Instruction::Read).
21/// This machine have configurable word size and address size. This crate provide following aliases:
22/// - [StateMachine256](crate::machine::StateMachine256) with 256 bits address and word size
23/// - [StateMachine64](crate::machine::StateMachine64) with 64 bits address and word size
24/// - [StateMachine32](crate::machine::StateMachine32) with 32 bits address and word size
25pub mod machine;
26/// Raw memory as a key-value store base on [RBTree](rbtree::RBTree) that mapping address to value
27pub mod memory;
28
29#[cfg(test)]
30mod tests {
31    use crate::base::{Base, UsizeConvertible, U256};
32    use crate::config::{ConfigArgs, DefaultConfig};
33    use crate::machine::{
34        RAMMachine, RegisterMachine, StackMachine, StateMachine256, StateMachine32,
35    };
36
37    #[test]
38    fn sm256_write_read_one_cell() {
39        let mut sm = StateMachine256::new(DefaultConfig::default());
40        let chunk = U256::from_bytes([5u8; 32]);
41        assert!(sm.write(sm.base_address(), chunk).is_ok());
42        let read_result = sm.read(sm.base_address());
43        assert!(read_result.is_ok());
44        assert_eq!(read_result.unwrap(), chunk);
45    }
46
47    #[test]
48    fn sm256_read_empty_cell() {
49        let mut sm = StateMachine256::new(DefaultConfig::default());
50        let chunk = U256::from_bytes([0u8; 32]);
51        let read_result = sm.read(sm.base_address());
52        assert!(read_result.is_ok());
53        assert_eq!(read_result.unwrap(), chunk);
54    }
55
56    #[test]
57    fn sm256_write_one_cell_read_two_cell() {
58        let mut sm = StateMachine256::new(DefaultConfig::default());
59        let chunk_1 = U256::from_bytes([5u8; 32]);
60        let chunk_2 = U256::from_bytes([10u8; 32]);
61        let base_addr = sm.base_address().to_usize();
62
63        let expected: [u8; 32] = [[5u8; 17].as_slice(), [10u8; 15].as_slice()]
64            .concat()
65            .try_into()
66            .unwrap();
67
68        assert!(sm.write(U256::from_usize(base_addr), chunk_1).is_ok());
69        assert!(sm.write(U256::from_usize(base_addr + 32), chunk_2).is_ok());
70        let read_result = sm.read(U256::from_usize(base_addr + 15));
71        assert!(read_result.is_ok());
72        assert_eq!(read_result.unwrap(), U256::from_bytes(expected));
73    }
74
75    #[test]
76    fn sm256_write_two_cell_read_one_cell() {
77        let mut sm = StateMachine256::new(DefaultConfig::default());
78        let base_addr = sm.base_address().to_usize();
79
80        let chunk = U256::from_bytes([1u8; 32]);
81        assert!(sm.write(U256::from_usize(base_addr + 23), chunk).is_ok());
82        let expected_lo: [u8; 32] = [[0u8; 23].as_slice(), [1u8; 9].as_slice()]
83            .concat()
84            .try_into()
85            .unwrap();
86        let expected_hi: [u8; 32] = [[1u8; 23].as_slice(), [0u8; 9].as_slice()]
87            .concat()
88            .try_into()
89            .unwrap();
90
91        let read_result_lo = sm.read(U256::from_usize(base_addr));
92        let read_result_hi = sm.read(U256::from_usize(base_addr + 32));
93
94        assert!(read_result_lo.is_ok());
95        assert!(read_result_hi.is_ok());
96        assert_eq!(read_result_lo.unwrap(), U256::from_bytes(expected_lo));
97        assert_eq!(read_result_hi.unwrap(), U256::from_bytes(expected_hi));
98    }
99
100    #[test]
101    #[should_panic]
102    fn sm32_read_prohibited_cell() {
103        let mut sm = StateMachine32::new(DefaultConfig::default());
104        assert_eq!(sm.read(64).unwrap(), 0u32);
105    }
106
107    #[test]
108    fn sm32_read_empty_cell() {
109        let mut sm = StateMachine32::new(DefaultConfig::default());
110        assert_eq!(sm.read(sm.base_address() + 64).unwrap(), 0u32);
111    }
112
113    #[test]
114    fn sm32_write_read_one_cell() {
115        let mut sm = StateMachine32::new(DefaultConfig::default());
116        let chunk = 12u32;
117        assert!(sm.write(sm.base_address(), chunk).is_ok());
118        assert_eq!(sm.read(sm.base_address()).unwrap(), 12u32);
119    }
120
121    #[test]
122    fn sm32_write_one_cell_read_two_cells() {
123        let mut sm = StateMachine32::new(DefaultConfig::default());
124        let chunk_1 = u32::from_bytes([7u8; 4]);
125        let chunk_2 = u32::from_bytes([10u8; 4]);
126        assert!(sm.write(sm.base_address(), chunk_1).is_ok());
127        assert!(sm.write(sm.base_address() + 4u32, chunk_2).is_ok());
128        assert_eq!(
129            sm.read(sm.base_address() + 3u32).unwrap(),
130            u32::from_be_bytes([7u8, 10, 10, 10])
131        );
132    }
133
134    #[test]
135    fn sm32_write_two_cells_read_one_cells() {
136        let mut sm = StateMachine32::new(DefaultConfig::default());
137        let chunk = u32::from_bytes([3u8; 4]);
138        assert!(sm.write(sm.base_address() + 2u32, chunk).is_ok());
139        assert_eq!(sm.read(sm.base_address()).unwrap(), 0x00000303u32);
140        assert_eq!(sm.read(sm.base_address() + 4u32).unwrap(), 0x03030000u32);
141    }
142
143    #[test]
144    fn u256_test() {
145        let chunk_1 = U256::from_bytes([9u8; 32]);
146        let chunk_2 = U256::from_usize(10);
147        assert_eq!(chunk_1.to_bytes(), [9u8; 32]);
148        assert_eq!(U256::zero(), U256::from_bytes([0u8; 32]));
149        assert_eq!(chunk_2.to_usize(), 10 as usize);
150        assert!(!chunk_1.is_zero());
151    }
152
153    #[test]
154    /// The testcases above already covered Add, Sub and Rem. This test case covers Div
155    fn u256_arithmetic_test() {
156        let chunk_1 = U256::from_bytes([34u8; 32]);
157        let chunk_2 = U256::from_bytes([17u8; 32]);
158        assert_eq!(chunk_1 / chunk_2, U256::from_usize(2));
159    }
160
161    #[test]
162    fn u32_test() {
163        let chunk_1 = u32::from_bytes([73u8; 4]);
164        let chunk_2 = u32::from_usize(103);
165        assert_eq!(chunk_1.to_bytes(), [73u8; 4]);
166        assert_eq!(u32::zero(), u32::from_bytes([0u8; 4]));
167        assert_eq!(chunk_2.to_usize(), 103 as usize);
168        assert!(!chunk_1.is_zero());
169    }
170
171    #[test]
172    fn u64_test() {
173        let chunk_1 = u64::from_bytes([15u8; 8]);
174        let chunk_2 = u64::from_usize(235);
175        assert_eq!(chunk_1.to_bytes(), [15u8; 8]);
176        assert_eq!(u64::zero(), u64::from_bytes([0u8; 8]));
177        assert_eq!(chunk_2.to_usize(), 235 as usize);
178        assert!(!chunk_1.is_zero());
179    }
180
181    #[test]
182    fn u32_stack_functional() {
183        let mut sm = StateMachine32::new(DefaultConfig::default());
184
185        assert!(sm.push(0x01020304).is_ok());
186        assert!(sm.push(0xaabbccdd).is_ok());
187        assert!(sm.stack_depth() == 2);
188
189        assert_eq!(sm.pop().unwrap(), 0xaabbccdd);
190        assert_eq!(sm.pop().unwrap(), 0x01020304);
191        assert!(sm.stack_depth() == 0);
192    }
193
194    #[test]
195    #[should_panic]
196    fn u32_stack_underflow() {
197        let mut sm = StateMachine32::new(DefaultConfig::default());
198        sm.pop().unwrap();
199    }
200
201    #[test]
202    #[should_panic]
203    fn u32_stack_overflow() {
204        let mut sm = StateMachine32::new(ConfigArgs {
205            head_layout: true,
206            stack_depth: 2,
207            no_register: 0,
208            buffer_size: 64,
209        });
210        assert!(sm.push(0x01020304).is_ok());
211        assert!(sm.push(0x01020304).is_ok());
212        assert!(sm.push(0x01020304).is_ok());
213        assert!(sm.push(0x01020304).is_ok());
214    }
215
216    #[test]
217    fn u32_register_functional() {
218        let mut sm = StateMachine32::new(DefaultConfig::default());
219
220        let r0 = sm.register(0).unwrap();
221        let r1 = sm.register(1).unwrap();
222
223        assert!(sm.set(r0, 0x01020304).is_ok());
224        assert!(sm.set(r1, 0xaabbccdd).is_ok());
225
226        assert_eq!(sm.get(r0).unwrap(), 0x01020304);
227        assert_eq!(sm.get(r1).unwrap(), 0xaabbccdd);
228
229        assert!(sm.mov(r0, r1).is_ok());
230
231        assert!(sm.get(r0).unwrap() == 0xaabbccdd);
232    }
233}