diff --git a/.changelog/unreleased/improvements/240-host-env-vp-write-check.md b/.changelog/unreleased/improvements/240-host-env-vp-write-check.md new file mode 100644 index 0000000000..ca42bc57ef --- /dev/null +++ b/.changelog/unreleased/improvements/240-host-env-vp-write-check.md @@ -0,0 +1,2 @@ +- Validate WASM code of validity predicates written by transactions. + ([#240](https://github.com/anoma/anoma/pull/240)) diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs index ac9f89c31e..ee9cd54704 100644 --- a/shared/src/vm/host_env.rs +++ b/shared/src/vm/host_env.rs @@ -40,15 +40,10 @@ pub enum TxRuntimeError { OutOfGas(gas::Error), #[error("Trying to modify storage for an address that doesn't exit {0}")] UnknownAddressStorageModification(Address), - #[error("Trying to update a validity predicate with an invalid WASM {0}")] - UpdateVpInvalid(WasmValidationError), + #[error("Trying to use a validity predicate with an invalid WASM {0}")] + InvalidVpCode(WasmValidationError), #[error("A validity predicate of an account cannot be deleted")] CannotDeleteVp, - #[error( - "Trying to initialize an account with an invalid validity predicate \ - WASM {0}" - )] - InitAccountInvalidVpWasm(WasmValidationError), #[error("Storage modification error: {0}")] StorageModificationError(write_log::Error), #[error("Storage error: {0}")] @@ -807,6 +802,9 @@ where tracing::debug!("tx_update {}, {:?}", key, value); let key = Key::parse(key).map_err(TxRuntimeError::StorageDataError)?; + if key.is_validity_predicate().is_some() { + tx_validate_vp_code(env, &value)?; + } check_address_existence(env, &key)?; @@ -1363,8 +1361,7 @@ where .map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?; tx_add_gas(env, gas)?; - tx_add_gas(env, code.len() as u64 * WASM_VALIDATION_GAS_PER_BYTE)?; - validate_untrusted_wasm(&code).map_err(TxRuntimeError::UpdateVpInvalid)?; + tx_validate_vp_code(env, &code)?; let write_log = unsafe { env.ctx.write_log.get() }; let (gas, _size_diff) = write_log @@ -1393,9 +1390,7 @@ where .map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?; tx_add_gas(env, gas)?; - tx_add_gas(env, code.len() as u64 * WASM_VALIDATION_GAS_PER_BYTE)?; - validate_untrusted_wasm(&code) - .map_err(TxRuntimeError::InitAccountInvalidVpWasm)?; + tx_validate_vp_code(env, &code)?; #[cfg(feature = "wasm-runtime")] { let vp_wasm_cache = unsafe { env.ctx.vp_wasm_cache.get() }; @@ -1696,6 +1691,21 @@ where Ok(()) } +/// Validate a VP WASM code in a tx environment. +fn tx_validate_vp_code( + env: &TxEnv, + code: &[u8], +) -> TxResult<()> +where + MEM: VmMemory, + DB: storage::DB + for<'iter> storage::DBIter<'iter>, + H: StorageHasher, + CA: WasmCacheAccess, +{ + tx_add_gas(env, code.len() as u64 * WASM_VALIDATION_GAS_PER_BYTE)?; + validate_untrusted_wasm(code).map_err(TxRuntimeError::InvalidVpCode) +} + /// Evaluate a validity predicate with the given input data. pub fn vp_eval( env: &VpEnv<'static, MEM, DB, H, EVAL, CA>,