From 087b2a723ea730253bf2b7d705d09bc57b68a48a Mon Sep 17 00:00:00 2001 From: Joshua Primero Date: Tue, 13 Aug 2024 23:05:26 -0500 Subject: [PATCH 1/3] Add new method to transaction processor --- .../model/manifest_address_reservation.rs | 2 +- .../data/manifest/model/manifest_bucket.rs | 2 +- .../src/data/manifest/model/manifest_proof.rs | 2 +- .../transaction_processor/invocations.rs | 2 + .../src/types/node_layout.rs | 14 ++ .../assets/native_function_base_costs.csv | 1 + .../transaction_processor/blueprint.rs | 28 ++++ .../blueprints/transaction_processor/mod.rs | 2 + .../transaction_processor/package.rs | 39 +++++- .../transaction_processor/tx_processor.rs | 121 +++++++++++++----- .../system_modules/kernel_trace/module.rs | 4 +- radix-native-sdk/src/resource/worktop.rs | 3 +- .../src/validation/id_allocator.rs | 2 +- 13 files changed, 177 insertions(+), 45 deletions(-) create mode 100644 radix-engine/src/blueprints/transaction_processor/blueprint.rs diff --git a/radix-common/src/data/manifest/model/manifest_address_reservation.rs b/radix-common/src/data/manifest/model/manifest_address_reservation.rs index 24e1b90d95d..5d9cb6bd9ec 100644 --- a/radix-common/src/data/manifest/model/manifest_address_reservation.rs +++ b/radix-common/src/data/manifest/model/manifest_address_reservation.rs @@ -10,7 +10,7 @@ use crate::data::manifest::*; use crate::*; #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ScryptoSbor)] #[must_use] pub struct ManifestAddressReservation(pub u32); diff --git a/radix-common/src/data/manifest/model/manifest_bucket.rs b/radix-common/src/data/manifest/model/manifest_bucket.rs index 4e6bdb6352b..d3a27cd3c1d 100644 --- a/radix-common/src/data/manifest/model/manifest_bucket.rs +++ b/radix-common/src/data/manifest/model/manifest_bucket.rs @@ -10,7 +10,7 @@ use crate::data::manifest::*; use crate::*; #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ScryptoSbor)] #[must_use] pub struct ManifestBucket(pub u32); diff --git a/radix-common/src/data/manifest/model/manifest_proof.rs b/radix-common/src/data/manifest/model/manifest_proof.rs index 5cbb763faba..085ca975bc2 100644 --- a/radix-common/src/data/manifest/model/manifest_proof.rs +++ b/radix-common/src/data/manifest/model/manifest_proof.rs @@ -10,7 +10,7 @@ use crate::data::manifest::*; use crate::*; #[cfg_attr(feature = "fuzzing", derive(Arbitrary))] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, ScryptoSbor)] #[must_use] pub struct ManifestProof(pub u32); diff --git a/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs b/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs index 84e778150cd..b18626012f1 100644 --- a/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs +++ b/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs @@ -6,6 +6,8 @@ pub const TRANSACTION_PROCESSOR_BLUEPRINT: &str = "TransactionProcessor"; pub const TRANSACTION_PROCESSOR_RUN_IDENT: &str = "run"; +pub const TRANSACTION_PROCESSOR_NEW_IDENT: &str = "new"; + // TransactionProcessorInput in the engine pub type TransactionProcessorRunOutput = Vec; diff --git a/radix-engine-interface/src/types/node_layout.rs b/radix-engine-interface/src/types/node_layout.rs index 180e84ab318..d64dbc0ec24 100644 --- a/radix-engine-interface/src/types/node_layout.rs +++ b/radix-engine-interface/src/types/node_layout.rs @@ -152,6 +152,7 @@ blueprint_partition_offset!( } ); + //=========== // Blueprints //=========== @@ -201,6 +202,19 @@ blueprint_partition_offset!( } ); +blueprint_partition_offset!( + pub enum SubTransactionProcessorPartitionOffset { + Field, + } +); + +#[repr(u8)] +#[derive(Debug, Copy, Clone, Sbor, PartialEq, Eq, Hash, PartialOrd, Ord, FromRepr)] +pub enum SubTransactionProcessorField { + ExecutionState, +} + + #[repr(u8)] #[derive(Debug, Copy, Clone, Sbor, PartialEq, Eq, Hash, PartialOrd, Ord, FromRepr)] pub enum FungibleBucketField { diff --git a/radix-engine/assets/native_function_base_costs.csv b/radix-engine/assets/native_function_base_costs.csv index 955e93e87b7..8cec2f73de5 100644 --- a/radix-engine/assets/native_function_base_costs.csv +++ b/radix-engine/assets/native_function_base_costs.csv @@ -136,6 +136,7 @@ 0d906318c6318c61e603c64c6318c6318cf7be913d63aafbc6318c6318c6,update_non_fungible_data,1805510 0d906318c6318c659963ed8c6318c6318cf7be85a17d48bca6318c6318c6,create,3072615 0d906318c6318c659a6130cc6318c6318cf7a8ba5295eabf46318c6318c6,run,2056162 +0d906318c6318c659a6130cc6318c6318cf7a8ba5295eabf46318c6318c6,new,2056162 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,create,2237763 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,create_advanced,1709496 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,on_virtualize,1298374 diff --git a/radix-engine/src/blueprints/transaction_processor/blueprint.rs b/radix-engine/src/blueprints/transaction_processor/blueprint.rs new file mode 100644 index 00000000000..633f90cb013 --- /dev/null +++ b/radix-engine/src/blueprints/transaction_processor/blueprint.rs @@ -0,0 +1,28 @@ +use crate::blueprints::account::AccountSubstate; +use crate::blueprints::transaction_processor::TransactionProcessor; +use crate::internal_prelude::declare_native_blueprint_state; +use crate::internal_prelude::*; +use radix_engine_interface::types::*; + + + +declare_native_blueprint_state! { + blueprint_ident: SubTransactionProcessor, + blueprint_snake_case: sub_transaction_processor, + features: { + }, + fields: { + execution_state: { + ident: ExecutionState, + field_type: { + kind: StaticSingleVersioned, + }, + condition: Condition::Always, + } + }, + collections: { + } +} + + +pub type SubTransactionProcessorExecutionStateV1 = TransactionProcessor; \ No newline at end of file diff --git a/radix-engine/src/blueprints/transaction_processor/mod.rs b/radix-engine/src/blueprints/transaction_processor/mod.rs index 0473c593cb2..bdb21a21070 100644 --- a/radix-engine/src/blueprints/transaction_processor/mod.rs +++ b/radix-engine/src/blueprints/transaction_processor/mod.rs @@ -1,5 +1,7 @@ mod package; mod tx_processor; +mod blueprint; +pub use blueprint::*; pub use package::*; pub use tx_processor::*; diff --git a/radix-engine/src/blueprints/transaction_processor/package.rs b/radix-engine/src/blueprints/transaction_processor/package.rs index 27c8c0bc156..669e18db333 100644 --- a/radix-engine/src/blueprints/transaction_processor/package.rs +++ b/radix-engine/src/blueprints/transaction_processor/package.rs @@ -13,8 +13,9 @@ use radix_engine_interface::blueprints::package::{ PackageDefinition, }; use radix_engine_interface::blueprints::transaction_processor::*; +use crate::blueprints::resource::FungibleResourceManagerStateSchemaInit; -use super::TransactionProcessorBlueprint; +use super::{SubTransactionProcessorStateSchemaInit, TransactionProcessorBlueprint, TransactionProcessorNewInput, TransactionProcessorNewOutput}; use super::TransactionProcessorRunInput; use super::TransactionProcessorV1MinorVersion; @@ -24,7 +25,8 @@ impl TransactionProcessorNativePackage { pub fn definition() -> PackageDefinition { let mut aggregator = TypeAggregator::::new(); - let fields = Vec::new(); + + let state = SubTransactionProcessorStateSchemaInit::create_schema_init(&mut aggregator); let mut functions = index_map_new(); functions.insert( @@ -40,6 +42,19 @@ impl TransactionProcessorNativePackage { export: TRANSACTION_PROCESSOR_RUN_IDENT.to_string(), }, ); + functions.insert( + TRANSACTION_PROCESSOR_NEW_IDENT.to_string(), + FunctionSchemaInit { + receiver: None, + input: TypeRef::Static( + aggregator.add_child_type_and_descendents::(), + ), + output: TypeRef::Static( + aggregator.add_child_type_and_descendents::(), + ), + export: TRANSACTION_PROCESSOR_NEW_IDENT.to_string(), + }, + ); let schema = generate_full_schema(aggregator); let blueprints = indexmap!( @@ -51,10 +66,7 @@ impl TransactionProcessorNativePackage { schema: BlueprintSchemaInit { generics: vec![], schema, - state: BlueprintStateSchemaInit { - fields, - collections: vec![], - }, + state, functions: BlueprintFunctionsSchemaInit { functions, }, @@ -67,7 +79,7 @@ impl TransactionProcessorNativePackage { // Only allow the root call frame to call any function in transaction processor. // This is a safety precaution to reduce surface area of attack. This may be removed // if/when the transaction processor is verified to be safe. - function_auth: FunctionAuth::RootOnly, + function_auth: FunctionAuth::AllowAll, method_auth: MethodAuthTemplate::AllowAll, }, } @@ -100,6 +112,19 @@ impl TransactionProcessorNativePackage { Ok(IndexedScryptoValue::from_typed(&rtn)) } + TRANSACTION_PROCESSOR_NEW_IDENT => { + let input: TransactionProcessorNewInput = input.as_typed().map_err(|e| { + RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e)) + })?; + + let rtn = TransactionProcessorBlueprint::new( + input.manifest, + input.global_address_reservations, + api, + )?; + + Ok(IndexedScryptoValue::from_typed(&rtn)) + } _ => Err(RuntimeError::ApplicationError( ApplicationError::ExportDoesNotExist(export_name.to_string()), )), diff --git a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs index 2cfa0bb2907..62f40ef257e 100644 --- a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs +++ b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs @@ -20,6 +20,7 @@ use radix_transactions::data::TransformHandler; use radix_transactions::model::*; use radix_transactions::validation::*; use sbor::rust::prelude::*; +use crate::blueprints::transaction_processor::SubTransactionProcessorExecutionStateFieldPayload; #[cfg(not(feature = "coverage"))] pub const MAX_TOTAL_BLOB_SIZE_PER_INVOCATION: usize = 1024 * 1024; @@ -62,6 +63,15 @@ pub struct TransactionProcessorRunInputEfficientEncodable { pub references: IndexSet, } +#[derive(Debug, Eq, PartialEq, ScryptoSbor)] +pub struct TransactionProcessorNewInput { + pub manifest: TransactionManifest, + pub global_address_reservations: Vec, +} + +pub type TransactionProcessorNewOutput = Own; + + #[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] pub enum TransactionProcessorError { BucketNotFound(u32), @@ -129,23 +139,41 @@ impl TransactionProcessorBlueprint { Y: SystemApi + KernelNodeApi + KernelSubstateApi, L: Default, >( - manifests: Vec, + mut manifests: Vec, global_address_reservations: Vec, _references: Vec, // Required so that the kernel passes the references to the processor frame version: TransactionProcessorV1MinorVersion, api: &mut Y, ) -> Result, RuntimeError> { let root_thread = manifests.get(0).unwrap().id; - let mut threads = { + let mut main_thread = TransactionProcessor::init( + manifests.remove(0), + global_address_reservations.clone(), + version, + api, + )?; + let mut child_threads = { let mut threads = btreemap!(); - for manifest in manifests.into_iter() { + for manifest in manifests { let id = manifest.id; + let thread: Own = scrypto_decode(&api.call_function( + TRANSACTION_PROCESSOR_PACKAGE, + TRANSACTION_PROCESSOR_BLUEPRINT, + TRANSACTION_PROCESSOR_NEW_IDENT, + scrypto_encode(&TransactionProcessorNewInput { + manifest, + global_address_reservations: global_address_reservations.clone(), + }).unwrap() + )?).unwrap(); + + /* let thread = TransactionProcessor::init( manifest, global_address_reservations.clone(), version, api, )?; + */ let parent = if id.eq(&root_thread) { None } else { @@ -160,12 +188,17 @@ impl TransactionProcessorBlueprint { let mut cur_thread = root_thread; let mut received_value = None; loop { - let (processor, parent) = threads.get_mut(&cur_thread).unwrap(); - let result = processor.execute(api, received_value.take())?; - if cur_thread.eq(&root_thread) { + let (parent, state) = if cur_thread.eq(&root_thread) { + let result = main_thread.execute(api, received_value.take())?; output.extend(result.outputs); + (Option::::None, result.state) + } else { + let (processor, parent) = child_threads.get_mut(&cur_thread).unwrap(); + todo!(); + }; + if cur_thread.eq(&root_thread) { } - match result.state { + match state { TransactionProcessorState::YieldToChild(hash, value) => { received_value = Some(value); todo!() @@ -177,7 +210,7 @@ impl TransactionProcessorBlueprint { TransactionProcessorState::Done => { if let Some(parent) = parent { // Parent should never be done while children are running - cur_thread = *parent; + cur_thread = parent; } else { break; } @@ -187,8 +220,31 @@ impl TransactionProcessorBlueprint { Ok(output) } + + pub(crate) fn new< + Y: SystemApi + KernelNodeApi + KernelSubstateApi, + L: Default, + >( + manifest: TransactionManifest, + global_address_reservations: Vec, + api: &mut Y, + ) -> Result { + let processor = TransactionProcessor::init( + manifest, + global_address_reservations, + TransactionProcessorV1MinorVersion::One, + api, + )?; + let node = api.new_simple_object( + TRANSACTION_PROCESSOR_BLUEPRINT, + indexmap!(0 => FieldValue::new(SubTransactionProcessorExecutionStateFieldPayload::from_content_source(processor))) + )?; + Ok(Own(node)) + } } + + struct TransactionProcessorExecuteResult { outputs: Vec, state: TransactionProcessorState, @@ -200,12 +256,13 @@ enum TransactionProcessorState { Done, } -struct TransactionProcessor { - version: TransactionProcessorV1MinorVersion, - worktop: Worktop, - cur_instruction: usize, - instructions: Vec, - processor: TransactionProcessorMapping, +#[derive(ScryptoSbor, Debug, PartialEq, Eq)] +pub struct TransactionProcessor { + pub version: TransactionProcessorV1MinorVersion, + pub worktop: Worktop, + pub cur_instruction: usize, + pub instructions: Vec, + pub processor: TransactionProcessorMapping, } impl TransactionProcessor { @@ -240,14 +297,7 @@ impl TransactionProcessor { api.kernel_pin_node(worktop_node_id)?; let worktop = Worktop(Own(worktop_node_id)); - let instructions = - manifest_decode::>(&manifest.manifest_encoded_instructions) - .map_err(|e| { - // This error should never occur if being called from root since this is constructed - // by the transaction executor. This error is more to protect against application - // space calling this function if/when possible - RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e)) - })?; + let processor = TransactionProcessorMapping::new(manifest.blobs, global_address_reservations); @@ -255,7 +305,7 @@ impl TransactionProcessor { version, worktop, cur_instruction: 0usize, - instructions, + instructions: manifest.manifest_encoded_instructions, processor, }) } @@ -270,10 +320,18 @@ impl TransactionProcessor { .handle_call_return_data(&value, &self.worktop, api)?; } + let instructions = + manifest_decode::>(&self.instructions) + .map_err(|e| { + // This error should never occur if being called from root since this is constructed + // by the transaction executor. This error is more to protect against application + // space calling this function if/when possible + RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e)) + })?; + let mut outputs = Vec::new(); - for (index, inst) in self - .instructions + for (index, inst) in instructions .iter() .enumerate() .skip(self.cur_instruction) @@ -635,11 +693,12 @@ impl TransactionProcessor { } } +#[derive(ScryptoSbor, Debug, PartialEq, Eq)] struct TransactionProcessorMapping { - bucket_mapping: NonIterMap, + bucket_mapping: IndexMap, proof_mapping: IndexMap, - address_reservation_mapping: NonIterMap, - address_mapping: NonIterMap, + address_reservation_mapping: IndexMap, + address_mapping: IndexMap, id_allocator: ManifestIdAllocator, blobs_by_hash: IndexMap>, } @@ -652,9 +711,9 @@ impl TransactionProcessorMapping { let mut processor = Self { blobs_by_hash, proof_mapping: index_map_new(), - bucket_mapping: NonIterMap::new(), - address_reservation_mapping: NonIterMap::new(), - address_mapping: NonIterMap::new(), + bucket_mapping: index_map_new(), + address_reservation_mapping: index_map_new(), + address_mapping: index_map_new(), id_allocator: ManifestIdAllocator::new(), }; diff --git a/radix-engine/src/system/system_modules/kernel_trace/module.rs b/radix-engine/src/system/system_modules/kernel_trace/module.rs index 8a95e32470c..4cd78833ce4 100644 --- a/radix-engine/src/system/system_modules/kernel_trace/module.rs +++ b/radix-engine/src/system/system_modules/kernel_trace/module.rs @@ -20,8 +20,8 @@ pub struct KernelTraceModule; #[macro_export] macro_rules! log { ( $api: expr, $msg: expr $( , $arg:expr )* ) => { - #[cfg(not(feature = "alloc"))] - println!("{}[{}] {}", " ".repeat($api.kernel_get_current_depth()), $api.kernel_get_current_depth(), sbor::rust::format!($msg, $( $arg ),*)); + //#[cfg(not(feature = "alloc"))] + //println!("{}[{}] {}", " ".repeat($api.kernel_get_current_depth()), $api.kernel_get_current_depth(), sbor::rust::format!($msg, $( $arg ),*)); }; } diff --git a/radix-native-sdk/src/resource/worktop.rs b/radix-native-sdk/src/resource/worktop.rs index 790003847c0..2d17700d8b6 100644 --- a/radix-native-sdk/src/resource/worktop.rs +++ b/radix-native-sdk/src/resource/worktop.rs @@ -2,6 +2,7 @@ use radix_common::constants::RESOURCE_PACKAGE; use radix_common::data::scrypto::model::*; use radix_common::data::scrypto::{scrypto_decode, scrypto_encode}; use radix_common::math::Decimal; +use radix_common::ScryptoSbor; use radix_engine_interface::api::*; use radix_engine_interface::blueprints::resource::*; use radix_engine_interface::types::*; @@ -9,7 +10,7 @@ use sbor::rust::collections::IndexSet; use sbor::rust::fmt::Debug; use sbor::rust::vec::Vec; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ScryptoSbor)] pub struct Worktop(pub Own); impl Worktop { diff --git a/radix-transactions/src/validation/id_allocator.rs b/radix-transactions/src/validation/id_allocator.rs index 935d8709be9..656d3934bdc 100644 --- a/radix-transactions/src/validation/id_allocator.rs +++ b/radix-transactions/src/validation/id_allocator.rs @@ -1,6 +1,6 @@ use crate::internal_prelude::*; -#[derive(Default, Debug, Clone, PartialEq, Eq)] +#[derive(Default, Debug, Clone, PartialEq, Eq, ScryptoSbor)] pub struct ManifestIdAllocator { next_bucket_id: u32, next_proof_id: u32, From 132d994c0ced8c5bbf19e66d62c0f3f3be544ddd Mon Sep 17 00:00:00 2001 From: Joshua Primero Date: Tue, 13 Aug 2024 23:22:10 -0500 Subject: [PATCH 2/3] Add execute method to transaction processor --- .../transaction_processor/invocations.rs | 2 + .../transaction_processor/package.rs | 27 ++++++++++- .../transaction_processor/tx_processor.rs | 45 ++++++++++++++++++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs b/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs index b18626012f1..956a47c1408 100644 --- a/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs +++ b/radix-engine-interface/src/blueprints/transaction_processor/invocations.rs @@ -8,6 +8,8 @@ pub const TRANSACTION_PROCESSOR_RUN_IDENT: &str = "run"; pub const TRANSACTION_PROCESSOR_NEW_IDENT: &str = "new"; +pub const TRANSACTION_PROCESSOR_EXECUTE_IDENT: &str = "execute"; + // TransactionProcessorInput in the engine pub type TransactionProcessorRunOutput = Vec; diff --git a/radix-engine/src/blueprints/transaction_processor/package.rs b/radix-engine/src/blueprints/transaction_processor/package.rs index 669e18db333..2cdbae2878f 100644 --- a/radix-engine/src/blueprints/transaction_processor/package.rs +++ b/radix-engine/src/blueprints/transaction_processor/package.rs @@ -15,7 +15,7 @@ use radix_engine_interface::blueprints::package::{ use radix_engine_interface::blueprints::transaction_processor::*; use crate::blueprints::resource::FungibleResourceManagerStateSchemaInit; -use super::{SubTransactionProcessorStateSchemaInit, TransactionProcessorBlueprint, TransactionProcessorNewInput, TransactionProcessorNewOutput}; +use super::{SubTransactionProcessorStateSchemaInit, TransactionProcessorBlueprint, TransactionProcessorExecuteInput, TransactionProcessorExecuteOutput, TransactionProcessorNewInput, TransactionProcessorNewOutput}; use super::TransactionProcessorRunInput; use super::TransactionProcessorV1MinorVersion; @@ -55,6 +55,19 @@ impl TransactionProcessorNativePackage { export: TRANSACTION_PROCESSOR_NEW_IDENT.to_string(), }, ); + functions.insert( + TRANSACTION_PROCESSOR_EXECUTE_IDENT.to_string(), + FunctionSchemaInit { + receiver: Some(ReceiverInfo::normal_ref_mut()), + input: TypeRef::Static( + aggregator.add_child_type_and_descendents::(), + ), + output: TypeRef::Static( + aggregator.add_child_type_and_descendents::(), + ), + export: TRANSACTION_PROCESSOR_EXECUTE_IDENT.to_string(), + }, + ); let schema = generate_full_schema(aggregator); let blueprints = indexmap!( @@ -125,6 +138,18 @@ impl TransactionProcessorNativePackage { Ok(IndexedScryptoValue::from_typed(&rtn)) } + TRANSACTION_PROCESSOR_EXECUTE_IDENT => { + let input: TransactionProcessorExecuteInput = input.as_typed().map_err(|e| { + RuntimeError::ApplicationError(ApplicationError::InputDecodeError(e)) + })?; + + let rtn = TransactionProcessorBlueprint::execute( + input, + api, + )?; + + Ok(IndexedScryptoValue::from_typed(&rtn)) + } _ => Err(RuntimeError::ApplicationError( ApplicationError::ExportDoesNotExist(export_name.to_string()), )), diff --git a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs index 62f40ef257e..c3e6fc1f962 100644 --- a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs +++ b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs @@ -20,7 +20,7 @@ use radix_transactions::data::TransformHandler; use radix_transactions::model::*; use radix_transactions::validation::*; use sbor::rust::prelude::*; -use crate::blueprints::transaction_processor::SubTransactionProcessorExecutionStateFieldPayload; +use crate::blueprints::transaction_processor::{SubTransactionProcessorExecutionStateFieldPayload, SubTransactionProcessorExecutionStateFieldSubstate}; #[cfg(not(feature = "coverage"))] pub const MAX_TOTAL_BLOB_SIZE_PER_INVOCATION: usize = 1024 * 1024; @@ -69,6 +69,9 @@ pub struct TransactionProcessorNewInput { pub global_address_reservations: Vec, } +pub type TransactionProcessorExecuteInput = ScryptoValue; +pub type TransactionProcessorExecuteOutput = TransactionProcessorExecutionOutput; + pub type TransactionProcessorNewOutput = Own; @@ -194,7 +197,18 @@ impl TransactionProcessorBlueprint { (Option::::None, result.state) } else { let (processor, parent) = child_threads.get_mut(&cur_thread).unwrap(); - todo!(); + let rtn = api.call_method( + processor.as_node_id(), + TRANSACTION_PROCESSOR_EXECUTE_IDENT, + scrypto_encode(&received_value.take().map(|i| i.to_scrypto_value())).unwrap() + )?; + let rtn: TransactionProcessorExecutionOutput = scrypto_decode(&rtn).unwrap(); + let rtn = match rtn { + TransactionProcessorExecutionOutput::Done => TransactionProcessorState::Done, + TransactionProcessorExecutionOutput::YieldToChild(child, value) => TransactionProcessorState::YieldToChild(child, IndexedScryptoValue::from_scrypto_value(value)), + TransactionProcessorExecutionOutput::YieldToParent(value) => TransactionProcessorState::YieldToParent(IndexedScryptoValue::from_scrypto_value(value)), + }; + (*parent, rtn) }; if cur_thread.eq(&root_thread) { } @@ -241,6 +255,26 @@ impl TransactionProcessorBlueprint { )?; Ok(Own(node)) } + + pub(crate) fn execute< + Y: SystemApi + KernelNodeApi + KernelSubstateApi, + L: Default, + >( + input: ScryptoValue, + api: &mut Y, + ) -> Result { + let field = api.actor_open_field(ACTOR_STATE_SELF, 0, LockFlags::MUTABLE)?; + let payload: SubTransactionProcessorExecutionStateFieldPayload = api.field_read_typed(field)?; + let mut state = payload.into_unique_version(); + let output = state.execute(api, Some(IndexedScryptoValue::from_scrypto_value(input)))?; + let rtn = match output.state { + TransactionProcessorState::Done => TransactionProcessorExecutionOutput::Done, + TransactionProcessorState::YieldToParent(value) => TransactionProcessorExecutionOutput::YieldToParent(value.to_scrypto_value()), + TransactionProcessorState::YieldToChild(hash, value) => TransactionProcessorExecutionOutput::YieldToChild(hash, value.to_scrypto_value()), + }; + + Ok(rtn) + } } @@ -250,6 +284,13 @@ struct TransactionProcessorExecuteResult { state: TransactionProcessorState, } +#[derive(ScryptoSbor, Debug, PartialEq, Eq)] +pub enum TransactionProcessorExecutionOutput { + YieldToChild(Hash, ScryptoValue), + YieldToParent(ScryptoValue), + Done, +} + enum TransactionProcessorState { YieldToChild(Hash, IndexedScryptoValue), YieldToParent(IndexedScryptoValue), From 0c05b3b54a080857943b06fbfb60c9b3f13a82ff Mon Sep 17 00:00:00 2001 From: Joshua Primero Date: Tue, 13 Aug 2024 23:56:20 -0500 Subject: [PATCH 3/3] Add working example without auth --- radix-engine-tests/tests/intents.rs | 4 +++ .../assets/native_function_base_costs.csv | 1 + .../transaction_processor/package.rs | 1 + .../transaction_processor/tx_processor.rs | 28 +++++++++++++++---- radix-engine/src/kernel/call_frame.rs | 4 ++- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/radix-engine-tests/tests/intents.rs b/radix-engine-tests/tests/intents.rs index 0304864c718..a265b75c845 100644 --- a/radix-engine-tests/tests/intents.rs +++ b/radix-engine-tests/tests/intents.rs @@ -52,6 +52,10 @@ fn swap_with_intents_should_work() { let execution_config = { let mut execution_config = ExecutionConfig::for_test_transaction(); + execution_config.system_overrides = Some(SystemOverrides { + disable_auth: true, + ..Default::default() + }); execution_config.enable_kernel_trace = false; execution_config }; diff --git a/radix-engine/assets/native_function_base_costs.csv b/radix-engine/assets/native_function_base_costs.csv index 8cec2f73de5..d165c9b8d6e 100644 --- a/radix-engine/assets/native_function_base_costs.csv +++ b/radix-engine/assets/native_function_base_costs.csv @@ -137,6 +137,7 @@ 0d906318c6318c659963ed8c6318c6318cf7be85a17d48bca6318c6318c6,create,3072615 0d906318c6318c659a6130cc6318c6318cf7a8ba5295eabf46318c6318c6,run,2056162 0d906318c6318c659a6130cc6318c6318cf7a8ba5295eabf46318c6318c6,new,2056162 +0d906318c6318c659a6130cc6318c6318cf7a8ba5295eabf46318c6318c6,execute,2056162 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,create,2237763 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,create_advanced,1709496 0d906318c6318c66cd64318c6318c6318cf79e9a7f8f179ca6318c6318c6,on_virtualize,1298374 diff --git a/radix-engine/src/blueprints/transaction_processor/package.rs b/radix-engine/src/blueprints/transaction_processor/package.rs index 2cdbae2878f..a068c25cf74 100644 --- a/radix-engine/src/blueprints/transaction_processor/package.rs +++ b/radix-engine/src/blueprints/transaction_processor/package.rs @@ -133,6 +133,7 @@ impl TransactionProcessorNativePackage { let rtn = TransactionProcessorBlueprint::new( input.manifest, input.global_address_reservations, + input.references, api, )?; diff --git a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs index c3e6fc1f962..4b98ecdd145 100644 --- a/radix-engine/src/blueprints/transaction_processor/tx_processor.rs +++ b/radix-engine/src/blueprints/transaction_processor/tx_processor.rs @@ -67,6 +67,7 @@ pub struct TransactionProcessorRunInputEfficientEncodable { pub struct TransactionProcessorNewInput { pub manifest: TransactionManifest, pub global_address_reservations: Vec, + pub references: Vec, // Required so that the kernel passes the references to the processor frame } pub type TransactionProcessorExecuteInput = ScryptoValue; @@ -144,7 +145,7 @@ impl TransactionProcessorBlueprint { >( mut manifests: Vec, global_address_reservations: Vec, - _references: Vec, // Required so that the kernel passes the references to the processor frame + references: Vec, // Required so that the kernel passes the references to the processor frame version: TransactionProcessorV1MinorVersion, api: &mut Y, ) -> Result, RuntimeError> { @@ -153,6 +154,7 @@ impl TransactionProcessorBlueprint { manifests.remove(0), global_address_reservations.clone(), version, + references.clone(), api, )?; let mut child_threads = { @@ -166,6 +168,7 @@ impl TransactionProcessorBlueprint { scrypto_encode(&TransactionProcessorNewInput { manifest, global_address_reservations: global_address_reservations.clone(), + references: references.clone(), }).unwrap() )?).unwrap(); @@ -210,22 +213,29 @@ impl TransactionProcessorBlueprint { }; (*parent, rtn) }; - if cur_thread.eq(&root_thread) { - } match state { TransactionProcessorState::YieldToChild(hash, value) => { received_value = Some(value); - todo!() + cur_thread = hash; } TransactionProcessorState::YieldToParent(value) => { received_value = Some(value); - todo!() + cur_thread = parent.unwrap(); } TransactionProcessorState::Done => { if let Some(parent) = parent { + let (processor, _) = child_threads.remove(&cur_thread).unwrap(); + let dropped_obj = api.drop_object(processor.as_node_id())?; + let payload: SubTransactionProcessorExecutionStateFieldPayload = scrypto_decode(&dropped_obj[0]).unwrap(); + payload.into_unique_version().worktop.drop(api)?; + // Parent should never be done while children are running cur_thread = parent; } else { + main_thread.worktop.drop(api)?; + if !child_threads.is_empty() { + println!("OOPS"); + } break; } } @@ -241,12 +251,14 @@ impl TransactionProcessorBlueprint { >( manifest: TransactionManifest, global_address_reservations: Vec, + references: Vec, api: &mut Y, ) -> Result { let processor = TransactionProcessor::init( manifest, global_address_reservations, TransactionProcessorV1MinorVersion::One, + references, api, )?; let node = api.new_simple_object( @@ -267,6 +279,7 @@ impl TransactionProcessorBlueprint { let payload: SubTransactionProcessorExecutionStateFieldPayload = api.field_read_typed(field)?; let mut state = payload.into_unique_version(); let output = state.execute(api, Some(IndexedScryptoValue::from_scrypto_value(input)))?; + api.field_write_typed(field, &SubTransactionProcessorExecutionStateFieldPayload::from_content_source(state))?; let rtn = match output.state { TransactionProcessorState::Done => TransactionProcessorExecutionOutput::Done, TransactionProcessorState::YieldToParent(value) => TransactionProcessorExecutionOutput::YieldToParent(value.to_scrypto_value()), @@ -304,6 +317,7 @@ pub struct TransactionProcessor { pub cur_instruction: usize, pub instructions: Vec, pub processor: TransactionProcessorMapping, + pub references: Vec, // Required so that the kernel passes the references to the processor frame } impl TransactionProcessor { @@ -311,6 +325,7 @@ impl TransactionProcessor { manifest: TransactionManifest, global_address_reservations: Vec, version: TransactionProcessorV1MinorVersion, + references: Vec, api: &mut Y, ) -> Result { // Create a worktop @@ -348,6 +363,7 @@ impl TransactionProcessor { cur_instruction: 0usize, instructions: manifest.manifest_encoded_instructions, processor, + references, }) } @@ -725,7 +741,7 @@ impl TransactionProcessor { outputs.push(result); } - self.worktop.drop(api)?; + // self.worktop.drop(api)?; Ok(TransactionProcessorExecuteResult { outputs, diff --git a/radix-engine/src/kernel/call_frame.rs b/radix-engine/src/kernel/call_frame.rs index 9e506386cd2..483cb6d810a 100644 --- a/radix-engine/src/kernel/call_frame.rs +++ b/radix-engine/src/kernel/call_frame.rs @@ -604,7 +604,9 @@ impl CallFrame { // Copy references and move nodes Self::pass_message(substate_io, parent, &mut frame, message) - .map_err(CreateFrameError::PassMessageError)?; + .map_err(|e| { + CreateFrameError::PassMessageError(e) + })?; Ok(frame) }