iota_move_natives_latest/
address.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::collections::VecDeque;
6
7use move_binary_format::errors::PartialVMResult;
8use move_core_types::{account_address::AccountAddress, gas_algebra::InternalGas, u256::U256};
9use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext};
10use move_vm_types::{
11    loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, values::Value,
12};
13use smallvec::smallvec;
14
15use crate::NativesCostTable;
16
17const E_ADDRESS_PARSE_ERROR: u64 = 0;
18#[derive(Clone)]
19pub struct AddressFromBytesCostParams {
20    /// addresses are constant size, so base cost suffices
21    pub address_from_bytes_cost_base: InternalGas,
22}
23/// ****************************************************************************
24/// ********************* native fun from_bytes
25/// Implementation of the Move native function `address::from_bytes(bytes:
26/// vector<u8>)`   gas cost: address_from_bytes_cost_base
27/// | addresses are constant size, so base cost suffices ***********************
28/// ************************************************************************
29pub fn from_bytes(
30    context: &mut NativeContext,
31    ty_args: Vec<Type>,
32    mut args: VecDeque<Value>,
33) -> PartialVMResult<NativeResult> {
34    debug_assert!(ty_args.is_empty());
35    debug_assert!(args.len() == 1);
36
37    let address_from_bytes_cost_params = context
38        .extensions_mut()
39        .get::<NativesCostTable>()
40        .address_from_bytes_cost_params
41        .clone();
42
43    // Charge base fee
44    native_charge_gas_early_exit!(
45        context,
46        address_from_bytes_cost_params.address_from_bytes_cost_base
47    );
48
49    let addr_bytes = pop_arg!(args, Vec<u8>);
50    let cost = context.gas_used();
51
52    // Address parsing can fail if fed the incorrect number of bytes.
53    Ok(match AccountAddress::from_bytes(addr_bytes) {
54        Ok(addr) => NativeResult::ok(cost, smallvec![Value::address(addr)]),
55        Err(_) => NativeResult::err(cost, E_ADDRESS_PARSE_ERROR),
56    })
57}
58#[derive(Clone)]
59pub struct AddressToU256CostParams {
60    /// addresses and u256 are constant size, so base cost suffices
61    pub address_to_u256_cost_base: InternalGas,
62}
63/// ****************************************************************************
64/// ********************* native fun to_u256
65/// Implementation of the Move native function `address::to_u256(address): u256`
66///   gas cost:  address_to_u256_cost_base                   | addresses and
67/// u256 are constant size, so base cost suffices ******************************
68/// *****************************************************************
69pub fn to_u256(
70    context: &mut NativeContext,
71    ty_args: Vec<Type>,
72    mut args: VecDeque<Value>,
73) -> PartialVMResult<NativeResult> {
74    debug_assert!(ty_args.is_empty());
75    debug_assert!(args.len() == 1);
76
77    let address_to_u256_cost_params = context
78        .extensions_mut()
79        .get::<NativesCostTable>()
80        .address_to_u256_cost_params
81        .clone();
82
83    // Charge flat cost
84    native_charge_gas_early_exit!(
85        context,
86        address_to_u256_cost_params.address_to_u256_cost_base
87    );
88
89    let addr = pop_arg!(args, AccountAddress);
90    let mut addr_bytes_le = addr.to_vec();
91    addr_bytes_le.reverse();
92
93    // unwrap safe because we know addr_bytes_le is length 32
94    let u256_val = Value::u256(U256::from_le_bytes(&addr_bytes_le.try_into().unwrap()));
95    Ok(NativeResult::ok(context.gas_used(), smallvec![u256_val]))
96}
97
98#[derive(Clone)]
99pub struct AddressFromU256CostParams {
100    /// addresses and u256 are constant size, so base cost suffices
101    pub address_from_u256_cost_base: InternalGas,
102}
103/// ****************************************************************************
104/// ********************* native fun from_u256
105/// Implementation of the Move native function `address::from_u256(u256):
106/// address`   gas cost: address_from_u256_cost_base              | addresses
107/// and u256 are constant size, so base cost suffices **************************
108/// *********************************************************************
109pub fn from_u256(
110    context: &mut NativeContext,
111    ty_args: Vec<Type>,
112    mut args: VecDeque<Value>,
113) -> PartialVMResult<NativeResult> {
114    debug_assert!(ty_args.is_empty());
115    debug_assert!(args.len() == 1);
116
117    let address_from_u256_cost_params = context
118        .extensions_mut()
119        .get::<NativesCostTable>()
120        .address_from_u256_cost_params
121        .clone();
122
123    // charge flat fee
124    native_charge_gas_early_exit!(
125        context,
126        address_from_u256_cost_params.address_from_u256_cost_base
127    );
128
129    let u256 = pop_arg!(args, U256);
130    let mut u256_bytes = u256.to_le_bytes().to_vec();
131    u256_bytes.reverse();
132
133    // unwrap safe because we are passing a 32 byte slice
134    let addr_val = Value::address(AccountAddress::from_bytes(&u256_bytes[..]).unwrap());
135    Ok(NativeResult::ok(context.gas_used(), smallvec![addr_val]))
136}