iota_move_natives_latest/
tx_context.rs1use std::collections::VecDeque;
6
7use iota_sdk_types::{ObjectId, TransactionDigest};
8use move_binary_format::errors::PartialVMResult;
9use move_core_types::{account_address::AccountAddress, gas_algebra::InternalGas};
10use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext};
11use move_vm_types::{
12 loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, values::Value,
13};
14use smallvec::smallvec;
15
16use crate::{
17 NativesCostTable, object_runtime::ObjectRuntime, transaction_context::TransactionContext,
18};
19
20#[derive(Clone)]
21pub struct TxContextDeriveIdCostParams {
22 pub tx_context_derive_id_cost_base: InternalGas,
23}
24pub fn derive_id(
32 context: &mut NativeContext,
33 ty_args: Vec<Type>,
34 mut args: VecDeque<Value>,
35) -> PartialVMResult<NativeResult> {
36 debug_assert!(ty_args.is_empty());
37 debug_assert!(args.len() == 2);
38
39 let tx_context_derive_id_cost_params = context
40 .extensions_mut()
41 .get::<NativesCostTable>()?
42 .tx_context_derive_id_cost_params
43 .clone();
44 native_charge_gas_early_exit!(
45 context,
46 tx_context_derive_id_cost_params.tx_context_derive_id_cost_base
47 );
48
49 let ids_created = pop_arg!(args, u64);
50 let tx_hash = pop_arg!(args, Vec<u8>);
51
52 let digest = TransactionDigest::from_bytes(tx_hash.as_slice()).unwrap();
55 let object_id = ObjectId::derive_id(digest, ids_created);
56 let obj_runtime: &mut ObjectRuntime = context.extensions_mut().get_mut()?;
57 obj_runtime.new_id(object_id)?;
58
59 Ok(NativeResult::ok(
60 context.gas_used(),
61 smallvec![Value::address(AccountAddress::new(object_id.into_bytes()))],
62 ))
63}
64#[derive(Clone)]
65pub struct TxContextFreshIdCostParams {
66 pub tx_context_fresh_id_cost_base: InternalGas,
67}
68pub fn fresh_id(
74 context: &mut NativeContext,
75 ty_args: Vec<Type>,
76 args: VecDeque<Value>,
77) -> PartialVMResult<NativeResult> {
78 debug_assert!(ty_args.is_empty());
79 debug_assert!(args.is_empty());
80
81 let tx_context_fresh_id_cost_params = context
82 .extensions_mut()
83 .get::<NativesCostTable>()?
84 .tx_context_fresh_id_cost_params
85 .clone();
86 native_charge_gas_early_exit!(
87 context,
88 tx_context_fresh_id_cost_params.tx_context_fresh_id_cost_base
89 );
90
91 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
92 let fresh_id = transaction_context.fresh_id();
93 let object_runtime: &mut ObjectRuntime = context.extensions_mut().get_mut()?;
94 object_runtime.new_id(fresh_id)?;
95
96 Ok(NativeResult::ok(
97 context.gas_used(),
98 smallvec![Value::address(AccountAddress::new(fresh_id.into_bytes()))],
99 ))
100}
101
102#[derive(Clone)]
103pub struct TxContextSenderCostParams {
104 pub tx_context_sender_cost_base: InternalGas,
105}
106pub fn sender(
112 context: &mut NativeContext,
113 ty_args: Vec<Type>,
114 args: VecDeque<Value>,
115) -> PartialVMResult<NativeResult> {
116 debug_assert!(ty_args.is_empty());
117 debug_assert!(args.is_empty());
118
119 let tx_context_sender_cost_params = context
120 .extensions_mut()
121 .get::<NativesCostTable>()?
122 .tx_context_sender_cost_params
123 .clone();
124 native_charge_gas_early_exit!(
125 context,
126 tx_context_sender_cost_params.tx_context_sender_cost_base
127 );
128
129 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
130 let sender = transaction_context.sender();
131
132 Ok(NativeResult::ok(
133 context.gas_used(),
134 smallvec![Value::address(AccountAddress::new(sender.into_bytes()))],
135 ))
136}
137
138#[derive(Clone)]
139pub struct TxContextDigestCostParams {
140 pub tx_context_digest_cost_base: InternalGas,
141}
142pub fn digest(
148 context: &mut NativeContext,
149 ty_args: Vec<Type>,
150 args: VecDeque<Value>,
151) -> PartialVMResult<NativeResult> {
152 debug_assert!(ty_args.is_empty());
153 debug_assert!(args.is_empty());
154
155 let tx_context_digest_cost_params = context
156 .extensions_mut()
157 .get::<NativesCostTable>()?
158 .tx_context_digest_cost_params
159 .clone();
160 native_charge_gas_early_exit!(
161 context,
162 tx_context_digest_cost_params.tx_context_digest_cost_base
163 );
164
165 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
166 let digest_ref = transaction_context.digest_ref()?;
167
168 Ok(NativeResult::ok(context.gas_used(), smallvec![digest_ref]))
169}
170
171#[derive(Clone)]
172pub struct TxContextEpochCostParams {
173 pub tx_context_epoch_cost_base: InternalGas,
174}
175pub fn epoch(
181 context: &mut NativeContext,
182 ty_args: Vec<Type>,
183 args: VecDeque<Value>,
184) -> PartialVMResult<NativeResult> {
185 debug_assert!(ty_args.is_empty());
186 debug_assert!(args.is_empty());
187
188 let tx_context_epoch_cost_params = context
189 .extensions_mut()
190 .get::<NativesCostTable>()?
191 .tx_context_epoch_cost_params
192 .clone();
193 native_charge_gas_early_exit!(
194 context,
195 tx_context_epoch_cost_params.tx_context_epoch_cost_base
196 );
197
198 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
199 let epoch = transaction_context.epoch();
200
201 Ok(NativeResult::ok(
202 context.gas_used(),
203 smallvec![Value::u64(epoch)],
204 ))
205}
206
207#[derive(Clone)]
208pub struct TxContextEpochTimestampMsCostParams {
209 pub tx_context_epoch_timestamp_ms_cost_base: InternalGas,
210}
211pub fn epoch_timestamp_ms(
217 context: &mut NativeContext,
218 ty_args: Vec<Type>,
219 args: VecDeque<Value>,
220) -> PartialVMResult<NativeResult> {
221 debug_assert!(ty_args.is_empty());
222 debug_assert!(args.is_empty());
223
224 let tx_context_epoch_timestamp_ms_cost_params = context
225 .extensions_mut()
226 .get::<NativesCostTable>()?
227 .tx_context_epoch_timestamp_ms_cost_params
228 .clone();
229 native_charge_gas_early_exit!(
230 context,
231 tx_context_epoch_timestamp_ms_cost_params.tx_context_epoch_timestamp_ms_cost_base
232 );
233
234 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
235 let timestamp = transaction_context.epoch_timestamp_ms();
236
237 Ok(NativeResult::ok(
238 context.gas_used(),
239 smallvec![Value::u64(timestamp)],
240 ))
241}
242
243#[derive(Clone)]
244pub struct TxContextSponsorCostParams {
245 pub tx_context_sponsor_cost_base: InternalGas,
246}
247pub fn sponsor(
253 context: &mut NativeContext,
254 ty_args: Vec<Type>,
255 args: VecDeque<Value>,
256) -> PartialVMResult<NativeResult> {
257 debug_assert!(ty_args.is_empty());
258 debug_assert!(args.is_empty());
259
260 let tx_context_sponsor_cost_params = context
261 .extensions_mut()
262 .get::<NativesCostTable>()?
263 .tx_context_sponsor_cost_params
264 .clone();
265 native_charge_gas_early_exit!(
266 context,
267 tx_context_sponsor_cost_params.tx_context_sponsor_cost_base
268 );
269
270 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
271 let sponsor = transaction_context
272 .sponsor()
273 .map(|addr| AccountAddress::new(addr.into_bytes()))
274 .into_iter();
275 let sponsor = Value::vector_address(sponsor);
276 Ok(NativeResult::ok(context.gas_used(), smallvec![sponsor]))
277}
278
279#[derive(Clone)]
280pub struct TxContextRGPCostParams {
281 pub tx_context_rgp_cost_base: InternalGas,
282}
283pub fn rgp(
289 context: &mut NativeContext,
290 ty_args: Vec<Type>,
291 args: VecDeque<Value>,
292) -> PartialVMResult<NativeResult> {
293 debug_assert!(ty_args.is_empty());
294 debug_assert!(args.is_empty());
295
296 let tx_context_rgp_cost_params = context
297 .extensions_mut()
298 .get::<NativesCostTable>()?
299 .tx_context_rgp_cost_params
300 .clone();
301 native_charge_gas_early_exit!(context, tx_context_rgp_cost_params.tx_context_rgp_cost_base);
302
303 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
304 let rgp = transaction_context.rgp();
305
306 Ok(NativeResult::ok(
307 context.gas_used(),
308 smallvec![Value::u64(rgp)],
309 ))
310}
311#[derive(Clone)]
312pub struct TxContextGasPriceCostParams {
313 pub tx_context_gas_price_cost_base: InternalGas,
314}
315pub fn gas_price(
321 context: &mut NativeContext,
322 ty_args: Vec<Type>,
323 args: VecDeque<Value>,
324) -> PartialVMResult<NativeResult> {
325 debug_assert!(ty_args.is_empty());
326 debug_assert!(args.is_empty());
327
328 let tx_context_gas_price_cost_params = context
329 .extensions_mut()
330 .get::<NativesCostTable>()?
331 .tx_context_gas_price_cost_params
332 .clone();
333 native_charge_gas_early_exit!(
334 context,
335 tx_context_gas_price_cost_params.tx_context_gas_price_cost_base
336 );
337
338 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
339 let gas_price = transaction_context.gas_price();
340
341 Ok(NativeResult::ok(
342 context.gas_used(),
343 smallvec![Value::u64(gas_price)],
344 ))
345}
346
347#[derive(Clone)]
348pub struct TxContextGasBudgetCostParams {
349 pub tx_context_gas_budget_cost_base: InternalGas,
350}
351pub fn gas_budget(
357 context: &mut NativeContext,
358 ty_args: Vec<Type>,
359 args: VecDeque<Value>,
360) -> PartialVMResult<NativeResult> {
361 debug_assert!(ty_args.is_empty());
362 debug_assert!(args.is_empty());
363
364 let tx_context_gas_budget_cost_params = context
365 .extensions_mut()
366 .get::<NativesCostTable>()?
367 .tx_context_gas_budget_cost_params
368 .clone();
369 native_charge_gas_early_exit!(
370 context,
371 tx_context_gas_budget_cost_params.tx_context_gas_budget_cost_base
372 );
373
374 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
375 let gas_budget = transaction_context.gas_budget();
376
377 Ok(NativeResult::ok(
378 context.gas_used(),
379 smallvec![Value::u64(gas_budget)],
380 ))
381}
382
383#[derive(Clone)]
384pub struct TxContextIdsCreatedCostParams {
385 pub tx_context_ids_created_cost_base: InternalGas,
386}
387pub fn ids_created(
393 context: &mut NativeContext,
394 ty_args: Vec<Type>,
395 args: VecDeque<Value>,
396) -> PartialVMResult<NativeResult> {
397 debug_assert!(ty_args.is_empty());
398 debug_assert!(args.is_empty());
399
400 let tx_context_ids_created_cost_params = context
401 .extensions_mut()
402 .get::<NativesCostTable>()?
403 .tx_context_ids_created_cost_params
404 .clone();
405 native_charge_gas_early_exit!(
406 context,
407 tx_context_ids_created_cost_params.tx_context_ids_created_cost_base
408 );
409
410 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
411 let ids_created = transaction_context.ids_created();
412
413 Ok(NativeResult::ok(
414 context.gas_used(),
415 smallvec![Value::u64(ids_created)],
416 ))
417}
418
419#[derive(Clone)]
423pub struct TxContextReplaceCostParams {
424 pub tx_context_replace_cost_base: InternalGas,
425}
426pub fn replace(
446 context: &mut NativeContext,
447 ty_args: Vec<Type>,
448 mut args: VecDeque<Value>,
449) -> PartialVMResult<NativeResult> {
450 debug_assert!(ty_args.is_empty());
451 debug_assert!(args.len() == 9);
452
453 let tx_context_replace_cost_params = context
455 .extensions_mut()
456 .get::<NativesCostTable>()?
457 .tx_context_replace_cost_params
458 .clone();
459 native_charge_gas_early_exit!(
460 context,
461 tx_context_replace_cost_params.tx_context_replace_cost_base
462 );
463
464 let mut sponsor: Vec<AccountAddress> = pop_arg!(args, Vec<AccountAddress>);
465 let gas_budget: u64 = pop_arg!(args, u64);
466 let gas_price: u64 = pop_arg!(args, u64);
467 let rgp: u64 = pop_arg!(args, u64);
468 let ids_created: u64 = pop_arg!(args, u64);
469 let epoch_timestamp_ms: u64 = pop_arg!(args, u64);
470 let epoch: u64 = pop_arg!(args, u64);
471 let tx_hash: Vec<u8> = pop_arg!(args, Vec<u8>);
472 let sender: AccountAddress = pop_arg!(args, AccountAddress);
473 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
474 transaction_context.replace(
475 sender,
476 tx_hash,
477 epoch,
478 epoch_timestamp_ms,
479 ids_created,
480 rgp,
481 gas_price,
482 gas_budget,
483 sponsor.pop(),
484 )?;
485
486 Ok(NativeResult::ok(context.gas_used(), smallvec![]))
487}
488
489const E_NO_IDS_CREATED: u64 = 1;
492
493pub fn last_created_id(
500 context: &mut NativeContext,
501 ty_args: Vec<Type>,
502 args: VecDeque<Value>,
503) -> PartialVMResult<NativeResult> {
504 debug_assert!(ty_args.is_empty());
505 debug_assert!(args.is_empty());
506
507 let tx_context_derive_id_cost_params = context
508 .extensions_mut()
509 .get::<NativesCostTable>()?
510 .tx_context_derive_id_cost_params
511 .clone();
512 native_charge_gas_early_exit!(
513 context,
514 tx_context_derive_id_cost_params.tx_context_derive_id_cost_base
515 );
516
517 let transaction_context: &mut TransactionContext = context.extensions_mut().get_mut()?;
518 let mut ids_created = transaction_context.ids_created();
519 if ids_created == 0 {
520 return Ok(NativeResult::err(context.gas_used(), E_NO_IDS_CREATED));
521 }
522 ids_created -= 1;
523 let digest = transaction_context.digest();
524 let object_id = ObjectId::derive_id(digest, ids_created);
525 let address = AccountAddress::from(object_id.into_bytes());
526 let obj_runtime: &mut ObjectRuntime = context.extensions_mut().get_mut()?;
527 obj_runtime.new_id(object_id)?;
528
529 Ok(NativeResult::ok(
530 context.gas_used(),
531 smallvec![Value::address(address)],
532 ))
533}