revm_interpreter/instructions/data.rs
1use crate::{
2 gas::{cost_per_word, BASE, DATA_LOAD_GAS, VERYLOW},
3 interpreter::Interpreter,
4 interpreter_types::{
5 EofData, Immediates, InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr,
6 },
7 Host,
8};
9use primitives::{B256, U256};
10
11pub fn data_load<WIRE: InterpreterTypes, H: Host + ?Sized>(
12 interpreter: &mut Interpreter<WIRE>,
13 _host: &mut H,
14) {
15 require_eof!(interpreter);
16 gas!(interpreter, DATA_LOAD_GAS);
17 popn_top!([], offset, interpreter);
18
19 let offset_usize = as_usize_saturated!(offset);
20
21 let slice = interpreter.bytecode.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<WIRE: InterpreterTypes, H: Host + ?Sized>(
30 interpreter: &mut Interpreter<WIRE>,
31 _host: &mut H,
32) {
33 require_eof!(interpreter);
34 gas!(interpreter, VERYLOW);
35 let offset = interpreter.bytecode.read_u16() as usize;
36
37 let slice = interpreter.bytecode.data_slice(offset, 32);
38
39 let mut word = [0u8; 32];
40 word[..slice.len()].copy_from_slice(slice);
41
42 push!(interpreter, B256::new(word).into());
43
44 // Add +2 to the instruction pointer to skip the offset
45 interpreter.bytecode.relative_jump(2);
46}
47
48pub fn data_size<WIRE: InterpreterTypes, H: Host + ?Sized>(
49 interpreter: &mut Interpreter<WIRE>,
50 _host: &mut H,
51) {
52 require_eof!(interpreter);
53 gas!(interpreter, BASE);
54
55 push!(interpreter, U256::from(interpreter.bytecode.data_size()));
56}
57
58pub fn data_copy<WIRE: InterpreterTypes, H: Host + ?Sized>(
59 interpreter: &mut Interpreter<WIRE>,
60 _host: &mut H,
61) {
62 require_eof!(interpreter);
63 gas!(interpreter, VERYLOW);
64 popn!([mem_offset, offset, size], interpreter);
65
66 // Sizes more than u64::MAX will spend all the gas in memory resize.
67 let size = as_usize_or_fail!(interpreter, size);
68 // Size of zero should not change the memory
69 if size == 0 {
70 return;
71 }
72 // Fail if mem offset is big as it will spend all the gas
73 let mem_offset = as_usize_or_fail!(interpreter, mem_offset);
74 resize_memory!(interpreter, mem_offset, size);
75
76 gas_or_fail!(interpreter, cost_per_word(size, VERYLOW));
77
78 let offset = as_usize_saturated!(offset);
79 let data = interpreter.bytecode.data();
80
81 // Set data from the eof to the shared memory. Padded it with zeros.
82 interpreter.memory.set_data(mem_offset, offset, size, data);
83}
84
85// TODO : Test
86/*
87#[cfg(test)]
88mod test {
89 use bytecode::{Bytecode, Eof};
90 use primitives::{b256, bytes, Bytes};
91 use specification::hardfork::SpecId;
92 use std::sync::Arc;
93 use context_interface::DefaultEthereumWiring;
94
95 use super::*;
96 use crate::{table::make_instruction_table, DummyHost, Gas};
97 use bytecode::opcode::{DATACOPY, DATALOAD, DATALOADN, DATASIZE};
98
99 fn dummy_eof(code_bytes: Bytes) -> Bytecode {
100 let bytes = bytes!("ef000101000402000100010400000000800000fe");
101 let mut eof = Eof::decode(bytes).unwrap();
102
103 eof.body.data_section =
104 bytes!("000000000000000000000000000000000000000000000000000000000000000102030405");
105 eof.header.data_size = eof.body.data_section.len() as u16;
106
107 eof.header.code_sizes[0] = code_bytes.len() as u16;
108 eof.body.code_section[0] = code_bytes.len();
109 eof.body.code = code_bytes;
110 Bytecode::Eof(Arc::new(eof))
111 }
112
113 #[test]
114 fn dataload_dataloadn() {
115 let table = make_instruction_table::<Interpreter, DummyHost<DefaultEthereumWiring>>();
116 let mut host = DummyHost::default();
117 let eof = dummy_eof(Bytes::from([
118 DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN,
119 0x00, 36, DATASIZE,
120 ]));
121
122 let mut interp = Interpreter::new_bytecode(eof);
123 interp.spec_id = SpecId::PRAGUE;
124 interp.gas = Gas::new(10000);
125
126 // DATALOAD
127 interp.stack.push(U256::from(0)).unwrap();
128 interp.step(&table, &mut host);
129 assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]);
130 interp.stack.pop().unwrap();
131
132 // DATALOADN
133 interp.step(&table, &mut host);
134 assert_eq!(interp.stack.data(), &vec![U256::from(0x01)]);
135 interp.stack.pop().unwrap();
136
137 // DATALOAD (padding)
138 interp.stack.push(U256::from(35)).unwrap();
139 interp.step(&table, &mut host);
140 assert_eq!(
141 interp.stack.data(),
142 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
143 );
144 interp.stack.pop().unwrap();
145
146 // DATALOADN (padding)
147 interp.step(&table, &mut host);
148 assert_eq!(
149 interp.stack.data(),
150 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
151 );
152 interp.stack.pop().unwrap();
153
154 // DATALOAD (out of bounds)
155 interp.stack.push(U256::from(36)).unwrap();
156 interp.step(&table, &mut host);
157 assert_eq!(interp.stack.data(), &vec![U256::ZERO]);
158 interp.stack.pop().unwrap();
159
160 // DATALOADN (out of bounds)
161 interp.step(&table, &mut host);
162 assert_eq!(interp.stack.data(), &vec![U256::ZERO]);
163 interp.stack.pop().unwrap();
164
165 // DATA SIZE
166 interp.step(&table, &mut host);
167 assert_eq!(interp.stack.data(), &vec![U256::from(36)]);
168 }
169
170 #[test]
171 fn data_copy() {
172 let table = make_instruction_table::<Interpreter, DummyHost<DefaultEthereumWiring>>();
173 let mut host = DummyHost::default();
174 let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY]));
175
176 let mut interp = Interpreter::new_bytecode(eof);
177 interp.gas = Gas::new(10000);
178 interp.spec_id = SpecId::PRAGUE;
179
180 // Data copy
181 // size, offset mem_offset,
182 interp.stack.push(U256::from(32)).unwrap();
183 interp.stack.push(U256::from(0)).unwrap();
184 interp.stack.push(U256::from(0)).unwrap();
185 interp.step(&table, &mut host);
186 assert_eq!(
187 interp.shared_memory.context_memory(),
188 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
189 );
190
191 // Data copy (Padding)
192 // size, offset mem_offset,
193 interp.stack.push(U256::from(2)).unwrap();
194 interp.stack.push(U256::from(35)).unwrap();
195 interp.stack.push(U256::from(1)).unwrap();
196 interp.step(&table, &mut host);
197 assert_eq!(
198 interp.shared_memory.context_memory(),
199 &bytes!("0005000000000000000000000000000000000000000000000000000000000001")
200 );
201
202 // Data copy (Out of bounds)
203 // size, offset mem_offset,
204 interp.stack.push(U256::from(2)).unwrap();
205 interp.stack.push(U256::from(37)).unwrap();
206 interp.stack.push(U256::from(1)).unwrap();
207 interp.step(&table, &mut host);
208 assert_eq!(
209 interp.shared_memory.context_memory(),
210 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
211 );
212
213 // Data copy (Size == 0)
214 // mem_offset, offset, size
215 interp.stack.push(U256::from(0)).unwrap();
216 interp.stack.push(U256::from(37)).unwrap();
217 interp.stack.push(U256::from(1)).unwrap();
218 interp.step(&table, &mut host);
219 assert_eq!(
220 interp.shared_memory.context_memory(),
221 &bytes!("0000000000000000000000000000000000000000000000000000000000000001")
222 );
223 }
224}
225 */