From 0bbeec2d6e5f6a484c797a7211a4ce99e3325c27 Mon Sep 17 00:00:00 2001 From: Dmytro Kozhevin Date: Mon, 17 Jul 2023 20:36:20 -0400 Subject: [PATCH] Update host to account for the XDR changes. (#954) * Update host to account for the XDR changes. --- Cargo.lock | 6 +- Cargo.toml | 2 +- soroban-env-host/src/auth.rs | 48 ++++--- soroban-env-host/src/events/internal.rs | 19 +-- soroban-env-host/src/events/mod.rs | 2 +- soroban-env-host/src/host/conversion.rs | 79 ++++++------ soroban-env-host/src/host/frame.rs | 48 +++---- .../src/native_contract/account_contract.rs | 20 ++- .../src/native_contract/testutils.rs | 30 +++-- soroban-env-host/src/test/auth.rs | 117 +++++++++--------- soroban-env-host/src/test/event.rs | 6 +- soroban-env-host/src/test/token.rs | 65 ++++------ soroban-test-wasms/wasm-workspace/Cargo.lock | 17 ++- .../delegated_account/src/lib.rs | 6 +- .../opt/example_simple_account.wasm | Bin 2066 -> 2000 bytes .../opt/test_delegated_account.wasm | Bin 2007 -> 2029 bytes .../wasm-workspace/simple_account/src/lib.rs | 12 +- 17 files changed, 212 insertions(+), 265 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9427252a..357375151 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1210,9 +1210,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" @@ -1537,7 +1537,7 @@ dependencies = [ [[package]] name = "stellar-xdr" version = "0.0.17" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=54c183e91573d8a5882ff1dda21d444ef42cc426#54c183e91573d8a5882ff1dda21d444ef42cc426" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=3a853f63639ba729454f53c16545dcddcaa59737#3a853f63639ba729454f53c16545dcddcaa59737" dependencies = [ "arbitrary", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index 67594e7e6..83bcb1c12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ soroban-native-sdk-macros = { version = "0.0.17", path = "soroban-native-sdk-mac [workspace.dependencies.stellar-xdr] version = "0.0.17" git = "https://github.com/stellar/rs-stellar-xdr" -rev = "54c183e91573d8a5882ff1dda21d444ef42cc426" +rev = "3a853f63639ba729454f53c16545dcddcaa59737" default-features = false [workspace.dependencies.wasmi] diff --git a/soroban-env-host/src/auth.rs b/soroban-env-host/src/auth.rs index b9d0017e0..5cac27961 100644 --- a/soroban-env-host/src/auth.rs +++ b/soroban-env-host/src/auth.rs @@ -5,10 +5,9 @@ use std::rc::Rc; use rand::Rng; use soroban_env_common::xdr::{ ContractDataEntry, ContractDataEntryBody, ContractDataEntryData, CreateContractArgs, - HashIdPreimage, HashIdPreimageSorobanAuthorization, LedgerEntry, LedgerEntryData, - LedgerEntryExt, ScAddress, ScErrorCode, ScErrorType, ScNonceKey, ScVal, - SorobanAuthorizationEntry, SorobanAuthorizedContractFunction, SorobanAuthorizedFunction, - SorobanCredentials, + HashIdPreimage, HashIdPreimageSorobanAuthorization, InvokeContractArgs, LedgerEntry, + LedgerEntryData, LedgerEntryExt, ScAddress, ScErrorCode, ScErrorType, ScNonceKey, ScVal, + SorobanAuthorizationEntry, SorobanAuthorizedFunction, SorobanCredentials, }; use soroban_env_common::{AddressObject, Compare, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; @@ -209,9 +208,9 @@ struct AccountAuthorizationTracker { // Helper for matching the tree that address authorized to the invocation // tree. invocation_tracker: InvocationTracker, - // Arguments representing the signature(s) made by the address to authorize + // Value representing the signature created by the address to authorize // the invocations tracked here. - signature_args: Vec, + signature: Val, // Indicates whether this tracker is still valid. If invalidated once, this // can't be used to authorize anything anymore is_valid: bool, @@ -382,14 +381,11 @@ impl AuthorizedFunction { &[], )); }; - Ok(SorobanAuthorizedFunction::ContractFn( - SorobanAuthorizedContractFunction { - contract_address: host - .scaddress_from_address(contract_fn.contract_address)?, - function_name, - args: host.rawvals_to_scvec(contract_fn.args.as_slice())?, - }, - )) + Ok(SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { + contract_address: host.scaddress_from_address(contract_fn.contract_address)?, + function_name, + args: host.rawvals_to_sc_val_vec(contract_fn.args.as_slice())?, + })) } AuthorizedFunction::CreateContractHostFn(create_contract_args) => { Ok(SorobanAuthorizedFunction::CreateContractHostFn( @@ -401,16 +397,16 @@ impl AuthorizedFunction { fn to_xdr_non_metered(&self, host: &Host) -> Result { match self { - AuthorizedFunction::ContractFn(contract_fn) => Ok( - SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + AuthorizedFunction::ContractFn(contract_fn) => { + Ok(SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: host .visit_obj(contract_fn.contract_address, |addr: &ScAddress| { Ok(addr.clone()) })?, function_name: contract_fn.function_name.try_into_val(host)?, - args: host.rawvals_to_scvec_non_metered(contract_fn.args.as_slice())?, - }), - ), + args: host.rawvals_to_sc_val_vec_non_metered(contract_fn.args.as_slice())?, + })) + } AuthorizedFunction::CreateContractHostFn(create_contract_args) => Ok( SorobanAuthorizedFunction::CreateContractHostFn(create_contract_args.clone()), ), @@ -1273,7 +1269,7 @@ impl AccountAuthorizationTracker { host: &Host, auth_entry: SorobanAuthorizationEntry, ) -> Result { - let (address, nonce, signature_args) = match auth_entry.credentials { + let (address, nonce, signature) = match auth_entry.credentials { SorobanCredentials::SourceAccount => ( host.source_account_address()?.ok_or_else(|| { host.err( @@ -1284,7 +1280,7 @@ impl AccountAuthorizationTracker { ) })?, None, - vec![], + Val::VOID.into(), ), SorobanCredentials::Address(address_creds) => ( host.add_host_object(address_creds.address)?, @@ -1292,14 +1288,14 @@ impl AccountAuthorizationTracker { address_creds.nonce, address_creds.signature_expiration_ledger, )), - host.scvals_to_rawvals(address_creds.signature_args.0.as_slice())?, + host.to_host_val(&address_creds.signature)?, ), }; let is_invoker = nonce.is_none(); Ok(Self { address, invocation_tracker: InvocationTracker::from_xdr(host, auth_entry.root_invocation)?, - signature_args, + signature, authenticated: false, need_nonce: !is_invoker, is_invoker, @@ -1347,7 +1343,7 @@ impl AccountAuthorizationTracker { Ok(Self { address, invocation_tracker: InvocationTracker::new_recording(function, current_stack_len), - signature_args: Default::default(), + signature: Val::VOID.into(), is_valid: true, authenticated: true, need_nonce: false, @@ -1543,14 +1539,14 @@ impl AccountAuthorizationTracker { let payload = self.get_signature_payload(host)?; match sc_addr { ScAddress::Account(acc) => { - check_account_authentication(host, acc, &payload, &self.signature_args)?; + check_account_authentication(host, acc, &payload, self.signature)?; } ScAddress::Contract(acc_contract) => { check_account_contract_auth( host, &acc_contract, &payload, - &self.signature_args, + self.signature, &self.invocation_tracker.root_authorized_invocation, )?; } diff --git a/soroban-env-host/src/events/internal.rs b/soroban-env-host/src/events/internal.rs index 782042a82..ac25e17ac 100644 --- a/soroban-env-host/src/events/internal.rs +++ b/soroban-env-host/src/events/internal.rs @@ -1,9 +1,6 @@ use std::rc::Rc; -use soroban_env_common::{ - xdr::{ScErrorCode, ScErrorType}, - BytesObject, VecObject, -}; +use soroban_env_common::{BytesObject, VecObject}; use super::{Events, HostEvent}; use crate::{ @@ -28,16 +25,7 @@ pub struct InternalContractEvent { impl InternalContractEvent { // Metering: covered by components pub fn to_xdr(&self, host: &Host) -> Result { - let topics = if let ScVal::Vec(Some(v)) = host.from_host_obj(self.topics)?.into() { - Ok(v) - } else { - Err(host.err( - ScErrorType::Events, - ScErrorCode::InvalidInput, - "converting event topics to vector", - &[self.topics.to_val()], - )) - }?; + let topics = host.call_args_to_sc_val_vec(self.topics)?; let data = host.from_host_val(self.data)?; let contract_id = match self.contract_id { Some(id) => Some(host.hash_from_bytesobj_input("contract_id", id)?), @@ -100,8 +88,7 @@ fn externalize_args(host: &Host, args: &[InternalDiagnosticArg]) -> Result Result { - let topics: Vec = externalize_args(host, &self.topics)?; - let topics = xdr::ScVec::from(xdr::VecM::try_from(topics)?); + let topics: xdr::VecM = externalize_args(host, &self.topics)?.try_into()?; let args = externalize_args(host, &self.args)?; let data = if args.len() > 1 { ScVal::Vec(Some(xdr::ScVec::from(xdr::VecM::try_from(args)?))) diff --git a/soroban-env-host/src/events/mod.rs b/soroban-env-host/src/events/mod.rs index 2e759819f..bbfd862d2 100644 --- a/soroban-env-host/src/events/mod.rs +++ b/soroban-env-host/src/events/mod.rs @@ -117,7 +117,7 @@ impl core::fmt::Display for HostEvent { match &self.event.body { ContractEventBody::V0(ceb) => { write!(f, "topics:[")?; - for (i, topic) in ceb.topics.0.iter().enumerate() { + for (i, topic) in ceb.topics.iter().enumerate() { if i != 0 { write!(f, ", ")?; } diff --git a/soroban-env-host/src/host/conversion.rs b/soroban-env-host/src/host/conversion.rs index 55315236b..d010d0cb7 100644 --- a/soroban-env-host/src/host/conversion.rs +++ b/soroban-env-host/src/host/conversion.rs @@ -12,7 +12,7 @@ use soroban_env_common::num::{ use soroban_env_common::xdr::{ self, int128_helpers, AccountId, ContractDataDurability, ContractEntryBodyType, DepthLimiter, Int128Parts, Int256Parts, ScAddress, ScBytes, ScErrorCode, ScErrorType, ScMap, ScMapEntry, - UInt128Parts, UInt256Parts, + UInt128Parts, UInt256Parts, VecM, }; use soroban_env_common::{ AddressObject, BytesObject, Convert, Object, ScValObjRef, ScValObject, TryFromVal, TryIntoVal, @@ -231,52 +231,53 @@ impl Host { }) } - // Metering: free? - pub(crate) fn call_args_to_scvec(&self, args: VecObject) -> Result { - self.visit_obj(args, |hv: &HostVec| self.rawvals_to_scvec(hv.as_slice())) + // Metering: covered by rawvals_to_vec + pub(crate) fn call_args_to_sc_val_vec( + &self, + args: VecObject, + ) -> Result, HostError> { + self.visit_obj(args, |hv: &HostVec| { + self.rawvals_to_sc_val_vec(hv.as_slice()) + }) } - pub(crate) fn rawvals_to_scvec(&self, raw_vals: &[Val]) -> Result { + pub(crate) fn rawvals_to_sc_val_vec(&self, raw_vals: &[Val]) -> Result, HostError> { charge_container_bulk_init_with_elts::, Val>( raw_vals.len() as u64, self.as_budget(), )?; - Ok(ScVec( - raw_vals - .iter() - .map(|v| self.from_host_val(*v)) - .collect::, HostError>>()? - .try_into() - .map_err(|_| { - err!( - self, - (ScErrorType::Object, ScErrorCode::ExceededLimit), - "vector size limit exceeded", - raw_vals.len() - ) - })?, - )) - } - - pub(crate) fn rawvals_to_scvec_non_metered( + raw_vals + .iter() + .map(|v| self.from_host_val(*v)) + .collect::, HostError>>()? + .try_into() + .map_err(|_| { + err!( + self, + (ScErrorType::Object, ScErrorCode::ExceededLimit), + "vector size limit exceeded", + raw_vals.len() + ) + }) + } + + pub(crate) fn rawvals_to_sc_val_vec_non_metered( &self, raw_vals: &[Val], - ) -> Result { - Ok(ScVec( - raw_vals - .iter() - .map(|v| v.try_into_val(self)?) - .collect::, HostError>>()? - .try_into() - .map_err(|_| { - err!( - self, - (ScErrorType::Object, ScErrorCode::ExceededLimit), - "vector size limit exceeded", - raw_vals.len() - ) - })?, - )) + ) -> Result, HostError> { + raw_vals + .iter() + .map(|v| v.try_into_val(self)?) + .collect::, HostError>>()? + .try_into() + .map_err(|_| { + err!( + self, + (ScErrorType::Object, ScErrorCode::ExceededLimit), + "vector size limit exceeded", + raw_vals.len() + ) + }) } pub(crate) fn scvals_to_rawvals(&self, sc_vals: &[ScVal]) -> Result, HostError> { diff --git a/soroban-env-host/src/host/frame.rs b/soroban-env-host/src/host/frame.rs index c257521ce..df711eded 100644 --- a/soroban-env-host/src/host/frame.rs +++ b/soroban-env-host/src/host/frame.rs @@ -6,7 +6,6 @@ use soroban_env_common::{ use crate::{ auth::AuthorizationManagerSnapshot, budget::AsBudget, - err, storage::{InstanceStorageMap, StorageMap}, xdr::{ContractCostType, ContractExecutable, Hash, HostFunction, HostFunctionType, ScVal}, Error, Host, HostError, Object, Symbol, SymbolStr, TryFromVal, TryIntoVal, Val, @@ -656,35 +655,24 @@ impl Host { fn invoke_function_raw(&self, hf: HostFunction) -> Result { let hf_type = hf.discriminant(); match hf { - HostFunction::InvokeContract(args) => { - if let [ScVal::Address(ScAddress::Contract(contract_id)), ScVal::Symbol(scsym), rest @ ..] = - args.as_slice() - { - self.with_frame(Frame::HostFunction(hf_type), || { - // Metering: conversions to host objects are covered. Cost of collecting - // Vals into Vec is ignored. Since 1. Vals are cheap to clone 2. the - // max number of args is fairly limited. - - let symbol: Symbol = scsym.as_slice().try_into_val(self)?; - let args = self.scvals_to_rawvals(rest)?; - // since the `HostFunction` frame must be the bottom of the call stack, - // reentry is irrelevant, we always pass in `ContractReentryMode::Prohibited`. - self.call_n_internal( - contract_id, - symbol, - &args[..], - ContractReentryMode::Prohibited, - false, - ) - }) - } else { - Err(err!( - self, - (ScErrorType::Context, ScErrorCode::UnexpectedSize), - "unexpected number of arguments to 'call' host function", - args.len() - )) - } + HostFunction::InvokeContract(invoke_args) => { + self.with_frame(Frame::HostFunction(hf_type), || { + // Metering: conversions to host objects are covered. + let ScAddress::Contract(ref contract_id) = invoke_args.contract_address else { + return Err(self.err(ScErrorType::Value, ScErrorCode::UnexpectedType, "invoked address doesn't belong to a contract", &[])); + }; + let function_name: Symbol = invoke_args.function_name.try_into_val(self)?; + let args = self.scvals_to_rawvals(invoke_args.args.as_slice())?; + // since the `HostFunction` frame must be the bottom of the call stack, + // reentry is irrelevant, we always pass in `ContractReentryMode::Prohibited`. + self.call_n_internal( + contract_id, + function_name, + args.as_slice(), + ContractReentryMode::Prohibited, + false, + ) + }) } HostFunction::CreateContract(args) => { self.with_frame(Frame::HostFunction(hf_type), || { diff --git a/soroban-env-host/src/native_contract/account_contract.rs b/soroban-env-host/src/native_contract/account_contract.rs index 4bc3a98e0..b8c780547 100644 --- a/soroban-env-host/src/native_contract/account_contract.rs +++ b/soroban-env-host/src/native_contract/account_contract.rs @@ -123,22 +123,17 @@ pub(crate) fn check_account_contract_auth( host: &Host, account_contract: &Hash, signature_payload: &[u8; 32], - signature_args: &Vec, + signature: Val, invocation: &AuthorizedInvocation, ) -> Result<(), HostError> { let payload_obj = host.bytes_new_from_slice(signature_payload)?; - let signature_args_vec = HostVec::try_from_val(host, signature_args)?; let mut auth_context_vec = HostVec::new(host)?; invocation_tree_to_auth_contexts(host, invocation, &mut auth_context_vec)?; Ok(host .call_n_internal( account_contract, ACCOUNT_CONTRACT_CHECK_AUTH_FN_NAME.try_into_val(host)?, - &[ - payload_obj.into(), - signature_args_vec.into(), - auth_context_vec.into(), - ], + &[payload_obj.into(), signature, auth_context_vec.into()], // Allow self reentry for this function in order to be able to do // wallet admin ops using the auth framework itself. ContractReentryMode::SelfAllowed, @@ -151,12 +146,13 @@ pub(crate) fn check_account_authentication( host: &Host, account_id: AccountId, payload: &[u8], - signatures: &Vec, + signature: Val, ) -> Result<(), HostError> { + let signatures: HostVec = signature.try_into_val(host)?; // Check if there is too many signatures: there shouldn't be more // signatures then the amount of account signers. - let len = signatures.len(); - if len > MAX_ACCOUNT_SIGNATURES as usize { + let len = signatures.len()?; + if len > MAX_ACCOUNT_SIGNATURES { return Err(err!( host, ContractError::AuthenticationError, @@ -168,8 +164,8 @@ pub(crate) fn check_account_authentication( let account = host.load_account(account_id)?; let mut prev_pk: Option> = None; let mut weight = 0u32; - for sig in signatures { - let sig = AccountEd25519Signature::try_from_val(host, sig)?; + for i in 0..len { + let sig: AccountEd25519Signature = signatures.get(i)?; // Cannot take multiple signatures from the same key if let Some(prev) = prev_pk { if prev.compare(&sig.public_key)? != Ordering::Less { diff --git a/soroban-env-host/src/native_contract/testutils.rs b/soroban-env-host/src/native_contract/testutils.rs index be5d65be9..8bbba3679 100644 --- a/soroban-env-host/src/native_contract/testutils.rs +++ b/soroban-env-host/src/native_contract/testutils.rs @@ -4,12 +4,12 @@ use rand::{thread_rng, Rng}; use soroban_env_common::xdr::{ AccountEntry, AccountEntryExt, AccountEntryExtensionV1, AccountEntryExtensionV1Ext, AccountEntryExtensionV2, AccountEntryExtensionV2Ext, AccountId, Hash, HashIdPreimage, - HashIdPreimageSorobanAuthorization, LedgerEntryData, LedgerKey, Liabilities, PublicKey, - ScAddress, ScSymbol, ScVec, SequenceNumber, SignerKey, SorobanAddressCredentials, - SorobanAuthorizationEntry, SorobanAuthorizedContractFunction, SorobanAuthorizedFunction, + HashIdPreimageSorobanAuthorization, InvokeContractArgs, LedgerEntryData, LedgerKey, + Liabilities, PublicKey, ScAddress, ScSymbol, ScVal, SequenceNumber, SignerKey, + SorobanAddressCredentials, SorobanAuthorizationEntry, SorobanAuthorizedFunction, SorobanAuthorizedInvocation, SorobanCredentials, Thresholds, Uint256, }; -use soroban_env_common::{EnvBase, TryFromVal}; +use soroban_env_common::{EnvBase, TryFromVal, Val}; use crate::native_contract::base_types::BytesN; @@ -62,14 +62,13 @@ pub(crate) enum TestSigner<'a> { AccountInvoker(AccountId), ContractInvoker(Hash), Account(AccountSigner<'a>), - #[allow(dead_code)] AccountContract(AccountContractSigner<'a>), } pub(crate) struct AccountContractSigner<'a> { pub(crate) address: Address, #[allow(clippy::type_complexity)] - pub(crate) sign: Box HostVec + 'a>, + pub(crate) sign: Box Val + 'a>, } pub(crate) struct AccountSigner<'a> { @@ -108,9 +107,9 @@ impl<'a> TestSigner<'a> { } } - fn sign(&self, host: &Host, payload: &[u8]) -> ScVec { - let signature_args = match self { - TestSigner::AccountInvoker(_) => host_vec![host], + fn sign(&self, host: &Host, payload: &[u8]) -> ScVal { + let signature: Val = match self { + TestSigner::AccountInvoker(_) | TestSigner::ContractInvoker(_) => Val::VOID.into(), TestSigner::Account(account_signer) => { let mut signatures = HostVec::new(&host).unwrap(); for key in &account_signer.signers { @@ -118,12 +117,11 @@ impl<'a> TestSigner<'a> { .push(&sign_payload_for_account(host, key, payload)) .unwrap(); } - signatures + signatures.into() } TestSigner::AccountContract(signer) => (signer.sign)(payload), - TestSigner::ContractInvoker(_) => host_vec![host], }; - host.call_args_to_scvec(signature_args.into()).unwrap() + host.from_host_val(signature).unwrap() } pub(crate) fn address(&self, host: &Host) -> Address { @@ -153,7 +151,7 @@ pub(crate) fn authorize_single_invocation_with_nonce( address: sc_address, nonce: nonce.unwrap().0, signature_expiration_ledger: nonce.unwrap().1, - signature_args: Default::default(), + signature: ScVal::Void, }) } TestSigner::ContractInvoker(_) => { @@ -163,10 +161,10 @@ pub(crate) fn authorize_single_invocation_with_nonce( }; let root_invocation = SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: contract_address.to_sc_address().unwrap(), function_name: ScSymbol(function_name.try_into().unwrap()), - args: host.call_args_to_scvec(args.into()).unwrap(), + args: host.call_args_to_sc_val_vec(args.into()).unwrap(), }), sub_invocations: Default::default(), }; @@ -184,7 +182,7 @@ pub(crate) fn authorize_single_invocation_with_nonce( signature_expiration_ledger: address_credentials.signature_expiration_ledger, }); let signature_payload = host.metered_hash_xdr(&signature_payload_preimage).unwrap(); - address_credentials.signature_args = signer.sign(host, &signature_payload); + address_credentials.signature = signer.sign(host, &signature_payload); } let auth_entry = SorobanAuthorizationEntry { credentials, diff --git a/soroban-env-host/src/test/auth.rs b/soroban-env-host/src/test/auth.rs index 4d9c51a92..924e1e959 100644 --- a/soroban-env-host/src/test/auth.rs +++ b/soroban-env-host/src/test/auth.rs @@ -2,8 +2,8 @@ use ed25519_dalek::Keypair; use rand::{thread_rng, Rng}; use soroban_env_common::xdr::{ AccountId, ContractDataDurability, HashIdPreimage, HashIdPreimageSorobanAuthorization, - PublicKey, ScAddress, ScBytes, ScErrorCode, ScErrorType, ScNonceKey, ScSymbol, ScVal, ScVec, - SorobanAddressCredentials, SorobanAuthorizationEntry, SorobanAuthorizedContractFunction, + InvokeContractArgs, PublicKey, ScAddress, ScBytes, ScErrorCode, ScErrorType, ScNonceKey, + ScSymbol, ScVal, SorobanAddressCredentials, SorobanAuthorizationEntry, SorobanAuthorizedFunction, SorobanAuthorizedInvocation, SorobanCredentials, Uint256, VecM, }; use soroban_native_sdk_macros::contracttype; @@ -44,7 +44,7 @@ struct SetupNode { struct SignNode { contract_address: Address, fn_name: Symbol, - args: ScVec, + args: VecM, children: Vec, } @@ -62,7 +62,7 @@ impl SignNode { fn new( contract_address: &Address, fn_name: Symbol, - args: ScVec, + args: VecM, children: Vec, ) -> Self { Self { @@ -78,7 +78,7 @@ impl SignNode { contract_address: contract_id.clone(), children, fn_name: Symbol::try_from_small_str("tree_fn").unwrap(), - args: ScVec::default(), + args: VecM::default(), } } } @@ -193,10 +193,12 @@ impl AuthTest { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: sc_address.clone(), nonce, - signature_args: self - .host - .call_args_to_scvec(signature_args.into()) - .unwrap(), + signature: ScVal::Vec(Some( + self.host + .call_args_to_sc_val_vec(signature_args.into()) + .unwrap() + .into(), + )), signature_expiration_ledger: 1000, }), root_invocation, @@ -295,7 +297,7 @@ impl AuthTest { let function_name: ScSymbol = ScSymbol(function_name.to_string().try_into().unwrap()); SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: root.contract_address.to_sc_address().unwrap(), function_name, args: root.args.clone(), @@ -1176,7 +1178,7 @@ fn test_out_of_order_auth() { &test.contracts[1], Symbol::try_from_small_str("do_auth").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![&test.host, test.key_to_address(&test.keys[0]), 10_u32] .into(), ) @@ -1191,7 +1193,7 @@ fn test_out_of_order_auth() { &test.contracts[0], Symbol::try_from_small_str("order_fn").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![ &test.host, test.key_to_address(&test.keys[0]), @@ -1217,7 +1219,7 @@ fn test_out_of_order_auth() { &test.contracts[0], Symbol::try_from_small_str("order_fn").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![ &test.host, test.key_to_address(&test.keys[0]), @@ -1232,7 +1234,7 @@ fn test_out_of_order_auth() { &test.contracts[1], Symbol::try_from_small_str("do_auth").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![&test.host, test.key_to_address(&test.keys[0]), 10_u32].into(), ) .unwrap(), @@ -1251,7 +1253,7 @@ fn test_out_of_order_auth() { &test.contracts[0], Symbol::try_from_small_str("order_fn").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![ &test.host, test.key_to_address(&test.keys[0]), @@ -1264,7 +1266,7 @@ fn test_out_of_order_auth() { &test.contracts[1], Symbol::try_from_small_str("do_auth").unwrap(), test.host - .call_args_to_scvec( + .call_args_to_sc_val_vec( host_vec![&test.host, test.key_to_address(&test.keys[0]), 10_u32].into(), ) .unwrap(), @@ -1449,17 +1451,15 @@ fn test_require_auth_within_check_auth() { let mut auth_entries = vec![]; // Payload for account 0 is just the normal contract call payload. let account_0_invocation = SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: auth_contract.to_sc_address().unwrap(), function_name: "do_auth".try_into().unwrap(), - args: ScVec( - vec![ - ScVal::Address(test.contracts[0].to_sc_address().unwrap()), - ScVal::U32(123), - ] - .try_into() - .unwrap(), - ), + args: vec![ + ScVal::Address(test.contracts[0].to_sc_address().unwrap()), + ScVal::U32(123), + ] + .try_into() + .unwrap(), }), sub_invocations: VecM::default(), }; @@ -1474,7 +1474,7 @@ fn test_require_auth_within_check_auth() { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: test.contracts[0].to_sc_address().unwrap(), nonce: 1111, - signature_args: ScVec(VecM::default()), + signature: ScVal::Void, signature_expiration_ledger: 1000, }), root_invocation: account_0_invocation, @@ -1487,16 +1487,14 @@ fn test_require_auth_within_check_auth() { // Account 1 needs to authorize `__check_auth` for account 0 with its // payload hash. let account_1_invocation = SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: test.contracts[0].to_sc_address().unwrap(), function_name: "__check_auth".try_into().unwrap(), - args: ScVec( - vec![ScVal::Bytes(ScBytes( - account_0_payload_hash.try_into().unwrap(), - ))] - .try_into() - .unwrap(), - ), + args: vec![ScVal::Bytes(ScBytes( + account_0_payload_hash.try_into().unwrap(), + ))] + .try_into() + .unwrap(), }), sub_invocations: VecM::default(), }; @@ -1512,7 +1510,7 @@ fn test_require_auth_within_check_auth() { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: test.contracts[1].to_sc_address().unwrap(), nonce: 2222, - signature_args: ScVec(VecM::default()), + signature: ScVal::Void, signature_expiration_ledger: 2000, }), root_invocation: account_1_invocation, @@ -1525,16 +1523,14 @@ fn test_require_auth_within_check_auth() { // Classic account needs to authorize `__check_auth` for account 1 with its // payload hash. let classic_account_invocation = SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: test.contracts[1].to_sc_address().unwrap(), function_name: "__check_auth".try_into().unwrap(), - args: ScVec( - vec![ScVal::Bytes(ScBytes( - account_1_payload_hash.try_into().unwrap(), - ))] - .try_into() - .unwrap(), - ), + args: vec![ScVal::Bytes(ScBytes( + account_1_payload_hash.try_into().unwrap(), + ))] + .try_into() + .unwrap(), }), sub_invocations: VecM::default(), }; @@ -1561,10 +1557,12 @@ fn test_require_auth_within_check_auth() { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: test.key_to_sc_address(&test.keys[0]), nonce: 4444, - signature_args: test - .host - .call_args_to_scvec(signature_args.clone().into()) - .unwrap(), + signature: ScVal::Vec(Some( + test.host + .call_args_to_sc_val_vec(signature_args.clone().into()) + .unwrap() + .into(), + )), signature_expiration_ledger: 3000, }), root_invocation: classic_account_invocation.clone(), @@ -1591,7 +1589,12 @@ fn test_require_auth_within_check_auth() { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: test.key_to_sc_address(&test.keys[0]), nonce: 3333, - signature_args: test.host.call_args_to_scvec(signature_args.into()).unwrap(), + signature: ScVal::Vec(Some( + test.host + .call_args_to_sc_val_vec(signature_args.into()) + .unwrap() + .into(), + )), signature_expiration_ledger: 3000, }), root_invocation: classic_account_invocation, @@ -1649,21 +1652,19 @@ fn test_require_auth_for_self_within_check_auth() { credentials: SorobanCredentials::Address(SorobanAddressCredentials { address: test.contracts[0].to_sc_address().unwrap(), nonce: 1111, - signature_args: ScVec(VecM::default()), + signature: ScVal::Void, signature_expiration_ledger: 1000, }), root_invocation: SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction { + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { contract_address: auth_contract.to_sc_address().unwrap(), function_name: "do_auth".try_into().unwrap(), - args: ScVec( - vec![ - ScVal::Address(test.contracts[0].to_sc_address().unwrap()), - ScVal::U32(123), - ] - .try_into() - .unwrap(), - ), + args: vec![ + ScVal::Address(test.contracts[0].to_sc_address().unwrap()), + ScVal::U32(123), + ] + .try_into() + .unwrap(), }), sub_invocations: VecM::default(), }, diff --git a/soroban-env-host/src/test/event.rs b/soroban-env-host/src/test/event.rs index 22c7893a0..e645ea403 100644 --- a/soroban-env-host/src/test/event.rs +++ b/soroban-env-host/src/test/event.rs @@ -97,7 +97,7 @@ fn test_event_rollback() -> Result<(), HostError> { ); host.try_borrow_events_mut()?.rollback(1)?; // run `UPDATE_EXPECT=true cargo test` to update this. - let expected = expect!["[HostEvent { event: ContractEvent { ext: V0, contract_id: Some(Hash(0000000000000000000000000000000000000000000000000000000000000000)), type_: Contract, body: V0(ContractEventV0 { topics: ScVec(VecM([I32(0), I32(1)])), data: U32(0) }) }, failed_call: false }, HostEvent { event: ContractEvent { ext: V0, contract_id: Some(Hash(0000000000000000000000000000000000000000000000000000000000000000)), type_: System, body: V0(ContractEventV0 { topics: ScVec(VecM([I32(0), I32(1)])), data: U32(0) }) }, failed_call: true }]"]; + let expected = expect!["[HostEvent { event: ContractEvent { ext: V0, contract_id: Some(Hash(0000000000000000000000000000000000000000000000000000000000000000)), type_: Contract, body: V0(ContractEventV0 { topics: VecM([I32(0), I32(1)]), data: U32(0) }) }, failed_call: false }, HostEvent { event: ContractEvent { ext: V0, contract_id: Some(Hash(0000000000000000000000000000000000000000000000000000000000000000)), type_: System, body: V0(ContractEventV0 { topics: VecM([I32(0), I32(1)]), data: U32(0) }) }, failed_call: true }]"]; let actual = format!("{:?}", host.try_borrow_events()?.externalize(&host)?.0); expected.assert_eq(&actual); Ok(()) @@ -126,8 +126,8 @@ fn test_internal_contract_events_metering_not_free() -> Result<(), HostError> { assert_eq!(host.as_budget().get_mem_bytes_consumed()?, 3); let _ = host.try_borrow_events()?.externalize(&host)?; - assert_eq!(host.as_budget().get_cpu_insns_consumed()?, 80); - assert_eq!(host.as_budget().get_mem_bytes_consumed()?, 8); + assert_eq!(host.as_budget().get_cpu_insns_consumed()?, 100); + assert_eq!(host.as_budget().get_mem_bytes_consumed()?, 10); Ok(()) } diff --git a/soroban-env-host/src/test/token.rs b/soroban-env-host/src/test/token.rs index 2f6c70d62..3003e79df 100644 --- a/soroban-env-host/src/test/token.rs +++ b/soroban-env-host/src/test/token.rs @@ -21,7 +21,7 @@ use crate::{ use ed25519_dalek::Keypair; use soroban_env_common::{ xdr::{ - self, AccountFlags, ScAddress, ScSymbol, ScVal, ScVec, SorobanAuthorizedContractFunction, + self, AccountFlags, InvokeContractArgs, ScAddress, ScSymbol, ScVal, SorobanAuthorizedFunction, SorobanAuthorizedInvocation, }, xdr::{ @@ -2646,15 +2646,9 @@ fn test_classic_transfers_not_possible_for_unauthorized_asset() { } #[allow(clippy::type_complexity)] -fn simple_account_sign_fn<'a>( - host: &'a Host, - kp: &'a Keypair, -) -> Box HostVec + 'a> { +fn simple_account_sign_fn<'a>(host: &'a Host, kp: &'a Keypair) -> Box Val + 'a> { use crate::native_contract::testutils::sign_payload_for_ed25519; - Box::new(|payload: &[u8]| -> HostVec { - let signature = sign_payload_for_ed25519(host, kp, payload); - host_vec![host, signature] - }) + Box::new(|payload: &[u8]| -> Val { sign_payload_for_ed25519(host, kp, payload).into() }) } #[test] @@ -2774,29 +2768,24 @@ fn test_recording_auth_for_token() { address: Some(admin.address(&test.host).to_sc_address().unwrap()), nonce: Some(0), invocation: SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn( - SorobanAuthorizedContractFunction { - contract_address: token.address.to_sc_address().unwrap(), - function_name: xdr::ScSymbol("mint".try_into().unwrap()), - args: ScVec( - vec![ - ScVal::try_from_val( - &test.host, - &Val::try_from_val(&test.host, &user.address(&test.host)) - .unwrap() - ) - .unwrap(), - ScVal::try_from_val( - &test.host, - &Val::try_from_val(&test.host, &100_i128).unwrap() - ) - .unwrap() - ] - .try_into() - .unwrap() - ), - } - ), + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { + contract_address: token.address.to_sc_address().unwrap(), + function_name: xdr::ScSymbol("mint".try_into().unwrap()), + args: vec![ + ScVal::try_from_val( + &test.host, + &Val::try_from_val(&test.host, &user.address(&test.host)).unwrap() + ) + .unwrap(), + ScVal::try_from_val( + &test.host, + &Val::try_from_val(&test.host, &100_i128).unwrap() + ) + .unwrap() + ] + .try_into() + .unwrap(), + }), sub_invocations: Default::default(), } }] @@ -2807,13 +2796,11 @@ fn test_recording_auth_for_token() { vec![( admin.address(&test.host).to_sc_address().unwrap(), SorobanAuthorizedInvocation { - function: SorobanAuthorizedFunction::ContractFn( - SorobanAuthorizedContractFunction { - contract_address: token.address.to_sc_address().unwrap(), - function_name: ScSymbol("mint".try_into().unwrap()), - args: test.host.call_args_to_scvec(args.into()).unwrap() - } - ), + function: SorobanAuthorizedFunction::ContractFn(InvokeContractArgs { + contract_address: token.address.to_sc_address().unwrap(), + function_name: ScSymbol("mint".try_into().unwrap()), + args: test.host.call_args_to_sc_val_vec(args.into()).unwrap() + }), sub_invocations: Default::default() } )] diff --git a/soroban-test-wasms/wasm-workspace/Cargo.lock b/soroban-test-wasms/wasm-workspace/Cargo.lock index 69f928e38..0ea17b686 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.lock +++ b/soroban-test-wasms/wasm-workspace/Cargo.lock @@ -447,7 +447,6 @@ dependencies = [ name = "example_hostile" version = "0.0.0" dependencies = [ - "soroban-env-common", "soroban-sdk", ] @@ -1052,7 +1051,7 @@ dependencies = [ "soroban-env-macros", "soroban-wasmi", "static_assertions", - "stellar-xdr 0.0.17 (git+https://github.com/stellar/rs-stellar-xdr?rev=54c183e91573d8a5882ff1dda21d444ef42cc426)", + "stellar-xdr 0.0.17 (git+https://github.com/stellar/rs-stellar-xdr?rev=a49a739d2af0d75814b62004a5c301ac2fd77036)", ] [[package]] @@ -1097,14 +1096,14 @@ dependencies = [ "quote", "serde", "serde_json", - "stellar-xdr 0.0.17 (git+https://github.com/stellar/rs-stellar-xdr?rev=54c183e91573d8a5882ff1dda21d444ef42cc426)", + "stellar-xdr 0.0.17 (git+https://github.com/stellar/rs-stellar-xdr?rev=a49a739d2af0d75814b62004a5c301ac2fd77036)", "syn 2.0.18", "thiserror", ] [[package]] name = "soroban-ledger-snapshot" -version = "0.9.2" +version = "0.9.1" dependencies = [ "serde", "serde_json", @@ -1125,7 +1124,7 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "0.9.2" +version = "0.9.1" dependencies = [ "arbitrary", "bytes-lit", @@ -1141,7 +1140,7 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "0.9.2" +version = "0.9.1" dependencies = [ "crate-git-revision", "darling", @@ -1159,7 +1158,7 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "0.9.2" +version = "0.9.1" dependencies = [ "base64 0.13.1", "stellar-xdr 0.0.17 (git+https://github.com/stellar/rs-stellar-xdr?rev=0f16673441898162c9996da6117be2280ef8fd84)", @@ -1169,7 +1168,7 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "0.9.2" +version = "0.9.1" dependencies = [ "prettyplease", "proc-macro2", @@ -1239,7 +1238,7 @@ dependencies = [ [[package]] name = "stellar-xdr" version = "0.0.17" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=54c183e91573d8a5882ff1dda21d444ef42cc426#54c183e91573d8a5882ff1dda21d444ef42cc426" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=a49a739d2af0d75814b62004a5c301ac2fd77036#a49a739d2af0d75814b62004a5c301ac2fd77036" dependencies = [ "arbitrary", "base64 0.13.1", diff --git a/soroban-test-wasms/wasm-workspace/delegated_account/src/lib.rs b/soroban-test-wasms/wasm-workspace/delegated_account/src/lib.rs index 32db3b4ce..641b8acb7 100644 --- a/soroban-test-wasms/wasm-workspace/delegated_account/src/lib.rs +++ b/soroban-test-wasms/wasm-workspace/delegated_account/src/lib.rs @@ -22,11 +22,11 @@ impl DelegatedAccount { pub fn __check_auth( env: Env, signature_payload: BytesN<32>, - signature_args: Vec, + signature: Val, _auth_context: Vec, ) { - if signature_args.len() != 0 { - panic!("incorrect number of signature args"); + if !signature.is_void() { + panic!("Unexpected signature provided"); } env.storage() .persistent() diff --git a/soroban-test-wasms/wasm-workspace/opt/example_simple_account.wasm b/soroban-test-wasms/wasm-workspace/opt/example_simple_account.wasm index 15ed616c5c93cacca0f0e56f3f70652e4571327f..ad4092f73adb8fb049839812c17c4ef92ff24ddd 100644 GIT binary patch delta 589 zcmXw#v2W8*5XSG`*-l(1=^Hvk6~nU|p=O|RnxuBb;#h(rCaA>3U>W1kI8rO6DHI_! z10xH?e*k8vv1eLPy7AvP@r9QsgG2S$;C$b ziq>(Zd`H)L{!FcTbzR}GS;!S`e$j$hIDdpN=6JdR!|yQhs0E4?1{89GfP6(mRdDeO z*$|PUHmOCOZ`!o!BJXA4TKrZ`Jd>ZA!)oCfybg;tfyV+>WhjXM;>-8~_U7jS0jrp8 zsxFKuMi*-6C{r(_zHTazmXyPfuzT*ZT$`G1#Zi{3XeCP%X%ofhiZ+E*Vk!Lz_NE$2 zV>JVcVsOQOD5J%GB9gWTG0M3S<9*|FiGbl+!o2SX*-m$~vz-pMgM2i&@pwF)J%901C%mGB=U0&UX( delta 638 zcmYk2F>ljQ5XbM{*{NG6?JH76R53ie5j0EWB&Bx5VjDqF7oZChvf?C7aik(8Y0E?g zz5vAxh>a-=MdBNPSSqpPBQP_tGQz!7R4jM*?(W_HcQ;>qBVXT9cWq2@4**ZF&GrSh zKyX}NWSW3y4?C)~Jnm1D=ch;g5v&%Iq{f%UWb4e?>+^RGalo!_F{ zXy#AJL77i!6N~wKy2-6 zNhv}_+d?Uf|KO|mJM52?xC%@Bqe|P3;E(82pimm}T7+#~h-BuNF*wNc)zCHeDj-4; zO524PWg*7L#!F=={aEs;tc=LY*f5|}MwP5t3AL9F#>jJQ2b8H*EM?}(+?dMQJuRaN z%07i037;P5XW)Y7xGY0#Nb>2?e%P@M&3)nyRiD@r6j4(zA zifA*f2GY%C^#r8FyMBT8Ig@d|>~P284i-D^(JG4XtdU^$kJVxp)(wZ8WPh>HzXFlV z`M`{cC+8o{3{Ugxh5OB#S8LT8Tj@csmv)~8+tx@o&Xg)|jKumul# z4e#RJLrxyVg9k-C7QA>66r|u;5DNYQI-4B4?2j2{=J)aTTmE<6f#~2K0svmMr_Oqw zty{Q_n^Zryk{HUQ%t4`IE?c3}Pl}+J^T9y#Xbr+M7!`~nNJC=4w+JBMx1?sCxqGu>z{U_)MKZPjnP|m_@wqPtV!} zGz3zFE{RAFmU(NIBl0ru(6|wnl7b-kGN(y5grY?nD6x`cbJow$8!uLT#drBBWBP&c>^qAb?&_D~BL39x zL}k-WJTnB3hsVdCfXsWqJCcWXS9BHxJW0(#+M~=U3nC+f1s+0^xx^rvEVXXxjIoNQ zzHB_dl1;tY3vXinB;@-0+;tj;>zXUnIMZK^>sp#2KGECe&7kgYv^OeialIAQ2K8Da zsthV|#cwo*er?!_8-6fo)`rb$)UF2cuzhW3e>`~%fAkOYZ7y@Lzk5HL9FAl9(ex{; F{tuRsbeI4D delta 676 zcmYLHy^9k;6n}4LHkr*Pxj_^|5S+~gyr6{52ic^{uAHYo8&H+=pji?8%Yi< zw6O^LN2C%ttn4f-4s5*2O1N6E7O~Jbk;7(Y-s z$AwW77~_3vKEs{$+5lW`U$;b>AvaTLv3y)_SlKY_4F|n(7#+=qkiih_Oc?f~SriTq z`wZ1<_!kMIw3ybIobZ}+eEbne zs`jZ3mY5GML(%|m8QMBaZkgARCHKr%^j2r)GLV$umyznajzaRG+ZFf+Q>y4gQb6cIb->TK)cBkffP1kKUyr}KcfA>52 dm3n_AKRwt#jAloZK^RT;r_=}bJ^7Gs{sn~(e%Am1 diff --git a/soroban-test-wasms/wasm-workspace/simple_account/src/lib.rs b/soroban-test-wasms/wasm-workspace/simple_account/src/lib.rs index bff539f1b..488617e68 100644 --- a/soroban-test-wasms/wasm-workspace/simple_account/src/lib.rs +++ b/soroban-test-wasms/wasm-workspace/simple_account/src/lib.rs @@ -25,17 +25,11 @@ impl SimpleAccount { pub fn __check_auth( env: Env, signature_payload: BytesN<32>, - signature_args: Vec>, + signature: BytesN<64>, _auth_context: Vec, ) { - if signature_args.len() != 1 { - panic!("incorrect number of signature args"); - } let public_key: BytesN<32> = env.storage().persistent().get(&DataKey::Owner).unwrap(); - env.crypto().ed25519_verify( - &public_key, - &signature_payload.into(), - &signature_args.get(0).unwrap(), - ); + env.crypto() + .ed25519_verify(&public_key, &signature_payload.into(), &signature); } }