Skip to content

Commit

Permalink
Move TxContext native and sponsor
Browse files Browse the repository at this point in the history
  • Loading branch information
dariorussi committed Mar 1, 2025
1 parent f89030b commit cd14ea6
Show file tree
Hide file tree
Showing 23 changed files with 972 additions and 112 deletions.
19 changes: 13 additions & 6 deletions crates/sui-core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1684,21 +1684,24 @@ async fn test_publish_dependent_module_ok() {

let authority = init_state_with_objects(vec![gas_payment_object]).await;
let rgp = authority.reference_gas_price_for_testing().unwrap();
let gas_price = rgp;
let gas_budget = gas_price * TEST_ONLY_GAS_UNIT_FOR_PUBLISH;
let data = TransactionData::new_module(
sender,
gas_payment_object_ref,
vec![dependent_module_bytes],
vec![ObjectID::from(*genesis_module.address())],
rgp * TEST_ONLY_GAS_UNIT_FOR_PUBLISH,
rgp,
gas_budget,
gas_price,
);
let transaction = to_sender_signed_transaction(data, &sender_key);

let dependent_module_id = TxContext::new(
&sender,
transaction.digest(),
&EpochData::new_test(),
rgp,
gas_price,
gas_budget,
None,
)
.fresh_id();
Expand All @@ -1722,6 +1725,7 @@ async fn test_publish_module_no_dependencies_ok() {
let authority = init_state_with_objects(vec![]).await;
let rgp = authority.reference_gas_price_for_testing().unwrap();
let gas_payment_object_id = ObjectID::random();

// Use the max budget to avoid running out of gas.
let gas_balance = {
let epoch_store = authority.epoch_store_for_testing();
Expand All @@ -1740,20 +1744,23 @@ async fn test_publish_module_no_dependencies_ok() {
.unwrap();
let module_bytes = vec![module_bytes];
let dependencies = vec![]; // no dependencies
let gas_price = rgp;
let gas_budget = gas_price * TEST_ONLY_GAS_UNIT_FOR_PUBLISH;
let data = TransactionData::new_module(
sender,
gas_payment_object_ref,
module_bytes,
dependencies,
rgp * TEST_ONLY_GAS_UNIT_FOR_PUBLISH,
rgp,
gas_budget,
gas_price,
);
let transaction = to_sender_signed_transaction(data, &sender_key);
let _module_object_id = TxContext::new(
&sender,
transaction.digest(),
&EpochData::new_test(),
rgp,
gas_price,
gas_budget,
None,
)
.fresh_id();
Expand Down
122 changes: 97 additions & 25 deletions crates/sui-framework/packages/sui-framework/sources/tx_context.move
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ const TX_HASH_LENGTH: u64 = 32;
/// Expected an tx hash of length 32, but found a different length
const EBadTxHashLength: u64 = 0;

#[test_only]
/// Attempt to get the most recent created object ID when none has been created.
const ENoIDsCreated: u64 = 1;

#[allow(unused_field)]
/// Information about the transaction currently being executed.
/// This cannot be constructed by a transaction--it is a privileged object created by
/// the VM and passed in to the entrypoint of the transaction as `&mut TxContext`.
Expand All @@ -34,9 +31,10 @@ public struct TxContext has drop {

/// Return the address of the user that signed the current
/// transaction
public fun sender(self: &TxContext): address {
self.sender
public fun sender(_self: &TxContext): address {
native_sender()
}
native fun native_sender(): address;

/// Return the transaction digest (hash of transaction inputs).
/// Please do not use as a source of randomness.
Expand All @@ -45,34 +43,45 @@ public fun digest(self: &TxContext): &vector<u8> {
}

/// Return the current epoch
public fun epoch(self: &TxContext): u64 {
self.epoch
public fun epoch(_self: &TxContext): u64 {
native_epoch()
}
native fun native_epoch(): u64;

/// Return the epoch start time as a unix timestamp in milliseconds.
public fun epoch_timestamp_ms(self: &TxContext): u64 {
self.epoch_timestamp_ms
public fun epoch_timestamp_ms(_self: &TxContext): u64 {
native_epoch_timestamp_ms()
}
native fun native_epoch_timestamp_ms(): u64;

/// Return the adress of the transaction sponsor or `None` if there was no sponsor.
public fun sponsor(_self: &TxContext): Option<address> {
option_sponsor()
}

/// Create an `address` that has not been used. As it is an object address, it will never
/// occur as the address for a user.
/// In other words, the generated address is a globally unique object ID.
public fun fresh_object_address(ctx: &mut TxContext): address {
let ids_created = ctx.ids_created;
let id = derive_id(*&ctx.tx_hash, ids_created);
ctx.ids_created = ids_created + 1;
id
public fun fresh_object_address(_ctx: &mut TxContext): address {
fresh_id()
}
native fun fresh_id(): address;

#[allow(unused_function)]
/// Return the number of id's created by the current transaction.
/// Hidden for now, but may expose later
fun ids_created(self: &TxContext): u64 {
self.ids_created
fun ids_created(_self: &TxContext): u64 {
native_ids_created()
}
native fun native_ids_created(): u64;

/// Native function for deriving an ID via hash(tx_hash || ids_created)
native fun derive_id(tx_hash: vector<u8>, ids_created: u64): address;
#[allow(unused_function)]
// native function to retrieve gas price, currently not exposed
native fun native_gas_price(): u64;

#[allow(unused_function)]
// native function to retrieve gas budget, currently not exposed
native fun native_gas_budget(): u64;

// ==== test-only functions ====

Expand All @@ -86,7 +95,24 @@ public fun new(
ids_created: u64,
): TxContext {
assert!(tx_hash.length() == TX_HASH_LENGTH, EBadTxHashLength);
TxContext { sender, tx_hash, epoch, epoch_timestamp_ms, ids_created }
replace(
sender,
tx_hash,
epoch,
epoch_timestamp_ms,
ids_created,
native_gas_price(),
native_gas_budget(),
native_sponsor(),
);
// return an empty TxContext given all the info is held on the native side (call above)
TxContext {
sender: @0x0,
tx_hash,
epoch: 0,
epoch_timestamp_ms: 0,
ids_created: 0,
}
}

#[test_only]
Expand Down Expand Up @@ -125,17 +151,63 @@ public fun get_ids_created(self: &TxContext): u64 {
#[test_only]
/// Return the most recent created object ID.
public fun last_created_object_id(self: &TxContext): address {
let ids_created = self.ids_created;
assert!(ids_created > 0, ENoIDsCreated);
derive_id(*&self.tx_hash, ids_created - 1)
last_created_id()
}
#[test_only]
native fun last_created_id(): address;

#[test_only]
public fun increment_epoch_number(self: &mut TxContext) {
self.epoch = self.epoch + 1
let epoch = self.epoch() + 1;
replace(
native_sender(),
self.tx_hash,
native_epoch(),
epoch,
native_ids_created(),
native_gas_price(),
native_gas_budget(),
native_sponsor(),
);
}

#[test_only]
public fun increment_epoch_timestamp(self: &mut TxContext, delta_ms: u64) {
self.epoch_timestamp_ms = self.epoch_timestamp_ms + delta_ms
let epoch_timestamp_ms = self.epoch_timestamp_ms() + delta_ms;
replace(
native_sender(),
self.tx_hash,
native_epoch(),
epoch_timestamp_ms,
native_ids_created(),
native_gas_price(),
native_gas_budget(),
native_sponsor(),
);
}

fun option_sponsor(): Option<address> {
let sponsor = native_sponsor();
if (sponsor.length() == 0) {
option::none()
} else {
option::some(sponsor[0])
}
}
native fun native_sponsor(): vector<address>;

#[test_only]
native fun replace(
sender: address,
tx_hash: vector<u8>,
epoch: u64,
epoch_timestamp_ms: u64,
ids_created: u64,
gas_price: u64,
gas_budget: u64,
sponsor: vector<address>,
);

#[allow(unused_function)]
/// Native function for deriving an ID via hash(tx_hash || ids_created)
native fun derive_id(tx_hash: vector<u8>, ids_created: u64): address;
27 changes: 20 additions & 7 deletions crates/sui-move/src/unit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ use move_package::BuildConfig;
use move_unit_test::{extensions::set_extension_hook, UnitTestingConfig};
use move_vm_runtime::native_extensions::NativeContextExtensions;
use once_cell::sync::Lazy;
use std::{cell::RefCell, collections::BTreeMap, path::Path, sync::Arc};
use std::{cell::RefCell, collections::BTreeMap, path::Path, rc::Rc, sync::Arc};
use sui_move_build::decorate_warnings;
use sui_move_natives::test_scenario::InMemoryTestStore;
use sui_move_natives::{object_runtime::ObjectRuntime, NativesCostTable};
use sui_move_natives::{test_scenario::InMemoryTestStore, transaction_context::TransactionContext};
use sui_protocol_config::ProtocolConfig;
use sui_types::{
gas_model::tables::initial_cost_schedule_for_unit_tests, in_memory_storage::InMemoryStorage,
base_types::{SuiAddress, TxContext},
digests::TransactionDigest,
gas_model::tables::initial_cost_schedule_for_unit_tests,
in_memory_storage::InMemoryStorage,
metrics::LimitsMetrics,
};

Expand Down Expand Up @@ -113,6 +116,7 @@ fn new_testing_object_and_natives_cost_runtime(ext: &mut NativeContextExtensions
let registry = prometheus::Registry::new();
let metrics = Arc::new(LimitsMetrics::new(&registry));
let store = Lazy::force(&TEST_STORE);
let protocol_config = ProtocolConfig::get_for_max_version_UNSAFE();

ext.add(ObjectRuntime::new(
store,
Expand All @@ -122,9 +126,18 @@ fn new_testing_object_and_natives_cost_runtime(ext: &mut NativeContextExtensions
metrics,
0, // epoch id
));
ext.add(NativesCostTable::from_protocol_config(
&ProtocolConfig::get_for_max_version_UNSAFE(),
));

ext.add(NativesCostTable::from_protocol_config(&protocol_config));
let tx_context = TxContext::new_from_components(
&SuiAddress::ZERO,
&TransactionDigest::default(),
&0,
0,
0,
0,
None,
);
ext.add(TransactionContext::new_for_testing(Rc::new(RefCell::new(
tx_context,
))));
ext.add(store);
}
41 changes: 41 additions & 0 deletions crates/sui-protocol-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ const MAX_PROTOCOL_VERSION: u64 = 76;
// Enable consensus garbage collection for testnet
// Enable the new consensus commit rule for testnet.
// Enable passkey auth in multisig for testnet.
// Make `TxContext` Move API native
#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub struct ProtocolVersion(u64);

Expand Down Expand Up @@ -639,6 +640,10 @@ struct FeatureFlags {
// If true, record the additional state digest in the consensus commit prologue.
#[serde(skip_serializing_if = "is_false")]
record_additional_state_digest_in_prologue: bool,

// If true, enable `TxContext` Move API to go native.
#[serde(skip_serializing_if = "is_false")]
move_native_context: bool,
}

fn is_false(b: &bool) -> bool {
Expand Down Expand Up @@ -1101,6 +1106,15 @@ pub struct ProtocolConfig {
// TxContext
// Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
tx_context_derive_id_cost_base: Option<u64>,
tx_context_fresh_id_cost_base: Option<u64>,
tx_context_sender_cost_base: Option<u64>,
tx_context_epoch_cost_base: Option<u64>,
tx_context_epoch_timestamp_ms_cost_base: Option<u64>,
tx_context_sponsor_cost_base: Option<u64>,
tx_context_gas_price_cost_base: Option<u64>,
tx_context_gas_budget_cost_base: Option<u64>,
tx_context_ids_created_cost_base: Option<u64>,
tx_context_replace_cost_base: Option<u64>,

// Types
// Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
Expand Down Expand Up @@ -1827,6 +1841,7 @@ impl ProtocolConfig {
pub fn consensus_zstd_compression(&self) -> bool {
self.feature_flags.consensus_zstd_compression
}

pub fn enable_nitro_attestation(&self) -> bool {
self.feature_flags.enable_nitro_attestation
}
Expand All @@ -1849,6 +1864,10 @@ impl ProtocolConfig {
pub fn minimize_child_object_mutations(&self) -> bool {
self.feature_flags.minimize_child_object_mutations
}

pub fn move_native_context(&self) -> bool {
self.feature_flags.move_native_context
}
}

#[cfg(not(msim))]
Expand Down Expand Up @@ -2141,6 +2160,15 @@ impl ProtocolConfig {
// `tx_context` module
// Cost params for the Move native function `transfer_impl<T: key>(obj: T, recipient: address)`
tx_context_derive_id_cost_base: Some(52),
tx_context_fresh_id_cost_base: None,
tx_context_sender_cost_base: None,
tx_context_epoch_cost_base: None,
tx_context_epoch_timestamp_ms_cost_base: None,
tx_context_sponsor_cost_base: None,
tx_context_gas_price_cost_base: None,
tx_context_gas_budget_cost_base: None,
tx_context_ids_created_cost_base: None,
tx_context_replace_cost_base: None,

// `types` module
// Cost params for the Move native function `is_one_time_witness<T: drop>(_: &T): bool`
Expand Down Expand Up @@ -3311,6 +3339,19 @@ impl ProtocolConfig {
if chain != Chain::Mainnet {
cfg.feature_flags.accept_passkey_in_multisig = true;
}

cfg.feature_flags.move_native_context = false;

cfg.feature_flags.move_native_context = true;
cfg.tx_context_fresh_id_cost_base = Some(52);
cfg.tx_context_sender_cost_base = Some(30);
cfg.tx_context_epoch_cost_base = Some(30);
cfg.tx_context_epoch_timestamp_ms_cost_base = Some(30);
cfg.tx_context_sponsor_cost_base = Some(30);
cfg.tx_context_gas_price_cost_base = Some(30);
cfg.tx_context_gas_budget_cost_base = Some(30);
cfg.tx_context_ids_created_cost_base = Some(30);
cfg.tx_context_replace_cost_base = Some(30);
}
// Use this template when making changes:
//
Expand Down
Loading

0 comments on commit cd14ea6

Please sign in to comment.