zksync_vm2/instruction_handlers/
context.rs1use primitive_types::{H160, U256};
2use zkevm_opcode_defs::VmMetaParameters;
3use zksync_vm2_interface::{
4 opcodes::{self, Caller, CodeAddress, ContextU128, ErgsLeft, This, SP},
5 OpcodeType, Tracer,
6};
7
8use super::common::boilerplate;
9use crate::{
10 addressing_modes::{Arguments, Destination, Register1, Source},
11 instruction::ExecutionStatus,
12 state::State,
13 Instruction, VirtualMachine, World,
14};
15
16pub(crate) fn address_into_u256(address: H160) -> U256 {
17 let mut buffer = [0; 32];
18 buffer[12..].copy_from_slice(address.as_bytes());
19 U256::from_big_endian(&buffer)
20}
21
22fn context<T, W: World<T>, Op>(
23 vm: &mut VirtualMachine<T, W>,
24 world: &mut W,
25 tracer: &mut T,
26) -> ExecutionStatus
27where
28 T: Tracer,
29 Op: ContextOp,
30{
31 boilerplate::<Op, _, _>(vm, world, tracer, |vm, args| {
32 let result = Op::get(&vm.state);
33 Register1::set(args, &mut vm.state, result);
34 })
35}
36
37trait ContextOp: OpcodeType {
38 fn get<T, W>(state: &State<T, W>) -> U256;
39}
40
41impl ContextOp for This {
42 fn get<T, W>(state: &State<T, W>) -> U256 {
43 address_into_u256(state.current_frame.address)
44 }
45}
46
47impl ContextOp for Caller {
48 fn get<T, W>(state: &State<T, W>) -> U256 {
49 address_into_u256(state.current_frame.caller)
50 }
51}
52
53impl ContextOp for CodeAddress {
54 fn get<T, W>(state: &State<T, W>) -> U256 {
55 address_into_u256(state.current_frame.code_address)
56 }
57}
58
59impl ContextOp for ErgsLeft {
60 fn get<T, W>(state: &State<T, W>) -> U256 {
61 U256([state.current_frame.gas.into(), 0, 0, 0])
62 }
63}
64
65impl ContextOp for ContextU128 {
66 fn get<T, W>(state: &State<T, W>) -> U256 {
67 state.get_context_u128().into()
68 }
69}
70
71impl ContextOp for SP {
72 fn get<T, W>(state: &State<T, W>) -> U256 {
73 state.current_frame.sp.into()
74 }
75}
76
77fn context_meta<T: Tracer, W: World<T>>(
78 vm: &mut VirtualMachine<T, W>,
79 world: &mut W,
80 tracer: &mut T,
81) -> ExecutionStatus {
82 boilerplate::<opcodes::ContextMeta, _, _>(vm, world, tracer, |vm, args| {
83 let result = VmMetaParameters {
84 heap_size: vm.state.current_frame.heap_size,
85 aux_heap_size: vm.state.current_frame.aux_heap_size,
86 this_shard_id: 0, caller_shard_id: 0,
88 code_shard_id: 0,
89 aux_field_0: if vm.state.current_frame.is_kernel {
91 #[allow(clippy::cast_sign_loss)] {
93 vm.world_diff.pubdata.0 as u32
94 }
95 } else {
96 0
97 },
98 }
99 .to_u256();
100
101 Register1::set(args, &mut vm.state, result);
102 })
103}
104
105fn set_context_u128<T: Tracer, W: World<T>>(
106 vm: &mut VirtualMachine<T, W>,
107 world: &mut W,
108 tracer: &mut T,
109) -> ExecutionStatus {
110 boilerplate::<opcodes::SetContextU128, _, _>(vm, world, tracer, |vm, args| {
111 let value = Register1::get(args, &mut vm.state).low_u128();
112 vm.state.set_context_u128(value);
113 })
114}
115
116fn increment_tx_number<T: Tracer, W: World<T>>(
117 vm: &mut VirtualMachine<T, W>,
118 world: &mut W,
119 tracer: &mut T,
120) -> ExecutionStatus {
121 boilerplate::<opcodes::IncrementTxNumber, _, _>(vm, world, tracer, |vm, _| {
122 vm.start_new_tx();
123 })
124}
125
126fn aux_mutating<T: Tracer, W: World<T>>(
127 vm: &mut VirtualMachine<T, W>,
128 world: &mut W,
129 tracer: &mut T,
130) -> ExecutionStatus {
131 boilerplate::<opcodes::AuxMutating0, _, _>(vm, world, tracer, |_, _| {
132 })
134}
135
136impl<T: Tracer, W: World<T>> Instruction<T, W> {
138 fn from_context<Op: ContextOp>(out: Register1, arguments: Arguments) -> Self {
139 Self {
140 handler: context::<T, W, Op>,
141 arguments: arguments.write_destination(&out),
142 }
143 }
144
145 pub fn from_this(out: Register1, arguments: Arguments) -> Self {
147 Self::from_context::<This>(out, arguments)
148 }
149
150 pub fn from_caller(out: Register1, arguments: Arguments) -> Self {
152 Self::from_context::<Caller>(out, arguments)
153 }
154
155 pub fn from_code_address(out: Register1, arguments: Arguments) -> Self {
157 Self::from_context::<CodeAddress>(out, arguments)
158 }
159
160 pub fn from_ergs_left(out: Register1, arguments: Arguments) -> Self {
162 Self::from_context::<ErgsLeft>(out, arguments)
163 }
164
165 pub fn from_context_u128(out: Register1, arguments: Arguments) -> Self {
167 Self::from_context::<ContextU128>(out, arguments)
168 }
169
170 pub fn from_context_sp(out: Register1, arguments: Arguments) -> Self {
172 Self::from_context::<SP>(out, arguments)
173 }
174
175 pub fn from_context_meta(out: Register1, arguments: Arguments) -> Self {
177 Self {
178 handler: context_meta,
179 arguments: arguments.write_destination(&out),
180 }
181 }
182
183 pub fn from_set_context_u128(src: Register1, arguments: Arguments) -> Self {
185 Self {
186 handler: set_context_u128,
187 arguments: arguments.write_source(&src),
188 }
189 }
190
191 pub fn from_increment_tx_number(arguments: Arguments) -> Self {
193 Self {
194 handler: increment_tx_number,
195 arguments,
196 }
197 }
198
199 pub fn from_aux_mutating(arguments: Arguments) -> Self {
201 Self {
202 handler: aux_mutating,
203 arguments,
204 }
205 }
206}