From 43a3ed852fd45a1a82f3d696740cc9ea5e9225e5 Mon Sep 17 00:00:00 2001 From: heytdep Date: Wed, 6 Nov 2024 16:55:41 +0700 Subject: [PATCH 1/6] add opt in reentrancy to soroban --- soroban-env-common/env.json | 42 +++ soroban-env-host/src/host.rs | 91 ++--- soroban-env-host/src/host/frame.rs | 94 +++++ soroban-env-host/src/test/lifecycle.rs | 58 ++++ soroban-test-wasms/src/lib.rs | 11 + soroban-test-wasms/wasm-workspace/Cargo.lock | 323 ++++++++++-------- soroban-test-wasms/wasm-workspace/Cargo.toml | 5 +- .../wasm-workspace/no_reentry_b/Cargo.toml | 19 ++ .../wasm-workspace/no_reentry_b/src/lib.rs | 27 ++ .../opt/23/example_no_reentry_b.wasm | Bin 0 -> 1311 bytes .../opt/23/example_reentry_a.wasm | Bin 0 -> 2244 bytes .../opt/23/example_reentry_b.wasm | Bin 0 -> 1311 bytes .../wasm-workspace/reentry_a/Cargo.toml | 19 ++ .../wasm-workspace/reentry_a/src/lib.rs | 31 ++ .../wasm-workspace/reentry_b/Cargo.toml | 19 ++ .../wasm-workspace/reentry_b/src/lib.rs | 27 ++ 16 files changed, 567 insertions(+), 199 deletions(-) create mode 100644 soroban-test-wasms/wasm-workspace/no_reentry_b/Cargo.toml create mode 100644 soroban-test-wasms/wasm-workspace/no_reentry_b/src/lib.rs create mode 100755 soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_b.wasm create mode 100755 soroban-test-wasms/wasm-workspace/opt/23/example_reentry_a.wasm create mode 100755 soroban-test-wasms/wasm-workspace/opt/23/example_reentry_b.wasm create mode 100644 soroban-test-wasms/wasm-workspace/reentry_a/Cargo.toml create mode 100644 soroban-test-wasms/wasm-workspace/reentry_a/src/lib.rs create mode 100644 soroban-test-wasms/wasm-workspace/reentry_b/Cargo.toml create mode 100644 soroban-test-wasms/wasm-workspace/reentry_b/src/lib.rs diff --git a/soroban-env-common/env.json b/soroban-env-common/env.json index d421dca2f..ac8af0b11 100644 --- a/soroban-env-common/env.json +++ b/soroban-env-common/env.json @@ -1560,6 +1560,48 @@ ], "return": "Val", "docs": "Calls a function in another contract with arguments contained in vector `args`, returning either the result of the called function or an `Error` if the called function failed. The returned error is either a custom `ContractError` that the called contract returns explicitly, or an error with type `Context` and code `InvalidAction` in case of any other error in the called contract (such as a host function failure that caused a trap). `try_call` might trap in a few scenarios where the error can't be meaningfully recovered from, such as running out of budget." + }, + { + "export": "1", + "name": "call_reentrant", + "args": [ + { + "name": "contract", + "type": "AddressObject" + }, + { + "name": "func", + "type": "Symbol" + }, + { + "name": "args", + "type": "VecObject" + } + ], + "return": "Val", + "docs": "Calls a function in another contract with arguments contained in vector `args`. If the call is successful, returns the result of the called function. Traps otherwise. This functions enables re-entrancy in the immediate cross-contract call.", + "min_supported_protocol": 21 + }, + { + "export": "2", + "name": "try_call_reentrant", + "args": [ + { + "name": "contract", + "type": "AddressObject" + }, + { + "name": "func", + "type": "Symbol" + }, + { + "name": "args", + "type": "VecObject" + } + ], + "return": "Val", + "docs": "Calls a function in another contract with arguments contained in vector `args`, returning either the result of the called function or an `Error` if the called function failed. The returned error is either a custom `ContractError` that the called contract returns explicitly, or an error with type `Context` and code `InvalidAction` in case of any other error in the called contract (such as a host function failure that caused a trap). `try_call` might trap in a few scenarios where the error can't be meaningfully recovered from, such as running out of budget. This functions enables re-entrancy in the immediate cross-contract call.", + "min_supported_protocol": 21 } ] }, diff --git a/soroban-env-host/src/host.rs b/soroban-env-host/src/host.rs index c371ba460..c5680ef7a 100644 --- a/soroban-env-host/src/host.rs +++ b/soroban-env-host/src/host.rs @@ -2369,23 +2369,8 @@ impl VmCallerEnv for Host { func: Symbol, args: VecObject, ) -> Result { - let argvec = self.call_args_from_obj(args)?; - // this is the recommended path of calling a contract, with `reentry` - // always set `ContractReentryMode::Prohibited` - let res = self.call_n_internal( - &self.contract_id_from_address(contract_address)?, - func, - argvec.as_slice(), - CallParams::default_external_call(), - ); - if let Err(e) = &res { - self.error( - e.error, - "contract call failed", - &[func.to_val(), args.to_val()], - ); - } - res + let call_params = CallParams::default_external_call(); + self.call_with_params(contract_address, func, args, call_params) } // Notes on metering: covered by the components. @@ -2396,54 +2381,30 @@ impl VmCallerEnv for Host { func: Symbol, args: VecObject, ) -> Result { - let argvec = self.call_args_from_obj(args)?; - // this is the "loosened" path of calling a contract. - // TODO: A `reentry` flag will be passed from `try_call` into here. - // For now, we are passing in `ContractReentryMode::Prohibited` to disable - // reentry. - let res = self.call_n_internal( - &self.contract_id_from_address(contract_address)?, - func, - argvec.as_slice(), - CallParams::default_external_call(), - ); - match res { - Ok(rv) => Ok(rv), - Err(e) => { - self.error( - e.error, - "contract try_call failed", - &[func.to_val(), args.to_val()], - ); - // Only allow to gracefully handle the recoverable errors. - // Non-recoverable errors should still cause guest to panic and - // abort execution. - if e.is_recoverable() { - // Pass contract error _codes_ through, while switching - // from Err(ce) to Ok(ce), i.e. recovering. - if e.error.is_type(ScErrorType::Contract) { - Ok(e.error.to_val()) - } else { - // Narrow all the remaining host errors down to a single - // error type. We don't want to expose the granular host - // errors to the guest, consistently with how every - // other host function works. This reduces the risk of - // implementation being 'locked' into specific error - // codes due to them being exposed to the guest and - // hashed into blockchain. - // The granular error codes are still observable with - // diagnostic events. - Ok(Error::from_type_and_code( - ScErrorType::Context, - ScErrorCode::InvalidAction, - ) - .to_val()) - } - } else { - Err(e) - } - } - } + let call_params = CallParams::default_external_call(); + self.try_call_with_params(contract_address, func, args, call_params) + } + + fn call_reentrant( + &self, + _vmcaller: &mut VmCaller, + contract_address: AddressObject, + func: Symbol, + args: VecObject, + ) -> Result { + let call_params = CallParams::reentrant_external_call(); + self.call_with_params(contract_address, func, args, call_params) + } + + fn try_call_reentrant( + &self, + _vmcaller: &mut VmCaller, + contract_address: AddressObject, + func: Symbol, + args: VecObject, + ) -> Result { + let call_params = CallParams::reentrant_external_call(); + self.try_call_with_params(contract_address, func, args, call_params) } // endregion: "call" module functions diff --git a/soroban-env-host/src/host/frame.rs b/soroban-env-host/src/host/frame.rs index 8a9e8592e..c036dd2fd 100644 --- a/soroban-env-host/src/host/frame.rs +++ b/soroban-env-host/src/host/frame.rs @@ -1,3 +1,5 @@ +use soroban_env_common::VecObject; + use crate::{ auth::AuthorizationManagerSnapshot, budget::AsBudget, @@ -111,6 +113,14 @@ impl CallParams { } } + pub(crate) fn reentrant_external_call() -> Self { + Self { + reentry_mode: ContractReentryMode::Allowed, + internal_host_call: false, + treat_missing_function_as_noop: false, + } + } + #[allow(unused)] pub(crate) fn default_internal_call() -> Self { Self { @@ -814,6 +824,90 @@ impl Host { } } + pub(crate) fn call_with_params( + &self, + contract_address: AddressObject, + func: Symbol, + args: VecObject, + call_params: CallParams, + ) -> Result { + let argvec = self.call_args_from_obj(args)?; + // this is the recommended path of calling a contract, with `reentry` + // always set `ContractReentryMode::Prohibited` unless the reentrant + // flag is enabled. + let res = self.call_n_internal( + &self.contract_id_from_address(contract_address)?, + func, + argvec.as_slice(), + call_params, + ); + if let Err(e) = &res { + self.error( + e.error, + "contract call failed", + &[func.to_val(), args.to_val()], + ); + } + res + } + + pub(crate) fn try_call_with_params( + &self, + contract_address: AddressObject, + func: Symbol, + args: VecObject, + call_params: CallParams, + ) -> Result { + let argvec = self.call_args_from_obj(args)?; + // this is the "loosened" path of calling a contract. + // TODO: A `reentry` flag will be passed from `try_call` into here. + // Default behaviour is to pass in `ContractReentryMode::Prohibited` to disable + // reentry, but it is the `call_data` parameter that controls this mode. + let res = self.call_n_internal( + &self.contract_id_from_address(contract_address)?, + func, + argvec.as_slice(), + call_params, + ); + match res { + Ok(rv) => Ok(rv), + Err(e) => { + self.error( + e.error, + "contract try_call failed", + &[func.to_val(), args.to_val()], + ); + // Only allow to gracefully handle the recoverable errors. + // Non-recoverable errors should still cause guest to panic and + // abort execution. + if e.is_recoverable() { + // Pass contract error _codes_ through, while switching + // from Err(ce) to Ok(ce), i.e. recovering. + if e.error.is_type(ScErrorType::Contract) { + Ok(e.error.to_val()) + } else { + // Narrow all the remaining host errors down to a single + // error type. We don't want to expose the granular host + // errors to the guest, consistently with how every + // other host function works. This reduces the risk of + // implementation being 'locked' into specific error + // codes due to them being exposed to the guest and + // hashed into blockchain. + // The granular error codes are still observable with + // diagnostic events. + Ok(Error::from_type_and_code( + ScErrorType::Context, + ScErrorCode::InvalidAction, + ) + .to_val()) + } + } else { + Err(e) + } + } + } + } + // Notes on metering: this is covered by the called components. pub(crate) fn call_n_internal( &self, diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index e3110e269..6b413cfb3 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2396,3 +2396,61 @@ mod cap_58_constructor { } } } + +#[allow(unused_imports)] +mod cap_xx_opt_in_reentry { + use crate::{Host, HostError, MeteredOrdMap}; + use soroban_env_common::{AddressObject, Env, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; + use soroban_test_wasms::{SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B}; + use stellar_xdr::curr::{ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash, ScSymbol, ScVal}; + + #[test] + fn test_reentry_enabled() { + let host = Host::test_host_with_recording_footprint(); + let contract_id_a = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_A); + let contract_id_b = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_B); + host.enable_debug().unwrap(); + let args = test_vec![ + &host, + contract_id_b + ].into(); + call_contract(&host, contract_id_a, args); + + let event_body = ContractEventBody::V0(ContractEventV0 { + topics: host.map_err(vec![ScVal::Symbol(ScSymbol("first_soroban_reentry".try_into().unwrap()))].try_into()).unwrap(), + data: ScVal::Void + } + ); + let events = host.get_events().unwrap().0; + match events.iter().find(|he| he.event.type_ == ContractEventType::Contract) { + Some(he) if he.event.type_ == ContractEventType::Contract => { + assert_eq!(he.event.body, event_body) + } + _ => panic!("missing contract event"), + } + } + + #[test] + #[should_panic] + fn test_reentry_disabled() { + let host = Host::test_host_with_recording_footprint(); + let contract_id_a = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_A); + let contract_id_b = host.register_test_contract_wasm(SIMPLE_NO_REENTRY_CONTRACT_B); + host.enable_debug().unwrap(); + let args = test_vec![ + &host, + contract_id_b + ].into(); + call_contract(&host, contract_id_a, args); + } + + fn call_contract(host: &Host, called: AddressObject, args: VecObject) { + let fname = Symbol::try_from_val(host, &"test_reentry").unwrap(); + host.call( + called, + fname, + args + ) + .unwrap(); + } +} diff --git a/soroban-test-wasms/src/lib.rs b/soroban-test-wasms/src/lib.rs index cc3985561..9c5c416b0 100644 --- a/soroban-test-wasms/src/lib.rs +++ b/soroban-test-wasms/src/lib.rs @@ -118,3 +118,14 @@ pub const CONSTRUCTOR_WITH_RESULT: &[u8] = include_bytes!("../wasm-workspace/opt/22/test_constructor_with_result.wasm").as_slice(); pub const CUSTOM_ACCOUNT_CONTEXT_TEST_CONTRACT: &[u8] = include_bytes!("../wasm-workspace/opt/22/test_custom_account_context.wasm").as_slice(); + + +// Protocol 23 Wasms. +pub const SIMPLE_REENTRY_CONTRACT_A: &[u8] = + include_bytes!("../wasm-workspace/opt/23/example_reentry_a.wasm").as_slice(); + +pub const SIMPLE_REENTRY_CONTRACT_B: &[u8] = +include_bytes!("../wasm-workspace/opt/23/example_reentry_b.wasm").as_slice(); + +pub const SIMPLE_NO_REENTRY_CONTRACT_B: &[u8] = +include_bytes!("../wasm-workspace/opt/23/example_no_reentry_b.wasm").as_slice(); diff --git a/soroban-test-wasms/wasm-workspace/Cargo.lock b/soroban-test-wasms/wasm-workspace/Cargo.lock index a01fd7d2f..7cd3acb10 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.lock +++ b/soroban-test-wasms/wasm-workspace/Cargo.lock @@ -17,18 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -53,17 +41,11 @@ dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - [[package]] name = "auth_test_contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -183,7 +165,7 @@ checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" name = "contract_sac_transfer" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -308,6 +290,12 @@ dependencies = [ "syn", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "der" version = "0.7.8" @@ -441,7 +429,7 @@ checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" name = "example_add_f32" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -449,7 +437,7 @@ dependencies = [ name = "example_add_i32" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -457,7 +445,7 @@ dependencies = [ name = "example_alloc" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -465,7 +453,7 @@ dependencies = [ name = "example_complex" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -473,7 +461,7 @@ dependencies = [ name = "example_contract_data" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -481,7 +469,7 @@ dependencies = [ name = "example_create_contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -489,7 +477,7 @@ dependencies = [ name = "example_err" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -497,7 +485,7 @@ dependencies = [ name = "example_fannkuch" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -505,7 +493,7 @@ dependencies = [ name = "example_fib" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -513,7 +501,7 @@ dependencies = [ name = "example_hostile" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -521,7 +509,7 @@ dependencies = [ name = "example_invoke_contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -529,7 +517,31 @@ dependencies = [ name = "example_linear_memory" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", + "soroban-sdk", +] + +[[package]] +name = "example_no_reentry_b" +version = "0.0.0" +dependencies = [ + "soroban-env-common 22.0.0-rc.1", + "soroban-sdk", +] + +[[package]] +name = "example_reentry_a" +version = "0.0.0" +dependencies = [ + "soroban-env-common 22.0.0-rc.1", + "soroban-sdk", +] + +[[package]] +name = "example_reentry_b" +version = "0.0.0" +dependencies = [ + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -537,7 +549,7 @@ dependencies = [ name = "example_simple_account" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -545,7 +557,7 @@ dependencies = [ name = "example_sum_i32" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -553,7 +565,7 @@ dependencies = [ name = "example_updateable_contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -561,7 +573,7 @@ dependencies = [ name = "example_upload_contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -569,7 +581,7 @@ dependencies = [ name = "example_vec" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -647,9 +659,6 @@ name = "hashbrown" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" -dependencies = [ - "ahash", -] [[package]] name = "hex" @@ -679,7 +688,7 @@ dependencies = [ name = "hostile_large_val" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -740,6 +749,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -801,7 +819,7 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" name = "loadgen" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -826,12 +844,6 @@ dependencies = [ "adler", ] -[[package]] -name = "multi-stash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" - [[package]] name = "num-bigint" version = "0.4.4" @@ -1005,7 +1017,7 @@ dependencies = [ name = "recursive_account" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1044,7 +1056,7 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" name = "sac_reentry_account" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1166,9 +1178,11 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "soroban-builtin-sdk-macros" -version = "22.0.0" +version = "21.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44877373b3dc6c662377cb1600e3a62706d75e484b6064f9cd22e467c676b159" dependencies = [ - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", "syn", @@ -1176,7 +1190,9 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "22.0.0" +version = "21.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590add16843a61b01844e19e89bccaaee6aa21dc76809017b0662c17dc139ee9" dependencies = [ "arbitrary", "crate-git-revision", @@ -1184,24 +1200,43 @@ dependencies = [ "num-derive", "num-traits", "serde", - "soroban-env-macros", + "soroban-env-macros 21.2.0", "soroban-wasmi", "static_assertions", - "stellar-xdr 21.2.0 (git+https://github.com/stellar/rs-stellar-xdr?rev=953ad1c6103146121871a3e2fa5aaca3d6256891)", + "stellar-xdr 21.2.0", "wasmparser", ] +[[package]] +name = "soroban-env-common" +version = "22.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc59f0172caff4867ea71e0b65ff8a532d10612ff78c791a01e23fc33521a9a" +dependencies = [ + "crate-git-revision", + "ethnum", + "num-derive", + "num-traits", + "soroban-env-macros 22.0.0-rc.1", + "static_assertions", + "stellar-xdr 22.0.0-rc.1", +] + [[package]] name = "soroban-env-guest" -version = "22.0.0" +version = "21.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ec8dc43acdd6c7e7b371acf44fc1a7dac24934ae3b2f05fafd618818548176" dependencies = [ - "soroban-env-common", + "soroban-env-common 21.2.0", "static_assertions", ] [[package]] name = "soroban-env-host" -version = "22.0.0" +version = "21.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e25aaffe0c62eb65e0e349f725b4b8b13ad0764d78a15aab5bbccb5c4797726" dependencies = [ "backtrace", "curve25519-dalek", @@ -1223,34 +1258,53 @@ dependencies = [ "sha2", "sha3", "soroban-builtin-sdk-macros", - "soroban-env-common", + "soroban-env-common 21.2.0", "soroban-wasmi", "static_assertions", - "stellar-strkey", + "stellar-strkey 0.0.8", "wasmparser", ] [[package]] name = "soroban-env-macros" -version = "22.0.0" +version = "21.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e16b761459fdf3c4b62b24df3941498d14e5246e6fadfb4774ed8114d243aa4" dependencies = [ - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", "serde", "serde_json", - "stellar-xdr 21.2.0 (git+https://github.com/stellar/rs-stellar-xdr?rev=953ad1c6103146121871a3e2fa5aaca3d6256891)", + "stellar-xdr 21.2.0", + "syn", +] + +[[package]] +name = "soroban-env-macros" +version = "22.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ed871b77a7e06adb5b61f792aac3d23c5180c56b4c9bba59ecdc38d5f468cf5" +dependencies = [ + "itertools 0.10.5", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr 22.0.0-rc.1", "syn", ] [[package]] name = "soroban-ledger-snapshot" -version = "21.4.0" +version = "21.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46f8b134b1e0b517f70d24dd72399cd263fd18c3c7cfcb5e56ffc6de9dad0c3" dependencies = [ "serde", "serde_json", "serde_with", - "soroban-env-common", + "soroban-env-common 21.2.0", "soroban-env-host", "thiserror", ] @@ -1258,6 +1312,8 @@ dependencies = [ [[package]] name = "soroban-sdk" version = "21.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60cd55eb88cbe1d9e7fe3ab1845c7c10c26b27e2d226e973150e5b55580aa359" dependencies = [ "arbitrary", "bytes-lit", @@ -1270,21 +1326,23 @@ dependencies = [ "soroban-env-host", "soroban-ledger-snapshot", "soroban-sdk-macros", - "stellar-strkey", + "stellar-strkey 0.0.8", ] [[package]] name = "soroban-sdk-macros" -version = "21.4.0" +version = "21.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f24c6b0c46e41852a8603bb32d43cf6a4046ce65483f6383903ec653118cd90" dependencies = [ "crate-git-revision", "darling", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", "rustc_version", "sha2", - "soroban-env-common", + "soroban-env-common 21.2.0", "soroban-spec", "soroban-spec-rust", "stellar-xdr 21.2.0", @@ -1293,7 +1351,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "21.4.0" +version = "21.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b262c82d840552f71ee9254f2e928622fd803bd4df4815e65f73f73efc2fa9c" dependencies = [ "base64 0.13.1", "stellar-xdr 21.2.0", @@ -1303,7 +1363,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "21.4.0" +version = "21.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a061820c2dd0bd3ece9411e0dd3aeb6ed9ca2b7d64270eda9e798c3b6dec5f" dependencies = [ "prettyplease", "proc-macro2", @@ -1317,16 +1379,13 @@ dependencies = [ [[package]] name = "soroban-wasmi" -version = "0.36.0-soroban.22.0.0" -source = "git+https://github.com/stellar/wasmi?rev=122a74a7c491929e5ac9de876099154ef7c06d06#122a74a7c491929e5ac9de876099154ef7c06d06" +version = "0.31.1-soroban.20.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719" dependencies = [ - "arrayvec", - "multi-stash", - "num-derive", - "num-traits", "smallvec", "spin", - "wasmi_collections", + "wasmi_arena", "wasmi_core", "wasmparser-nostd", ] @@ -1335,7 +1394,7 @@ dependencies = [ name = "soroban-write-upgrade-bytes-contract" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1373,21 +1432,21 @@ dependencies = [ ] [[package]] -name = "stellar-xdr" -version = "21.2.0" +name = "stellar-strkey" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" dependencies = [ "crate-git-revision", - "escape-bytes", - "hex", - "serde", - "serde_with", - "stellar-strkey", + "data-encoding", + "thiserror", ] [[package]] name = "stellar-xdr" version = "21.2.0" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=953ad1c6103146121871a3e2fa5aaca3d6256891#953ad1c6103146121871a3e2fa5aaca3d6256891" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2675a71212ed39a806e415b0dbf4702879ff288ec7f5ee996dda42a135512b50" dependencies = [ "arbitrary", "base64 0.13.1", @@ -1396,18 +1455,19 @@ dependencies = [ "hex", "serde", "serde_with", - "stellar-strkey", + "stellar-strkey 0.0.8", ] [[package]] -name = "string-interner" -version = "0.17.0" +name = "stellar-xdr" +version = "22.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" +checksum = "1946827903a221bf052e24e18f0ed6fb10ca350c9281911f24b7d7a9726ab181" dependencies = [ - "cfg-if", - "hashbrown 0.14.2", - "serde", + "crate-git-revision", + "escape-bytes", + "hex", + "stellar-strkey 0.0.9", ] [[package]] @@ -1437,7 +1497,7 @@ dependencies = [ name = "test_conditional_account" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1445,7 +1505,7 @@ dependencies = [ name = "test_constructor" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1453,7 +1513,7 @@ dependencies = [ name = "test_constructor_with_result" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1461,7 +1521,7 @@ dependencies = [ name = "test_constructor_with_return_value" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1469,7 +1529,7 @@ dependencies = [ name = "test_custom_account_context" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1477,7 +1537,7 @@ dependencies = [ name = "test_delegated_account" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1485,7 +1545,7 @@ dependencies = [ name = "test_deployer" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1493,7 +1553,7 @@ dependencies = [ name = "test_deployer_with_constructor" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1501,7 +1561,7 @@ dependencies = [ name = "test_no_arg_constructor" version = "0.0.0" dependencies = [ - "soroban-env-common", + "soroban-env-common 22.0.0-rc.1", "soroban-sdk", ] @@ -1633,19 +1693,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] -name = "wasmi_collections" -version = "0.36.0-soroban.22.0.0" -source = "git+https://github.com/stellar/wasmi?rev=122a74a7c491929e5ac9de876099154ef7c06d06#122a74a7c491929e5ac9de876099154ef7c06d06" -dependencies = [ - "ahash", - "hashbrown 0.14.2", - "string-interner", -] +name = "wasmi_arena" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" [[package]] name = "wasmi_core" -version = "0.36.0-soroban.22.0.0" -source = "git+https://github.com/stellar/wasmi?rev=122a74a7c491929e5ac9de876099154ef7c06d06#122a74a7c491929e5ac9de876099154ef7c06d06" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" dependencies = [ "downcast-rs", "libm", @@ -1738,28 +1795,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" + +[[patch.unused]] +name = "soroban-env-common" +version = "22.0.0" + +[[patch.unused]] +name = "soroban-env-guest" +version = "22.0.0" + +[[patch.unused]] +name = "soroban-env-host" +version = "22.0.0" + +[[patch.unused]] +name = "soroban-sdk" +version = "22.0.0-rc.3" + +[[patch.unused]] +name = "stellar-xdr" +version = "22.0.0" diff --git a/soroban-test-wasms/wasm-workspace/Cargo.toml b/soroban-test-wasms/wasm-workspace/Cargo.toml index c10342a4a..ce4e6e734 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.toml +++ b/soroban-test-wasms/wasm-workspace/Cargo.toml @@ -49,7 +49,10 @@ members = [ "deployer_with_constructor", "constructor_with_return_value", "constructor_with_result", - "custom_account_context" + "custom_account_context", + "reentry_a", + "no_reentry_b", + "reentry_b", ] [profile.release] opt-level = "z" diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_b/Cargo.toml b/soroban-test-wasms/wasm-workspace/no_reentry_b/Cargo.toml new file mode 100644 index 000000000..896871a14 --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_no_reentry_b" +version = "0.0.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +soroban-env-common = { workspace = true } + +[features] +next = ["soroban-env-common/next"] diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_b/src/lib.rs b/soroban-test-wasms/wasm-workspace/no_reentry_b/src/lib.rs new file mode 100644 index 000000000..7f87ea143 --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_b/src/lib.rs @@ -0,0 +1,27 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Val, Address, Vec, Symbol, vec}; + +#[link(wasm_import_module = "d")] +extern "C" { + #[allow(improper_ctypes)] + #[link_name = "_"] + pub fn call_reentrant(contract: i64, func: i64, args: i64, ) -> i64; +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn do_reentry(env: Env, caller: Address) { + let args: Vec = vec![&env]; + let func = Symbol::new(&env, "do_nothing"); + let called_val = caller.as_val().get_payload() as i64; + let func_val = func.as_val().get_payload() as i64; + let args_val = args.as_val().get_payload() as i64; + + unsafe { + call_reentrant(called_val, func_val, args_val); + }; + } +} diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_b.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_b.wasm new file mode 100755 index 0000000000000000000000000000000000000000..043b6b1b24baeec9cfb5ced2b76884fe54fbc061 GIT binary patch literal 1311 zcmZ`&&2G~`5T2Q}Q#ad`MHLcM2sVL3d!W>`#L!dMs7R<6gb>%niCw^@NlBtgT;c+y z;ve3CBc~oY!wc{XoOueEb$&VE!+L(dZ@yVAMBP0E0Njvu(eL-MU#I*8w$QrRhq}nJ z4C*j2Y%CibS)DjR3j$-TF-QYbKs;cZ#C%COu3Kk6m+fzq2!8JM^ zG>0Ug{vXuKA=O*kROYtawX%4CqIzS)IkWLn_0D=sHyB{-f#UcfEKYIC2V~bf5h8{{ zgr;SJfX-^ch)gHU*;F0del2+VvZHfD1;S&?37AccrO1?M0;_f_Q?N?}6-Uz&ITcbL zEg)^urWPD84YA!hL4*2W)6!v6F7ldBLVX-MN1BF)dYa?++85et_Z~fNJ%n5H%{D*PsM+i8C(VOZn0(U@*+y}gDm0@f zPm)gVE#&8g(<6|ib+DK8qA|{yJl`IZ{F8J$-Gdp^j>vX&E?jU{jn!j>= q#lN&3?A-L@W}~|1udY^uI1bhu&FXp-uls(m*0>fYYkuPUJMb54hz2YG literal 0 HcmV?d00001 diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_a.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_a.wasm new file mode 100755 index 0000000000000000000000000000000000000000..c3815269175dc7c916d0ee0be8d9e84e452b0d34 GIT binary patch literal 2244 zcmdTF$!^<5^t~BUrb)?}AP(T#MLlA2un)1#*pXVFJOW%G@S#Oe^j64P=p~g_$-5v zON&xEZcfa2QqDNetS|jQ=6yeyl?BJeBSds1!o}Pxa){>SYccDRIS%~ zu@wH3!s0)Oa(Ly0J}?`tP+qm5mRe|3kC|MSpk+mrrKhEtPw4Q{!`>EEpILp9TM;Xv z;OlDWv_e}Bmztx#m`5?mJbJ?AB; zo~sgm-!0I12Ml{f>ZVayX|xR9K^(PQw?fQppr#@!jT+5zLWfG!H<>}4GDxteK4u2V z=*(zE1dnNMM^2y#D&e%eR zQ|1++zDpg!IQd|Y1)wBY(Jhb}A$65*9<8F?HMb-|*v2$tXw%elE! z67#{k(;cQ*rxtQmK$#Tn{_ze_HNLRXN$xTGAwcn-QW$n?Cm|+6oEw}evnv8Z3SdPz zp-{iDL9rutctxRLO?pK)j{&uXq|}crP;_|@UF&MJdZYOY1iep`E%j)8`-H0}tQpL4 zA$SRYvZzKJ5P>H)lxgU)@&X@K{)Su6D2HJ0<@G4h8zQ;3SxqQduF2q)279?}k=-9#NV>niB)tFj8YD<0d}jZ8lgGc&cf0hv>vg)FdaXSoLSwGcq5og4(eE9_jpGfNeCPj<0GP3IjoQ6? zanoX#CgK*F{)tXluU#BDiQC7Aalbb9bJ+@Y#zCB8y4~J!+)d5oqP5qfwMlqhx7Ta7 zQug}wXzj*YbY-i2@J7^Z)JvPu#zv{!Y?im`jnY=FxfMm_&HD9bycxw&bO8SX=DW0F literal 0 HcmV?d00001 diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_b.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_b.wasm new file mode 100755 index 0000000000000000000000000000000000000000..6a2e63a7a25ad4bd6981b4140d431d1cdcaa6dbc GIT binary patch literal 1311 zcmZ`&&2G~`5T2Q}Q#ad`MHLcM2sVL3d!W>`#L!dMs7R<6gb>%niCw^@NlBtgT;c+y z;ve3CBc~oY!wc{XoOueEb$&VE!+L(dZ@yVAMBP0E0Njvu(eL-MU#I*8w$QrRhq}nJ z4C*j2Y%CibS)DjR3j$;G8Ki+JARb^1NX(anHk5!98$ftO=WJ&T`P+RD5^I$oHH9QRqw3Fbb|rL9w?3iG400mRu2ofkgNRUxq*7 z-U*k>?fDbEIi#sONd! z1N9;|zTxx$lYQjM$;@t-AcV3b>>`M_00yeWKkbCxaX5d(n&yP$IqX$j0Z^YTEEkI_ z;2Ck-w&d3m5Z{YoHDK$}U|L2^CQHl2ScPLPe3(5dJ98lIN~ubGdj>XO)MiP>t9`+5 zC^J|lW%_dL;rg=2rP~QU#0>~g&Tl&v<-k$cCsxVX^yP5Z7qA@ z<{n!-mJwXUEyOKSE+7nEuYIAdcJI;S)PlkZlx)sX{Y) z@+9fx-a>v}I6VSMS_gYcFB;>V$@A?o$v;WA(>)mCK*3+R;jc{Sy-v3q?+(&eulXz2 rSNu!s!Ol%TZZ@iG{_1Kqh~r?r(X6gV@w)E^YmIAhvgRkgzXN{(jWY%Q literal 0 HcmV?d00001 diff --git a/soroban-test-wasms/wasm-workspace/reentry_a/Cargo.toml b/soroban-test-wasms/wasm-workspace/reentry_a/Cargo.toml new file mode 100644 index 000000000..d725bfddf --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/reentry_a/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_reentry_a" +version = "0.0.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +soroban-env-common = { workspace = true } + +[features] +next = ["soroban-env-common/next"] diff --git a/soroban-test-wasms/wasm-workspace/reentry_a/src/lib.rs b/soroban-test-wasms/wasm-workspace/reentry_a/src/lib.rs new file mode 100644 index 000000000..542a57c93 --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/reentry_a/src/lib.rs @@ -0,0 +1,31 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Address, Symbol, TryIntoVal, Vec, Val}; + +#[link(wasm_import_module = "d")] +extern "C" { + #[allow(improper_ctypes)] + #[link_name = "1"] + pub fn call_reentrant(contract: i64, func: i64, args: i64, ) -> i64; +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn test_reentry(env: Env, called: Address) { + let args: Vec = (env.current_contract_address(), ).try_into_val(&env).unwrap(); + let func = Symbol::new(&env, "do_reentry"); + let called_val = called.as_val().get_payload() as i64; + let func_val = func.as_val().get_payload() as i64; + let args_val = args.as_val().get_payload() as i64; + + unsafe { + call_reentrant(called_val, func_val, args_val); + }; + } + + pub fn do_nothing(env: Env) { + env.events().publish((Symbol::new(&env, "first_soroban_reentry"),), ()); + } +} diff --git a/soroban-test-wasms/wasm-workspace/reentry_b/Cargo.toml b/soroban-test-wasms/wasm-workspace/reentry_b/Cargo.toml new file mode 100644 index 000000000..34df73408 --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/reentry_b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_reentry_b" +version = "0.0.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +soroban-env-common = { workspace = true } + +[features] +next = ["soroban-env-common/next"] diff --git a/soroban-test-wasms/wasm-workspace/reentry_b/src/lib.rs b/soroban-test-wasms/wasm-workspace/reentry_b/src/lib.rs new file mode 100644 index 000000000..d175d9669 --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/reentry_b/src/lib.rs @@ -0,0 +1,27 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Val, Address, Vec, Symbol, vec}; + +#[link(wasm_import_module = "d")] +extern "C" { + #[allow(improper_ctypes)] + #[link_name = "1"] + pub fn call_reentrant(contract: i64, func: i64, args: i64, ) -> i64; +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn do_reentry(env: Env, caller: Address) { + let args: Vec = vec![&env]; + let func = Symbol::new(&env, "do_nothing"); + let called_val = caller.as_val().get_payload() as i64; + let func_val = func.as_val().get_payload() as i64; + let args_val = args.as_val().get_payload() as i64; + + unsafe { + call_reentrant(called_val, func_val, args_val); + }; + } +} From efd3537cc6bafe8ba2fe37124195460aaf99432d Mon Sep 17 00:00:00 2001 From: heytdep Date: Wed, 6 Nov 2024 16:59:11 +0700 Subject: [PATCH 2/6] change supported protocol --- soroban-env-common/env.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soroban-env-common/env.json b/soroban-env-common/env.json index ac8af0b11..2adfeeedf 100644 --- a/soroban-env-common/env.json +++ b/soroban-env-common/env.json @@ -1580,7 +1580,7 @@ ], "return": "Val", "docs": "Calls a function in another contract with arguments contained in vector `args`. If the call is successful, returns the result of the called function. Traps otherwise. This functions enables re-entrancy in the immediate cross-contract call.", - "min_supported_protocol": 21 + "min_supported_protocol": 22 }, { "export": "2", @@ -1601,7 +1601,7 @@ ], "return": "Val", "docs": "Calls a function in another contract with arguments contained in vector `args`, returning either the result of the called function or an `Error` if the called function failed. The returned error is either a custom `ContractError` that the called contract returns explicitly, or an error with type `Context` and code `InvalidAction` in case of any other error in the called contract (such as a host function failure that caused a trap). `try_call` might trap in a few scenarios where the error can't be meaningfully recovered from, such as running out of budget. This functions enables re-entrancy in the immediate cross-contract call.", - "min_supported_protocol": 21 + "min_supported_protocol": 22 } ] }, From 22f57705fd7dc7408cbcab8a4e9bded0cd332b21 Mon Sep 17 00:00:00 2001 From: heytdep Date: Wed, 6 Nov 2024 17:08:54 +0700 Subject: [PATCH 3/6] fmt --- soroban-env-host/src/host/frame.rs | 2 +- soroban-env-host/src/test/lifecycle.rs | 45 ++++++++++++++------------ soroban-test-wasms/src/lib.rs | 5 ++- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/soroban-env-host/src/host/frame.rs b/soroban-env-host/src/host/frame.rs index c036dd2fd..298e0fab2 100644 --- a/soroban-env-host/src/host/frame.rs +++ b/soroban-env-host/src/host/frame.rs @@ -862,7 +862,7 @@ impl Host { // this is the "loosened" path of calling a contract. // TODO: A `reentry` flag will be passed from `try_call` into here. // Default behaviour is to pass in `ContractReentryMode::Prohibited` to disable - // reentry, but it is the `call_data` parameter that controls this mode. + // reentry, but it is the `call_data` parameter that controls this mode. let res = self.call_n_internal( &self.contract_id_from_address(contract_address)?, func, diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index 6b413cfb3..2609a70c3 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2401,8 +2401,13 @@ mod cap_58_constructor { mod cap_xx_opt_in_reentry { use crate::{Host, HostError, MeteredOrdMap}; use soroban_env_common::{AddressObject, Env, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; - use soroban_test_wasms::{SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B}; - use stellar_xdr::curr::{ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash, ScSymbol, ScVal}; + use soroban_test_wasms::{ + SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B, + }; + use stellar_xdr::curr::{ + ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash, + ScSymbol, ScVal, + }; #[test] fn test_reentry_enabled() { @@ -2410,19 +2415,25 @@ mod cap_xx_opt_in_reentry { let contract_id_a = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_A); let contract_id_b = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_B); host.enable_debug().unwrap(); - let args = test_vec![ - &host, - contract_id_b - ].into(); + let args = test_vec![&host, contract_id_b].into(); call_contract(&host, contract_id_a, args); let event_body = ContractEventBody::V0(ContractEventV0 { - topics: host.map_err(vec![ScVal::Symbol(ScSymbol("first_soroban_reentry".try_into().unwrap()))].try_into()).unwrap(), - data: ScVal::Void - } - ); + topics: host + .map_err( + vec![ScVal::Symbol(ScSymbol( + "first_soroban_reentry".try_into().unwrap(), + ))] + .try_into(), + ) + .unwrap(), + data: ScVal::Void, + }); let events = host.get_events().unwrap().0; - match events.iter().find(|he| he.event.type_ == ContractEventType::Contract) { + match events + .iter() + .find(|he| he.event.type_ == ContractEventType::Contract) + { Some(he) if he.event.type_ == ContractEventType::Contract => { assert_eq!(he.event.body, event_body) } @@ -2437,20 +2448,12 @@ mod cap_xx_opt_in_reentry { let contract_id_a = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_A); let contract_id_b = host.register_test_contract_wasm(SIMPLE_NO_REENTRY_CONTRACT_B); host.enable_debug().unwrap(); - let args = test_vec![ - &host, - contract_id_b - ].into(); + let args = test_vec![&host, contract_id_b].into(); call_contract(&host, contract_id_a, args); } fn call_contract(host: &Host, called: AddressObject, args: VecObject) { let fname = Symbol::try_from_val(host, &"test_reentry").unwrap(); - host.call( - called, - fname, - args - ) - .unwrap(); + host.call(called, fname, args).unwrap(); } } diff --git a/soroban-test-wasms/src/lib.rs b/soroban-test-wasms/src/lib.rs index 9c5c416b0..c69f67dc8 100644 --- a/soroban-test-wasms/src/lib.rs +++ b/soroban-test-wasms/src/lib.rs @@ -119,13 +119,12 @@ pub const CONSTRUCTOR_WITH_RESULT: &[u8] = pub const CUSTOM_ACCOUNT_CONTEXT_TEST_CONTRACT: &[u8] = include_bytes!("../wasm-workspace/opt/22/test_custom_account_context.wasm").as_slice(); - // Protocol 23 Wasms. pub const SIMPLE_REENTRY_CONTRACT_A: &[u8] = include_bytes!("../wasm-workspace/opt/23/example_reentry_a.wasm").as_slice(); pub const SIMPLE_REENTRY_CONTRACT_B: &[u8] = -include_bytes!("../wasm-workspace/opt/23/example_reentry_b.wasm").as_slice(); + include_bytes!("../wasm-workspace/opt/23/example_reentry_b.wasm").as_slice(); pub const SIMPLE_NO_REENTRY_CONTRACT_B: &[u8] = -include_bytes!("../wasm-workspace/opt/23/example_no_reentry_b.wasm").as_slice(); + include_bytes!("../wasm-workspace/opt/23/example_no_reentry_b.wasm").as_slice(); From d3bc92bd81c52fd07d3cd1653f20a13ed64fd49e Mon Sep 17 00:00:00 2001 From: heytdep Date: Thu, 7 Nov 2024 12:16:40 +0700 Subject: [PATCH 4/6] allow caller contract to specify reentry rules --- rust-toolchain.toml | 2 +- soroban-env-common/env.json | 17 +++++++++++-- soroban-env-host/src/host.rs | 14 ++++++++++ soroban-env-host/src/host/frame.rs | 24 +++++++++++++++--- soroban-env-host/src/test/lifecycle.rs | 1 + soroban-env-host/src/vm.rs | 24 +++++++++++++++--- soroban-env-host/src/vm/module_cache.rs | 5 +++- soroban-env-host/src/vm/parsed_module.rs | 14 ++++++++-- .../opt/23/example_reentry_a.wasm | Bin 2244 -> 2269 bytes .../wasm-workspace/reentry_a/src/lib.rs | 13 +++++++--- 10 files changed, 97 insertions(+), 17 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e340b7641..90ff24e80 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "stable" +channel = "1.81" targets = ["wasm32-unknown-unknown"] components = ["rustc", "cargo", "rustfmt", "clippy", "rust-src"] diff --git a/soroban-env-common/env.json b/soroban-env-common/env.json index 2adfeeedf..d3630dfb6 100644 --- a/soroban-env-common/env.json +++ b/soroban-env-common/env.json @@ -1580,7 +1580,7 @@ ], "return": "Val", "docs": "Calls a function in another contract with arguments contained in vector `args`. If the call is successful, returns the result of the called function. Traps otherwise. This functions enables re-entrancy in the immediate cross-contract call.", - "min_supported_protocol": 22 + "min_supported_protocol": 21 }, { "export": "2", @@ -1601,7 +1601,20 @@ ], "return": "Val", "docs": "Calls a function in another contract with arguments contained in vector `args`, returning either the result of the called function or an `Error` if the called function failed. The returned error is either a custom `ContractError` that the called contract returns explicitly, or an error with type `Context` and code `InvalidAction` in case of any other error in the called contract (such as a host function failure that caused a trap). `try_call` might trap in a few scenarios where the error can't be meaningfully recovered from, such as running out of budget. This functions enables re-entrancy in the immediate cross-contract call.", - "min_supported_protocol": 22 + "min_supported_protocol": 21 + }, + { + "export": "3", + "name": "set_reentrant", + "args": [ + { + "name": "enabled", + "type": "Bool" + } + ], + "return": "Void", + "docs": "Enables the current contract to specify the reentrancy rules.", + "min_supported_protocol": 21 } ] }, diff --git a/soroban-env-host/src/host.rs b/soroban-env-host/src/host.rs index c5680ef7a..8fb7aa8e5 100644 --- a/soroban-env-host/src/host.rs +++ b/soroban-env-host/src/host.rs @@ -166,6 +166,9 @@ struct HostImpl { #[doc(hidden)] #[cfg(any(test, feature = "recording_mode"))] need_to_build_module_cache: RefCell, + + // Enables calling modules that link functions that call with reentry. + enable_reentrant: RefCell, } // Host is a newtype on Rc so we can impl Env for it below. @@ -382,6 +385,8 @@ impl Host { suppress_diagnostic_events: RefCell::new(false), #[cfg(any(test, feature = "recording_mode"))] need_to_build_module_cache: RefCell::new(false), + + enable_reentrant: RefCell::new(false), })) } @@ -2407,6 +2412,15 @@ impl VmCallerEnv for Host { self.try_call_with_params(contract_address, func, args, call_params) } + fn set_reentrant( + &self, + _vmcaller: &mut VmCaller, + enabled: Bool, + ) -> Result { + *self.0.enable_reentrant.borrow_mut() = enabled.try_into()?; + Ok(Void::from(())) + } + // endregion: "call" module functions // region: "buf" module functions diff --git a/soroban-env-host/src/host/frame.rs b/soroban-env-host/src/host/frame.rs index 298e0fab2..8708b54be 100644 --- a/soroban-env-host/src/host/frame.rs +++ b/soroban-env-host/src/host/frame.rs @@ -184,6 +184,10 @@ impl Frame { } impl Host { + pub(crate) fn get_reentrancy_flag(&self) -> Result { + Ok(*self.0.enable_reentrant.borrow()) + } + /// Returns if the host currently has a frame on the stack. /// /// A frame being on the stack usually indicates that a contract is currently @@ -686,7 +690,7 @@ impl Host { let args_vec = args.to_vec(); match &instance.executable { ContractExecutable::Wasm(wasm_hash) => { - let vm = self.instantiate_vm(id, wasm_hash)?; + let vm = self.instantiate_vm(id, wasm_hash, true)?; let relative_objects = Vec::new(); self.with_frame( Frame::ContractVM { @@ -709,7 +713,12 @@ impl Host { } } - fn instantiate_vm(&self, id: &Hash, wasm_hash: &Hash) -> Result, HostError> { + fn instantiate_vm( + &self, + id: &Hash, + wasm_hash: &Hash, + reentry_guard: bool, + ) -> Result, HostError> { #[cfg(any(test, feature = "recording_mode"))] { if !self.in_storage_recording_mode()? { @@ -802,7 +811,14 @@ impl Host { #[cfg(not(any(test, feature = "recording_mode")))] let cost_mode = crate::vm::ModuleParseCostMode::Normal; - Vm::new_with_cost_inputs(self, contract_id, code.as_slice(), costs, cost_mode) + Vm::new_with_cost_inputs( + self, + contract_id, + code.as_slice(), + costs, + cost_mode, + reentry_guard, + ) } pub(crate) fn get_contract_protocol_version( @@ -817,7 +833,7 @@ impl Host { let instance = self.retrieve_contract_instance_from_storage(&storage_key)?; match &instance.executable { ContractExecutable::Wasm(wasm_hash) => { - let vm = self.instantiate_vm(contract_id, wasm_hash)?; + let vm = self.instantiate_vm(contract_id, wasm_hash, false)?; Ok(vm.module.proto_version) } ContractExecutable::StellarAsset => self.get_ledger_protocol_version(), diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index 2609a70c3..c5e3f56ef 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2416,6 +2416,7 @@ mod cap_xx_opt_in_reentry { let contract_id_b = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_B); host.enable_debug().unwrap(); let args = test_vec![&host, contract_id_b].into(); + call_contract(&host, contract_id_a, args); let event_body = ContractEventBody::V0(ContractEventV0 { diff --git a/soroban-env-host/src/vm.rs b/soroban-env-host/src/vm.rs index 5e7779a8c..b50f6c401 100644 --- a/soroban-env-host/src/vm.rs +++ b/soroban-env-host/src/vm.rs @@ -102,9 +102,20 @@ impl Host { pub(crate) fn make_linker( engine: &wasmi::Engine, symbols: &BTreeSet<(&str, &str)>, + enable_reentrant_linking: bool, ) -> Result, HostError> { let mut linker = Linker::new(&engine); for hf in HOST_FUNCTIONS { + if !enable_reentrant_linking { + if symbols.contains(&("d", "1")) || symbols.contains(&("d", "2")) { + return Err(crate::Error::from_type_and_code( + ScErrorType::WasmVm, + ScErrorCode::ArithDomain, + ) + .try_into()?); + } + } + if symbols.contains(&(hf.mod_str, hf.fn_str)) { (hf.wrap)(&mut linker).map_err(|le| wasmi::Error::Linker(le))?; } @@ -257,7 +268,7 @@ impl Vm { if let Some(linker) = &*host.try_borrow_linker()? { Self::instantiate(host, contract_id, parsed_module, linker) } else { - let linker = parsed_module.make_linker(host)?; + let linker = parsed_module.make_linker(host, true)?; Self::instantiate(host, contract_id, parsed_module, &linker) } } @@ -286,13 +297,16 @@ impl Vm { let cost_inputs = VersionedContractCodeCostInputs::V0 { wasm_bytes: wasm.len(), }; - Self::new_with_cost_inputs( + + let vm = Self::new_with_cost_inputs( host, contract_id, wasm, cost_inputs, ModuleParseCostMode::Normal, - ) + false, + ); + vm } pub(crate) fn new_with_cost_inputs( @@ -301,11 +315,13 @@ impl Vm { wasm: &[u8], cost_inputs: VersionedContractCodeCostInputs, cost_mode: ModuleParseCostMode, + reentry_guard: bool, ) -> Result, HostError> { let _span = tracy_span!("Vm::new"); VmInstantiationTimer::new(host.clone()); let parsed_module = Self::parse_module(host, wasm, cost_inputs, cost_mode)?; - let linker = parsed_module.make_linker(host)?; + let linker = parsed_module.make_linker(host, reentry_guard)?; + Self::instantiate(host, contract_id, parsed_module, &linker) } diff --git a/soroban-env-host/src/vm/module_cache.rs b/soroban-env-host/src/vm/module_cache.rs index e93df15b9..f798ac7b8 100644 --- a/soroban-env-host/src/vm/module_cache.rs +++ b/soroban-env-host/src/vm/module_cache.rs @@ -132,7 +132,10 @@ impl ModuleCache { } pub fn make_linker(&self, host: &Host) -> Result, HostError> { - self.with_import_symbols(host, |symbols| Host::make_linker(&self.engine, symbols)) + let enable_reentrant_linking = host.get_reentrancy_flag()?; + self.with_import_symbols(host, |symbols| { + Host::make_linker(&self.engine, symbols, enable_reentrant_linking) + }) } pub fn get_module( diff --git a/soroban-env-host/src/vm/parsed_module.rs b/soroban-env-host/src/vm/parsed_module.rs index 3857e2f14..85f278983 100644 --- a/soroban-env-host/src/vm/parsed_module.rs +++ b/soroban-env-host/src/vm/parsed_module.rs @@ -193,9 +193,19 @@ impl ParsedModule { callback(&symbols) } - pub fn make_linker(&self, host: &Host) -> Result, HostError> { + pub fn make_linker( + &self, + host: &Host, + reentry_guard: bool, + ) -> Result, HostError> { self.with_import_symbols(host, |symbols| { - Host::make_linker(self.module.engine(), symbols) + let enable_reentrant_linking = if reentry_guard { + host.get_reentrancy_flag()? + } else { + true + }; + + Host::make_linker(self.module.engine(), symbols, enable_reentrant_linking) }) } diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_a.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_reentry_a.wasm index c3815269175dc7c916d0ee0be8d9e84e452b0d34..c1a48c71cc2586de6841cf5aaaa2f9a9b1230bd3 100755 GIT binary patch delta 516 zcmZvXyK7WY5XR>_kInAANtjq=H;SVuLO$*7X&NaO6{Vu5WQd`D8XvIc^Jj_ zbu>Psg@u(^SlU|n7g#A+ihqQ9&So)<&BuK6`_9aq&m-SQn9g0f1R}!8;j`$XTc%P@ z?a%gB&_Oe_JD4TlJaRHv#9Yv8IMCA>vUaTDoTrK%s5&>`eJycG>IRb}t+{eN+g3|D z3$ybJS1(+gpQAKP;_}ya`(db|KT!8Zz@`4iIPPg1$MHxnn+ZJD4HNke-1;v&h-doM zw3|7+g19J#D3~u{UESB&vCk$taTZ znm)8+C)T&Q6f{-XF6o$`x&&=%Z%&J!#myNhrNwJH&Xh^XHQn*{C2t)`5Q!R?14n&Itu@SFd z38Drk$B%q$;*UrjNRcvSN-g{cY3#k@F4)+--1j*T=iJNwKm8HSzI_8C!i(NSn`CVK zY01Yt9yv0Hn1EF*xLk82%{nQ5P-OP}KxMMb8PCgw97dcE!zjl|yE%{z=T}!rf@7ZE)@2xwPesR z@k95r)Kt+CfDLJ}!6&gi_ i64; + #[link_name = "_"] + pub fn call_contract(contract: i64, func: i64, args: i64, ) -> i64; + + #[allow(improper_ctypes)] + #[link_name = "3"] + pub fn set_reentrant(enabled: i64, ) -> i64; } #[contract] @@ -19,9 +23,12 @@ impl Contract { let called_val = called.as_val().get_payload() as i64; let func_val = func.as_val().get_payload() as i64; let args_val = args.as_val().get_payload() as i64; + + let set_reentrant_flag = Val::from_bool(true).as_val().get_payload() as i64; unsafe { - call_reentrant(called_val, func_val, args_val); + set_reentrant(set_reentrant_flag); + call_contract(called_val, func_val, args_val); }; } From 450cbf34274beccf851d0360929fe6d5a72653b2 Mon Sep 17 00:00:00 2001 From: heytdep Date: Thu, 7 Nov 2024 12:24:40 +0700 Subject: [PATCH 5/6] add test where caller does not enable reentry --- soroban-env-host/src/test/lifecycle.rs | 14 +++++++- soroban-env-host/src/vm.rs | 2 +- soroban-test-wasms/src/lib.rs | 3 ++ soroban-test-wasms/wasm-workspace/Cargo.lock | 8 +++++ soroban-test-wasms/wasm-workspace/Cargo.toml | 1 + .../wasm-workspace/no_reentry_a/Cargo.toml | 19 +++++++++++ .../wasm-workspace/no_reentry_a/src/lib.rs | 31 ++++++++++++++++++ .../opt/23/example_no_reentry_a.wasm | Bin 0 -> 2244 bytes 8 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml create mode 100644 soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs create mode 100755 soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index c5e3f56ef..b58ebeef1 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2402,7 +2402,7 @@ mod cap_xx_opt_in_reentry { use crate::{Host, HostError, MeteredOrdMap}; use soroban_env_common::{AddressObject, Env, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; use soroban_test_wasms::{ - SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B, + SIMPLE_NO_REENTRY_CONTRACT_A, SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B }; use stellar_xdr::curr::{ ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash, @@ -2453,6 +2453,18 @@ mod cap_xx_opt_in_reentry { call_contract(&host, contract_id_a, args); } + #[test] + #[should_panic] + fn test_reentry_disabled_from_caller() { + let host = Host::test_host_with_recording_footprint(); + let contract_id_a = host.register_test_contract_wasm(SIMPLE_NO_REENTRY_CONTRACT_A); + let contract_id_b = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_B); + host.enable_debug().unwrap(); + let args = test_vec![&host, contract_id_b].into(); + + call_contract(&host, contract_id_a, args); + } + fn call_contract(host: &Host, called: AddressObject, args: VecObject) { let fname = Symbol::try_from_val(host, &"test_reentry").unwrap(); host.call(called, fname, args).unwrap(); diff --git a/soroban-env-host/src/vm.rs b/soroban-env-host/src/vm.rs index b50f6c401..9591fdd62 100644 --- a/soroban-env-host/src/vm.rs +++ b/soroban-env-host/src/vm.rs @@ -110,7 +110,7 @@ impl Host { if symbols.contains(&("d", "1")) || symbols.contains(&("d", "2")) { return Err(crate::Error::from_type_and_code( ScErrorType::WasmVm, - ScErrorCode::ArithDomain, + ScErrorCode::InvalidAction, ) .try_into()?); } diff --git a/soroban-test-wasms/src/lib.rs b/soroban-test-wasms/src/lib.rs index c69f67dc8..258bbc6c2 100644 --- a/soroban-test-wasms/src/lib.rs +++ b/soroban-test-wasms/src/lib.rs @@ -123,6 +123,9 @@ pub const CUSTOM_ACCOUNT_CONTEXT_TEST_CONTRACT: &[u8] = pub const SIMPLE_REENTRY_CONTRACT_A: &[u8] = include_bytes!("../wasm-workspace/opt/23/example_reentry_a.wasm").as_slice(); +pub const SIMPLE_NO_REENTRY_CONTRACT_A: &[u8] = + include_bytes!("../wasm-workspace/opt/23/example_no_reentry_a.wasm").as_slice(); + pub const SIMPLE_REENTRY_CONTRACT_B: &[u8] = include_bytes!("../wasm-workspace/opt/23/example_reentry_b.wasm").as_slice(); diff --git a/soroban-test-wasms/wasm-workspace/Cargo.lock b/soroban-test-wasms/wasm-workspace/Cargo.lock index 7cd3acb10..bc0f31938 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.lock +++ b/soroban-test-wasms/wasm-workspace/Cargo.lock @@ -521,6 +521,14 @@ dependencies = [ "soroban-sdk", ] +[[package]] +name = "example_no_reentry_a" +version = "0.0.0" +dependencies = [ + "soroban-env-common 22.0.0-rc.1", + "soroban-sdk", +] + [[package]] name = "example_no_reentry_b" version = "0.0.0" diff --git a/soroban-test-wasms/wasm-workspace/Cargo.toml b/soroban-test-wasms/wasm-workspace/Cargo.toml index ce4e6e734..f2a708459 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.toml +++ b/soroban-test-wasms/wasm-workspace/Cargo.toml @@ -51,6 +51,7 @@ members = [ "constructor_with_result", "custom_account_context", "reentry_a", + "no_reentry_a", "no_reentry_b", "reentry_b", ] diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml b/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml new file mode 100644 index 000000000..3a4b2553d --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_no_reentry_a" +version = "0.0.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +soroban-env-common = { workspace = true } + +[features] +next = ["soroban-env-common/next"] diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs b/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs new file mode 100644 index 000000000..2ba311eae --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs @@ -0,0 +1,31 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Address, Symbol, TryIntoVal, Vec, Val}; + +#[link(wasm_import_module = "d")] +extern "C" { + #[allow(improper_ctypes)] + #[link_name = "_"] + pub fn call_contract(contract: i64, func: i64, args: i64, ) -> i64; +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn test_reentry(env: Env, called: Address) { + let args: Vec = (env.current_contract_address(), ).try_into_val(&env).unwrap(); + let func = Symbol::new(&env, "do_reentry"); + let called_val = called.as_val().get_payload() as i64; + let func_val = func.as_val().get_payload() as i64; + let args_val = args.as_val().get_payload() as i64; + + unsafe { + call_contract(called_val, func_val, args_val); + }; + } + + pub fn do_nothing(env: Env) { + env.events().publish((Symbol::new(&env, "first_soroban_reentry"),), ()); + } +} diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm new file mode 100755 index 0000000000000000000000000000000000000000..1165746cd053ccd5249012fbb0a9482ad12d6a34 GIT binary patch literal 2244 zcmdT_J8v6D5T4n+qfU3EyoO~!k%DM>b|Dp(be2peshn?;N0r`I1>sPyR-0pWDfafYccD zRIS%~u@wH3!s0)Oa(Ly0J}?`tP+qm9mRe|3kC|PTpk+mrrKhEtPiXPd#qRc~KC||u zw<1SQQgm41RZWyDcI1v0y9Lw^>7x2_6wx8?r0DWS zPRuYViaZ2?28}kRLG^X2>}jZ^D9uKa;tyV$7HXkB8U^{^rL`-#_p<9!tx#mwCAci= zd(KNxJy#|CzFVO74w&|ebel$HrO`5Y2XS=ex)oyP12q*8>bo=$jFS)cSOH3cEuE6c(aA?DlAQc{|mXXIHaTn~72Ej5M z5;-@QN@6~Eclw42>(oH53MiAIoj;xds>T-_I7BF(Q-Wcqb^lR$kzv%HMG78RZb{y}TYJdP5}FHmeDN<(hoXj%_LU zp&6GzJCoQy+t`;F3P+yg5jeyP775|Aiax72r&?r$`oP-!r|6*-<L;t^8qu)D<8^;?k`Og0z0WcHg z8nt`(;-)=any6c9`X@ROy>@XFByJxc#{Jqj&Sk6A8G|?{bi2LdxSP7kMQg7|YZG{0 zx7Ta7Qt|rrXzj*YbY-i2@J7^Z)JvPu#zv{!Y?im`jnY=FxfMm_&HD9bycxw&bO8SX DX#cd3 literal 0 HcmV?d00001 From abe39c335745dddfdf62f790405b21155559fa61 Mon Sep 17 00:00:00 2001 From: heytdep Date: Thu, 7 Nov 2024 12:24:58 +0700 Subject: [PATCH 6/6] fmt --- soroban-env-host/src/test/lifecycle.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index b58ebeef1..05aab7378 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2402,7 +2402,8 @@ mod cap_xx_opt_in_reentry { use crate::{Host, HostError, MeteredOrdMap}; use soroban_env_common::{AddressObject, Env, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; use soroban_test_wasms::{ - SIMPLE_NO_REENTRY_CONTRACT_A, SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B + SIMPLE_NO_REENTRY_CONTRACT_A, SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, + SIMPLE_REENTRY_CONTRACT_B, }; use stellar_xdr::curr::{ ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash,