Skip to content

fix(engine)!: hard limit on template binary size - #1640

Merged
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:transaction-limit-binary-size
Nov 11, 2025
Merged

fix(engine)!: hard limit on template binary size#1640
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:transaction-limit-binary-size

Conversation

@sdbondi

@sdbondi sdbondi commented Nov 11, 2025

Copy link
Copy Markdown
Member

Description

fix(engine)!: hard limit on template binary size

Motivation and Context

Transaction cannot be constructed (in Rust code) with a binary that exceeds the pre-defined engine limit (currently 2MiB)
Serialized transactions that exceed this limit will be rejected at the decoding level.

How Has This Been Tested?

Existing tests

What process can a PR reviewer use to test or verify this change?

Breaking Changes

  • None
  • Requires data directory to be deleted
  • Other - Please specify

BREAKING CHANGE: JSON encoding for published binary data uses base64 encoding for compactness. This is a breaking change for any JSON-api that accepts transactions

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced type-safe template binary validation with automatic size enforcement for transaction publishing operations.
  • Bug Fixes

    • Improved error handling for oversized template binaries during transaction processing.
  • Refactor

    • Streamlined transaction processor initialization by eliminating intermediate configuration layers.
    • Adjusted template size limit to 2 MiB for improved resource efficiency.
    • Consolidated template binary handling with enhanced type-level safety checks.

@coderabbitai

coderabbitai Bot commented Nov 11, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request refactors the transaction template validation architecture by removing TransactionProcessorConfig entirely and relocating the maximum template binary size limit from ConsensusConstants to EngineLimits. A new TemplateBlob type (wrapping MaxBytes) enforces the size constraint at deserialization/conversion time. TransactionProcessor and related transaction execution paths are simplified to remove config threading, with validation now occurring earlier in the pipeline via try_into() conversions.

Changes

Cohort / File(s) Summary
TransactionProcessorConfig removal
crates/engine/src/transaction/config.rs, crates/engine/src/transaction/mod.rs, crates/engine/src/transaction/error.rs
Removed entire TransactionProcessorConfig struct (with network and template_binary_max_size_bytes fields), its constructors, and the WasmBinaryTooBig error variant.
TransactionProcessor simplification
crates/engine/src/transaction/processor.rs
Removed config field and constructor parameter from TransactionProcessor<TTemplateProvider>. Updated publish_template signature to accept TemplateBlob instead of Vec<u8> and removed config-based size validation.
TariTransactionProcessor updates
applications/tari_app_utilities/src/transaction_executor.rs
Removed config field from TariTransactionProcessor<TTemplateProvider> struct and removed config parameter from new(...) constructor.
TemplateBlob introduction
crates/transaction/src/v1/instruction.rs
Added public type TemplateBlob as MaxBytes wrapper with base64 serde encoding. Changed PublishTemplate.binary field type from Vec<u8> to TemplateBlob.
MaxBytes trait implementation
crates/template_lib_types/src/max_bytes.rs
Added as_slice(&self) -> &[u8] method and TryFrom<Box<[u8]>> trait implementation.
Template binary size limit relocation
crates/consensus/src/consensus_constants.rs, crates/engine_types/src/limits.rs
Removed template_binary_max_size_bytes from ConsensusConstants.devnet(). Added max_template_binary_size_bytes: 2 * 1024 * 1024 to EngineLimits.
Application bootstrap refactoring
applications/tari_indexer/src/bootstrap.rs, applications/tari_indexer/src/dry_run/processor.rs, applications/tari_validator_node/src/bootstrap.rs
Updated TariTransactionProcessor::new and DryRunTransactionProcessor::new calls to remove config parameter and pass FeeTable via get_fee_table_by_network() instead. Replaced config-based initialization with direct fee table argument.
Transaction builder and serialization updates
crates/transaction/src/builder/mod.rs, crates/p2p/src/conversions/transaction.rs
Updated publish_template method signature to accept TemplateBlob instead of Vec<u8>. Adjusted P2P conversion to apply try_into() on binary field with size validation error handling.
Template publishing validation
applications/tari_walletd/src/handlers/transaction.rs
Added try_into() conversion on WASM binary in handle_publish_template with error mapping for oversized binaries.
Test suite updates
crates/consensus_tests/src/consensus.rs, crates/consensus_tests/src/support/harness.rs, crates/engine/tests/publish_template.rs, crates/transaction/src/transaction.rs, crates/template_test_tooling/src/template_test.rs
Removed template_binary_max_size_bytes from test configurations. Updated PublishTemplate calls to use try_into().unwrap() for TemplateBlob conversion. Removed TransactionProcessorConfig and Network imports.
Documentation cleanup
crates/template_manager/src/implementation/service.rs
Simplified doc comments in add_pending_template call sites (no logic changes).

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Transaction Handler
    participant TxBuilder as TransactionBuilder
    participant Instruction as PublishTemplate<br/>(Instruction)
    participant TemplateBlob as TemplateBlob<br/>(MaxBytes)
    participant Processor as TransactionProcessor
    participant Runtime as Runtime

    Note over Caller,Runtime: New flow: Earlier validation via try_into()
    
    Caller->>TxBuilder: publish_template(binary: Vec<u8>)
    TxBuilder->>TemplateBlob: binary.try_into()
    alt Size within limit
        TemplateBlob-->>TxBuilder: Ok(TemplateBlob)
        TxBuilder->>Instruction: PublishTemplate { binary: TemplateBlob }
        Instruction-->>Caller: Transaction with validated blob
        Caller->>Processor: execute(transaction)
        Processor->>Runtime: publish_template(binary: TemplateBlob)
        Runtime-->>Processor: InstructionResult
    else Size exceeds limit
        TemplateBlob-->>TxBuilder: Err (size validation failed)
        TxBuilder-->>Caller: Error: invalid_params
    end

    Note over Caller,Runtime: Old flow (removed): Config-based validation
    Note over Caller,Runtime: TransactionProcessorConfig and size field removed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • High-impact public API changes: Removal of TransactionProcessorConfig struct and refactoring of TransactionProcessor::new and TariTransactionProcessor::new signatures across multiple crates affects multiple consumers.
  • Validation logic shift: Key behavioral change from constructor-time validation (via config) to deserialization-time validation (via try_into()), requiring careful verification in crates/p2p/src/conversions/transaction.rs and applications/tari_walletd/src/handlers/transaction.rs.
  • TemplateBlob type introduction: New MaxBytes wrapper and associated trait implementations (TryFrom<Box<[u8]>>, as_slice) need careful examination in crates/template_lib_types/src/max_bytes.rs and crates/transaction/src/v1/instruction.rs.
  • Distributed changes: Coordinated updates across 20+ files with interconnected API changes (bootstrap files, processor implementations, type definitions, tests).
  • Relocation of limits: Template size limit moved from ConsensusConstants to EngineLimits; verify all references updated and no orphaned references remain.

Areas requiring extra attention:

  • crates/engine/src/transaction/processor.rs — logic changes in instruction processing pipeline; verify publish_template behavior matches old contract minus config validation
  • crates/transaction/src/v1/instruction.rs — TemplateBlob serde encoding (base64); verify round-trip serialization/deserialization correctness
  • applications/tari_walletd/src/handlers/transaction.rs — new error path for oversized WASM; ensure error propagation is correct
  • crates/p2p/src/conversions/transaction.rs — deserialization error handling for size validation; confirm error messages are appropriate

Possibly related PRs

Suggested labels

refactoring, breaking-change, consensus-critical, P-acks_required, P-reviews_required

Poem

🐰 A hop through configs, now they're gone,
TemplateBlob validates at dawn,
EngineLimits holds the size,
No more threading, clean and wise,
Validation early, errors caught—
A cleaner arch, just as we ought!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.83% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(engine)!: hard limit on template binary size' directly and clearly summarizes the main objective of the PR: introducing a hard limit on template binary size in the engine.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df57b76 and 96f785a.

