Skip to content

Commit

Permalink
txcontext
Browse files Browse the repository at this point in the history
  • Loading branch information
dariorussi committed Oct 2, 2024
1 parent 337e6a5 commit 6dcf7ed
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 13 deletions.
2 changes: 1 addition & 1 deletion crates/sui-framework/packages/sui-framework/Move.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ name = "MoveStdlib"
source = { local = "../move-stdlib" }

[move.toolchain-version]
compiler-version = "1.30.0"
compiler-version = "1.34.0"
edition = "2024.beta"
flavor = "sui"
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ fun ids_created(self: &TxContext): 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 fun native_sender(): address;

#[allow(unused_function)]
native fun native_digest(): &vector<u8>;

#[allow(unused_function)]
native fun native_epoch(): u64;

#[allow(unused_function)]
native fun native_epoch_timestamp_ms(): u64;

#[allow(unused_function)]
native fun native_sponsor(): address;

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

#[test_only]
Expand Down
15 changes: 14 additions & 1 deletion crates/sui-protocol-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tracing::{info, warn};

/// The minimum and maximum protocol versions supported by this build.
const MIN_PROTOCOL_VERSION: u64 = 1;
const MAX_PROTOCOL_VERSION: u64 = 61;
const MAX_PROTOCOL_VERSION: u64 = 62;

// Record history of protocol version allocations here:
//
Expand Down Expand Up @@ -183,6 +183,8 @@ const MAX_PROTOCOL_VERSION: u64 = 61;
// Version 61: Switch to distributed vote scoring in consensus in testnet
// Further reduce minimum number of random beacon shares.
// Add feature flag for Mysticeti fastpath.
// Version 62: Framework natives for transaction context and protocol config
// feature flag to turn it on/off

#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub struct ProtocolVersion(u64);
Expand Down Expand Up @@ -541,6 +543,10 @@ struct FeatureFlags {
// Enables Mysticeti fastpath.
#[serde(skip_serializing_if = "is_false")]
mysticeti_fastpath: bool,

// Make transaction context native and zero out the Move struct
#[serde(skip_serializing_if = "is_false")]
transaction_context_native: bool,
}

fn is_false(b: &bool) -> bool {
Expand Down Expand Up @@ -1615,6 +1621,10 @@ impl ProtocolConfig {
pub fn mysticeti_fastpath(&self) -> bool {
self.feature_flags.mysticeti_fastpath
}

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

#[cfg(not(msim))]
Expand Down Expand Up @@ -2808,6 +2818,9 @@ impl ProtocolConfig {
cfg.feature_flags.mysticeti_fastpath = true;
}
}
62 => {
cfg.feature_flags.transaction_context_native = false;
}
// Use this template when making changes:
//
// // modify an existing constant.
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-types/src/base_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,10 @@ impl TxContext {
self.epoch
}

pub fn epoch_timestamp_ms(&self) -> CheckpointTimestamp {
self.epoch_timestamp_ms
}

/// Derive a globally unique object ID by hashing self.digest | self.ids_created
pub fn fresh_id(&mut self) -> ObjectID {
let id = ObjectID::derive_id(self.digest(), self.ids_created);
Expand Down
15 changes: 12 additions & 3 deletions sui-execution/latest/sui-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

pub use checked::*;

#[sui_macros::with_checked_arithmetic]
mod checked {
#[cfg(feature = "gas-profiler")]
Expand All @@ -23,11 +24,15 @@ mod checked {
native_functions::NativeFunctionTable,
};
use sui_move_natives::object_runtime;
use sui_types::metrics::BytecodeVerifierMetrics;
use sui_types::{base_types::TxContext, metrics::BytecodeVerifierMetrics};
use sui_verifier::check_for_verifier_timeout;
use tracing::instrument;

use sui_move_natives::{object_runtime::ObjectRuntime, NativesCostTable};
use sui_move_natives::{
object_runtime::ObjectRuntime,
native_tx_context::NativeTxContext,
NativesCostTable,
};
use sui_protocol_config::ProtocolConfig;
use sui_types::{
base_types::*,
Expand Down Expand Up @@ -84,8 +89,9 @@ mod checked {
is_metered: bool,
protocol_config: &'r ProtocolConfig,
metrics: Arc<LimitsMetrics>,
current_epoch_id: EpochId,
tx_context: &TxContext,
) -> NativeContextExtensions<'r> {
let current_epoch_id = tx_context.epoch();
let mut extensions = NativeContextExtensions::default();
extensions.add(ObjectRuntime::new(
child_resolver,
Expand All @@ -96,6 +102,9 @@ mod checked {
current_epoch_id,
));
extensions.add(NativesCostTable::from_protocol_config(protocol_config));
if protocol_config.transaction_context_native() {
extensions.add(NativeTxContext::from(tx_context));
}
extensions
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ mod checked {
!gas_charger.is_unmetered(),
protocol_config,
metrics.clone(),
tx_context.epoch(),
tx_context,
);

// Set the profiler if in CLI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod checked {
RESOLVED_STD_OPTION, RESOLVED_UTF8_STR, TX_CONTEXT_MODULE_NAME, TX_CONTEXT_STRUCT_NAME,
},
coin::Coin,
digests::TransactionDigest,
error::{command_argument_error, ExecutionError, ExecutionErrorKind},
id::{RESOLVED_SUI_ID, UID},
metrics::LimitsMetrics,
Expand Down Expand Up @@ -760,12 +761,30 @@ mod checked {
tx_context_kind: TxContextKind,
mut serialized_arguments: Vec<Vec<u8>>,
) -> Result<SerializedReturnValues, ExecutionError> {
let is_txctx_native = context.protocol_config.transaction_context_native();

match tx_context_kind {
TxContextKind::None => (),
TxContextKind::Mutable | TxContextKind::Immutable => {
serialized_arguments.push(context.tx_context.to_vec());
// build a TxContext for Move.
// When TxContext is native, it just pushes a zero'd out value
let tx_context = if is_txctx_native {
// zero out TxContext move value. TxContext API is native
TxContext::new_from_components(
&SuiAddress::ZERO,
&TransactionDigest::ZERO,
&0u64,
0u64,
).to_vec()
} else {
// legacy TxContext model. Copied on every move call
context.tx_context.to_vec()
};
// write the TxContext value either in native or non native mode
serialized_arguments.push(tx_context);
}
}

// script visibility checked manually for entry points
let mut result = context
.execute_function_bypass_visibility(
Expand All @@ -784,15 +803,20 @@ mod checked {
// Move VM (e.g. to account for the number of created
// objects).
if tx_context_kind == TxContextKind::Mutable {
// pop the TxContext value if there
let Some((_, ctx_bytes, _)) = result.mutable_reference_outputs.pop() else {
invariant_violation!("Missing TxContext in reference outputs");
};
let updated_ctx: TxContext = bcs::from_bytes(&ctx_bytes).map_err(|e| {
ExecutionError::invariant_violation(format!(
"Unable to deserialize TxContext bytes. {e}"
))
})?;
context.tx_context.update_state(updated_ctx)?;
// if in legacy mode, update the Rust TxContext value, otherwise it's in the
// native extension and it gets updated at the end of the PTB
if !is_txctx_native {
let updated_ctx = bcs::from_bytes(&ctx_bytes).map_err(|e| {
ExecutionError::invariant_violation(format!(
"Unable to deserialize TxContext bytes. {e}"
))
})?;
context.tx_context.update_state(updated_ctx)?;
};
}
Ok(result)
}
Expand Down
26 changes: 26 additions & 0 deletions sui-execution/latest/sui-move-natives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod transfer;
mod tx_context;
mod types;
mod validator;
pub mod native_tx_context;

#[derive(Tid)]
pub struct NativesCostTable {
Expand Down Expand Up @@ -987,6 +988,31 @@ pub fn all_natives(silent: bool, protocol_config: &ProtocolConfig) -> NativeFunc
"derive_id",
make_native!(tx_context::derive_id),
),
(
"tx_context",
"native_sender",
make_native!(tx_context::native_sender),
),
(
"tx_context",
"native_digest",
make_native!(tx_context::native_digest),
),
(
"tx_context",
"native_epoch",
make_native!(tx_context::native_epoch),
),
(
"tx_context",
"native_epoch_timestamp_ms",
make_native!(tx_context::native_epoch_timestamp_ms),
),
(
"tx_context",
"native_sponsor",
make_native!(tx_context::native_sponsor),
),
(
"types",
"is_one_time_witness",
Expand Down
33 changes: 33 additions & 0 deletions sui-execution/latest/sui-move-natives/src/native_tx_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use better_any::{Tid, TidAble};
use move_core_types::account_address::AccountAddress;
use sui_types::base_types::{EpochId, TransactionDigest, TxContext};
use sui_types::messages_checkpoint::CheckpointTimestamp;

#[derive(Debug, Tid)]
pub struct NativeTxContext {
/// Signer/sender of the transaction
pub sender: AccountAddress,
/// Digest of the current transaction
pub digest: TransactionDigest,
/// The current epoch number
pub epoch: EpochId,
/// Timestamp that the epoch started at
pub epoch_timestamp_ms: CheckpointTimestamp,
/// Number of `ObjectID`'s generated during execution of the current transaction
pub ids_created: u64,
}

impl From<&TxContext> for NativeTxContext {
fn from(tx_context: &TxContext) -> Self {
NativeTxContext {
sender: AccountAddress::new(tx_context.sender().to_inner()),
digest: tx_context.digest(),
epoch: tx_context.epoch(),
epoch_timestamp_ms: tx_context.epoch_timestamp_ms(),
ids_created: 0,
}
}
}
70 changes: 70 additions & 0 deletions sui-execution/latest/sui-move-natives/src/tx_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,73 @@ pub fn derive_id(
smallvec![Value::address(address)],
))
}

/***************************************************************************************************
* native fun native_sender(): address;
**************************************************************************************************/
pub fn native_sender(
context: &mut NativeContext,
_ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
Ok(NativeResult::ok(
context.gas_used(),
smallvec![Value::address(AccountAddress::ZERO)],
))
}

/***************************************************************************************************
* native fun native_digest(): &vector<u8>;
**************************************************************************************************/
pub fn native_digest(
context: &mut NativeContext,
_ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
Ok(NativeResult::ok(
context.gas_used(),
smallvec![Value::address(AccountAddress::ZERO)],
))
}

/***************************************************************************************************
* native fun native_epoch(): u64;
**************************************************************************************************/
pub fn native_epoch(
context: &mut NativeContext,
_ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
Ok(NativeResult::ok(
context.gas_used(),
smallvec![Value::u64(0)],
))
}

/***************************************************************************************************
* native fun native_epoch_timestamp_ms(): u64;
**************************************************************************************************/
pub fn native_epoch_timestamp_ms(
context: &mut NativeContext,
_ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
Ok(NativeResult::ok(
context.gas_used(),
smallvec![Value::u64(0)],
))
}

/***************************************************************************************************
* native fun sponsor(): address;
**************************************************************************************************/
pub fn native_sponsor(
context: &mut NativeContext,
_ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
Ok(NativeResult::ok(
context.gas_used(),
smallvec![Value::address(AccountAddress::ZERO)],
))
}

0 comments on commit 6dcf7ed

Please sign in to comment.