Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/engine/src/transaction/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum TransactionError {
InvariantError { details: String },
#[error("Load template error: {0}")]
LoadTemplate(#[from] TemplateLoaderError),
#[error("WASM binary too big! {size} bytes are greater than allowed maximum {max} bytes.")]
WasmBinaryTooBig { size: usize, max: usize },
#[error("Template provider error: {0}")]
TemplateProvider(String),
#[error("Converting to hash error: {0}")]
Expand Down
10 changes: 10 additions & 0 deletions crates/engine/src/transaction/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use tari_engine_types::{
entity_id_provider::EntityIdProvider,
indexed_value::{IndexedValue, IndexedWellKnownTypes},
instruction_result::InstructionResult,
limits,
lock::LockFlag,
virtual_substate::VirtualSubstates,
};
Expand Down Expand Up @@ -449,6 +450,15 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T

/// Load, validate template binary and adds it to TemplateProvider.
fn publish_template(runtime: &Runtime, binary: TemplateBlob) -> Result<InstructionResult, TransactionError> {
if binary.len() > limits::ENGINE_LIMITS.max_template_binary_size_bytes {
// Technically, not possible, but this check is kept in to make a test pass, and potentially for additional
// safety.
return Err(TransactionError::WasmBinaryTooBig {
size: binary.len(),
max: limits::ENGINE_LIMITS.max_template_binary_size_bytes,
});
}

// validate binary
WasmModule::load_template_from_code(&binary)?;
// creating new substate
Expand Down
29 changes: 12 additions & 17 deletions crates/engine/tests/publish_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
use std::iter;

use rand::random;
use tari_engine::wasm::compile::compile_template;
use tari_engine::{transaction::TransactionError, wasm::compile::compile_template};
use tari_engine_types::{
commit_result::{RejectReason, TransactionResult},
hashing::{hash_template_code, hasher32, EngineHashDomainLabel},
limits,
published_template::PublishedTemplateAddress,
substate::{SubstateId, SubstateValue},
};
use tari_template_test_tooling::TemplateTest;
use tari_transaction::Transaction;
use tari_template_test_tooling::{support::assert_error::assert_reject_reason, TemplateTest};
use tari_transaction::{TemplateBlob, Transaction};

#[test]
fn publish_template_success() {
Expand Down Expand Up @@ -78,27 +79,21 @@ fn publish_template_invalid_binary() {
fn publish_template_too_big_binary() {
let mut test = TemplateTest::new(Vec::<String>::new());
let (account_address, owner_proof, account_key, _) = test.create_custom_funded_account(250_000);
let random_wasm_binary = generate_random_binary(6 * 1000 * 1000); // 6 MB
let random_wasm_binary = generate_random_binary(limits::ENGINE_LIMITS.max_template_binary_size_bytes + 1);
let wasm_binary_size = random_wasm_binary.len();
let result = test.execute_expect_failure(
let reason = test.execute_expect_failure(
Transaction::builder()
.fee_transaction_pay_from_component(account_address, 200_000)
.publish_template(random_wasm_binary.try_into().unwrap())
// SAFETY: We are intentionally publishing an oversized binary to test size limits.
.publish_template(unsafe { TemplateBlob::new_unchecked(random_wasm_binary) })
.build_and_seal(&account_key),
vec![owner_proof],
);

assert!(matches!(result, RejectReason::ExecutionFailure(_)));

if let RejectReason::ExecutionFailure(error) = result {
assert_eq!(
error,
format!(
"WASM binary too big! {} bytes are greater than allowed maximum 5000000 bytes.",
wasm_binary_size
)
);
}
assert_reject_reason(reason, TransactionError::WasmBinaryTooBig {
size: wasm_binary_size,
max: limits::ENGINE_LIMITS.max_template_binary_size_bytes,
});
}

fn generate_random_binary(size_in_bytes: usize) -> Vec<u8> {
Expand Down
10 changes: 10 additions & 0 deletions crates/template_lib_types/src/max_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ impl<const N: usize> MaxBytes<N> {
}
}

/// Constructs a new `MaxBytes<N>` without checking the length of the input.
/// This is the only way to break the invariant guarantees of `MaxBytes<N>`.
/// NOTE: this exists for testing purposes and should not be used in general.
///
/// # Safety
/// The caller must ensure that the length of `bytes` is less than or equal to `N`.
pub unsafe fn new_unchecked(bytes: impl Into<Box<[u8]>>) -> Self {
Self { bytes: bytes.into() }
}

pub fn into_vec(self) -> Vec<u8> {
self.bytes.into_vec()
}
Expand Down
Loading