rtvm_interpreter/instructions/
data.rs1use crate::{
2 gas::{BASE, DATA_LOAD_GAS, VERYLOW},
3 instructions::utility::read_u16,
4 interpreter::Interpreter,
5 primitives::U256,
6 Host,
7};
8
9pub fn data_load<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
10 require_eof!(interpreter);
11 gas!(interpreter, DATA_LOAD_GAS);
12 pop_top!(interpreter, offset);
13
14 let offset_usize = as_usize_saturated!(offset);
15
16 let slice = interpreter
17 .contract
18 .bytecode
19 .eof()
20 .expect("eof")
21 .data_slice(offset_usize, 32);
22
23 let mut word = [0u8; 32];
24 word[..slice.len()].copy_from_slice(slice);
25
26 *offset = U256::from_be_bytes(word);
27}
28
29pub fn data_loadn<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
30 require_eof!(interpreter);
31 gas!(interpreter, VERYLOW);
32 let offset = unsafe { read_u16(interpreter.instruction_pointer) } as usize;
33
34 let slice = interpreter
35 .contract
36 .bytecode
37 .eof()
38 .expect("eof")
39 .data_slice(offset, 32);
40
41 let mut word = [0u8; 32];
42 word[..slice.len()].copy_from_slice(slice);
43
44 push_b256!(interpreter, word.into());
45
46 interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(2) };
48}
49
50pub fn data_size<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
51 require_eof!(interpreter);
52 gas!(interpreter, BASE);
53 let data_size = interpreter.eof().expect("eof").header.data_size;
54
55 push!(interpreter, U256::from(data_size));
56}
57
58pub fn data_copy<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
59 require_eof!(interpreter);
60 gas!(interpreter, VERYLOW);
61 pop!(interpreter, mem_offset, offset, size);
62
63 let size = as_usize_or_fail!(interpreter, size);
65 if size == 0 {
67 return;
68 }
69 let mem_offset = as_usize_or_fail!(interpreter, mem_offset);
71 resize_memory!(interpreter, mem_offset, size);
72
73 let offset = as_usize_saturated!(offset);
74 let data = interpreter.contract.bytecode.eof().expect("EOF").data();
75
76 interpreter
78 .shared_memory
79 .set_data(mem_offset, offset, size, data);
80}
81
82#[cfg(test)]
83mod test {
84 use rtvm_primitives::{b256, bytes, Bytecode, Bytes, Eof, PragueSpec};
85
86 use super::*;
87 use crate::{
88 opcode::{make_instruction_table, DATACOPY, DATALOAD, DATALOADN, DATASIZE},
89 DummyHost, Gas, Interpreter,
90 };
91
92 fn dummy_eof(code_bytes: Bytes) -> Bytecode {
93 let bytes = bytes!("ef000101000402000100010400000000800000fe");
94 let mut eof = Eof::decode(bytes).unwrap();
95
96 eof.body.data_section =
97 bytes!("000000000000000000000000000000000000000000000000000000000000000102030405");
98 eof.header.data_size = eof.body.data_section.len() as u16;
99
100 eof.header.code_sizes[0] = code_bytes.len() as u16;
101 eof.body.code_section[0] = code_bytes;
102 Bytecode::Eof(eof)
103 }
104
105 #[test]
106 fn dataload_dataloadn() {
107 let table = make_instruction_table::<_, PragueSpec>();
108 let mut host = DummyHost::default();
109 let eof = dummy_eof(Bytes::from([
110 DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN,
111 0x00, 36, DATASIZE,
112 ]));
113
114 let mut interp = Interpreter::new_bytecode(eof);
115 interp.gas = Gas::new(10000);
116
117 interp.stack.push(U256::from(0)).unwrap();
119 interp.step(&table, &mut host);
120 assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]);
121 interp.stack.pop().unwrap();
122
123 interp.step(&table, &mut host);
125 assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]);
126 interp.stack.pop().unwrap();
127
128 interp.stack.push(U256::from(35)).unwrap();
130 interp.step(&table, &mut host);
131 assert_eq!(
132 interp.stack.data(),
133 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
134 );
135 interp.stack.pop().unwrap();
136
137 interp.step(&table, &mut host);
139 assert_eq!(
140 interp.stack.data(),
141 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
142 );
143 interp.stack.pop().unwrap();
144
145 interp.stack.push(U256::from(36)).unwrap();
147 interp.step(&table, &mut host);
148 assert_eq!(interp.stack.data(), &vec![U256::ZERO]);
149 interp.stack.pop().unwrap();
150
151 interp.step(&table, &mut host);
153 assert_eq!(interp.stack.data(), &vec![U256::ZERO]);
154 interp.stack.pop().unwrap();
155
156 interp.step(&table, &mut host);
158 assert_eq!(interp.stack.data(), &vec![U256::from(36)]);
159 }
160
161 #[test]
162 fn data_copy() {
163 let table = make_instruction_table::<_, PragueSpec>();
164 let mut host = DummyHost::default();
165 let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY]));
166
167 let mut interp = Interpreter::new_bytecode(eof);
168 interp.gas = Gas::new(10000);
169
170 interp.stack.push(U256::from(32)).unwrap();
173 interp.stack.push(U256::from(0)).unwrap();
174 interp.stack.push(U256::from(0)).unwrap();
175 interp.step(&table, &mut host);
176 assert_eq!(
177 interp.shared_memory.context_memory(),
178 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
179 );
180
181 interp.stack.push(U256::from(2)).unwrap();
184 interp.stack.push(U256::from(35)).unwrap();
185 interp.stack.push(U256::from(1)).unwrap();
186 interp.step(&table, &mut host);
187 assert_eq!(
188 interp.shared_memory.context_memory(),
189 &bytes!("0005000000000000000000000000000000000000000000000000000000000001")
190 );
191
192 interp.stack.push(U256::from(2)).unwrap();
195 interp.stack.push(U256::from(37)).unwrap();
196 interp.stack.push(U256::from(1)).unwrap();
197 interp.step(&table, &mut host);
198 assert_eq!(
199 interp.shared_memory.context_memory(),
200 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
201 );
202
203 interp.stack.push(U256::from(0)).unwrap();
206 interp.stack.push(U256::from(37)).unwrap();
207 interp.stack.push(U256::from(1)).unwrap();
208 interp.step(&table, &mut host);
209 assert_eq!(
210 interp.shared_memory.context_memory(),
211 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
212 );
213 }
214}