📒 Files selected for processing (21)
  • applications/tari_app_utilities/src/transaction_executor.rs (1 hunks)
  • applications/tari_indexer/src/bootstrap.rs (2 hunks)
  • applications/tari_indexer/src/dry_run/processor.rs (3 hunks)
  • applications/tari_validator_node/src/bootstrap.rs (0 hunks)
  • applications/tari_walletd/src/handlers/transaction.rs (1 hunks)
  • crates/consensus/src/consensus_constants.rs (0 hunks)
  • crates/consensus_tests/src/consensus.rs (2 hunks)
  • crates/consensus_tests/src/support/harness.rs (0 hunks)
  • crates/engine/src/transaction/config.rs (0 hunks)
  • crates/engine/src/transaction/error.rs (0 hunks)
  • crates/engine/src/transaction/mod.rs (0 hunks)
  • crates/engine/src/transaction/processor.rs (7 hunks)
  • crates/engine/tests/publish_template.rs (3 hunks)
  • crates/engine_types/src/limits.rs (2 hunks)
  • crates/p2p/src/conversions/transaction.rs (2 hunks)
  • crates/template_lib_types/src/max_bytes.rs (2 hunks)
  • crates/template_manager/src/implementation/service.rs (1 hunks)
  • crates/template_test_tooling/src/template_test.rs (2 hunks)
  • crates/transaction/src/builder/mod.rs (2 hunks)
  • crates/transaction/src/transaction.rs (1 hunks)
  • crates/transaction/src/v1/instruction.rs (4 hunks)
💤 Files with no reviewable changes (6)
  • crates/engine/src/transaction/error.rs
  • crates/engine/src/transaction/mod.rs
  • crates/consensus_tests/src/support/harness.rs
  • crates/consensus/src/consensus_constants.rs
  • crates/engine/src/transaction/config.rs
  • applications/tari_validator_node/src/bootstrap.rs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-04T10:10:24.258Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1629
File: applications/tari_walletd/src/handlers/accounts.rs:1001-1002
Timestamp: 2025-11-04T10:10:24.258Z
Learning: In applications/tari_walletd/src/handlers/accounts.rs, the expect() on Memo::new_pay_ref_and_bytes_truncate at line 1002 is safe and intentional. PayRef is validated to be at most 64 bytes during address decoding (PayRef::MAX_LEN = 64), and the function only returns None if payref exceeds 252 bytes (Memo::MAX_BYTES_LENGTH - 1). Since 64 < 252, None is impossible with a valid PayRef.

Applied to files:

  • crates/engine/tests/publish_template.rs
  • applications/tari_walletd/src/handlers/transaction.rs
🧬 Code graph analysis (9)
crates/transaction/src/builder/mod.rs (3)
crates/engine/src/transaction/processor.rs (1)
  • publish_template (451-458)
crates/engine/src/runtime/impl.rs (1)
  • publish_template (2713-2744)
crates/engine/src/runtime/mod.rs (1)
  • publish_template (191-191)
crates/template_lib_types/src/max_bytes.rs (3)
crates/template_lib_types/src/hash.rs (1)
  • as_slice (58-60)
crates/state_store_rocksdb/src/codecs/small_bytes.rs (1)
  • as_slice (59-61)
crates/template_lib_types/src/max_string.rs (1)
  • new_checked (24-31)
crates/p2p/src/conversions/transaction.rs (5)
crates/engine/src/transaction/processor.rs (1)
  • publish_template (451-458)
crates/transaction/src/builder/mod.rs (1)
  • publish_template (290-292)
crates/engine/src/runtime/impl.rs (1)
  • publish_template (2713-2744)
crates/engine/src/runtime/mod.rs (1)
  • publish_template (191-191)
integration_tests/src/template.rs (1)
  • publish_template (30-85)
crates/transaction/src/v1/instruction.rs (1)
bindings/src/types/Instruction.ts (1)
  • Instruction (18-45)
applications/tari_walletd/src/handlers/transaction.rs (1)
applications/tari_walletd/src/handlers/helpers.rs (1)
  • invalid_params (161-172)
