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 */