crates/consensus_tests/src/consensus.rs (3)
crates/engine_types/src/hashing.rs (1)
  • hash_template_code (55-57)
crates/transaction/src/builder/mod.rs (1)
  • new (54-60)
crates/engine_types/src/published_template.rs (1)
  • from_author_and_binary_hash (43-49)
applications/tari_indexer/src/dry_run/processor.rs (2)
crates/engine/src/state_store/bootstrap.rs (1)
  • new_memory_store (6-8)
crates/engine/src/transaction/processor.rs (1)
  • new (91-107)
applications/tari_indexer/src/bootstrap.rs (2)
applications/tari_app_utilities/src/fee_tables.rs (1)
  • get_fee_table_by_network (26-35)
applications/tari_indexer/src/dry_run/processor.rs (1)
  • new (57-70)
crates/engine/src/transaction/processor.rs (4)
crates/transaction/src/builder/mod.rs (1)
  • publish_template (290-292)
crates/engine/src/runtime/impl.rs (1)
  • publish_template (2713-2744)
crates/engine/src/runtime/mod.rs (1)
  • publish_template (191-191)
crates/engine/src/wasm/module.rs (1)
  • load_template_from_code (65-100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test
  • GitHub Check: check stable
  • GitHub Check: check nightly
  • GitHub Check: machete
  • GitHub Check: clippy
🔇 Additional comments (3)
crates/template_manager/src/implementation/service.rs (1)

401-409: Documentation-only change—comment appropriately describes placeholder behavior.

The comment at line 402 is concise and clearly explains why "<unknown>" is used as a placeholder template name before download completion. This aligns with the actual code behavior.

crates/consensus_tests/src/consensus.rs (2)

1362-1372: LGTM! Clean refactor to precompute the hash.

The changes improve code clarity by precomputing the template binary hash once and reusing it throughout the test. The try_into().unwrap() on line 1364 correctly converts the raw WASM bytes to TemplateBlob, enforcing the new size limit. Since this test uses a known fixture (state.wasm), the unwrap is appropriate—if the fixture ever exceeds the limit, the test will fail fast, which is the desired behavior.


1415-1415: LGTM! Assertion correctly uses the precomputed hash.

Consistent with the earlier refactor, the assertion now compares against the expected_binary_hash defined at line 1362, improving test clarity and avoiding unnecessary recomputation.

Comment on lines 85 to 87
.fee_transaction_pay_from_component(account_address, 200_000)
.publish_template(random_wasm_binary)
.publish_template(random_wasm_binary.try_into().unwrap())
.build_and_seal(&account_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Don’t unwrap the oversize template blob
TemplateBlob now enforces the 2 MiB engine limit, so random_wasm_binary.try_into() returns Err for the 6 MiB sample. The unwrap() added here will panic and the test never reaches the engine rejection assertions. Please update this test to handle the Err (e.g. assert that the conversion fails before building the transaction, or restructure the scenario to exercise the serialized-transaction path) so the suite keeps running.

🤖 Prompt for AI Agents
In crates/engine/tests/publish_template.rs around lines 85 to 87, the test
currently calls random_wasm_binary.try_into().unwrap() which will panic because
TemplateBlob enforces a 2 MiB limit and the sample is 6 MiB; replace the unwrap
with proper handling: call random_wasm_binary.try_into(), match the Result, and
if it is Err assert that the conversion fails with the expected oversize/limit
error (so the test records the failure before building the transaction),
otherwise (if you want to test the engine rejection path) use a smaller wasm
sample or restructure the test to serialize and submit a transaction that
reaches the engine; ensure no unwrap is left so the test never panics.

@sdbondi
sdbondi merged commit 066d6f1 into tari-project:development Nov 11, 2025
12 of 13 checks passed
@sdbondi
sdbondi deleted the transaction-limit-binary-size branch November 11, 2025 09:28
@sdbondi sdbondi mentioned this pull request Nov 11, 2025
sdbondi added a commit that referenced this pull request Nov 11, 2025
Description
---
Forgot to push fixes in
#1640
@coderabbitai coderabbitai Bot mentioned this pull request Nov 12, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants