# #43322 \[BC-High] inadequate transaction validation in da light node allows unprocessable block creation

## #43322 \[BC-High] Inadequate Transaction Validation in DA Light Node Allows Unprocessable Block Creation

**Submitted on Apr 4th 2025 at 15:50:51 UTC by @Blockian for** [**Attackathon | Movement Labs**](https://immunefi.com/audit-competition/movement-labs-attackathon)

* **Report ID:** #43322
* **Report Type:** Blockchain/DLT
* **Report severity:** High
* **Target:** <https://github.com/immunefi-team/attackathon-movement/tree/main/protocol-units/da/movement/protocol/light-node>
* **Impacts:**
  * Temporary freezing of network transactions by delaying one block by 500% or more of the average block time of the preceding 24 hours beyond standard difficulty adjustments

### Description

## Movement Bug Report

### Inadequate Transaction Validation in DA Light Node Allows Unprocessable Block Creation

#### Summary

The DA Light Node does not properly validate incoming transactions, which allows a malicious node to inject malformed data. If such a corrupt transaction is included in a block, it causes block execution to fail, thereby halting the processing of all other valid transactions in the same block.

### Root Cause Analysis

When a node processes a block, it calls the `execute_block` function:

```rs
	async fn execute_block(
		&mut self,
		block: Block,
		block_timestamp: u64,
	) -> anyhow::Result<BlockCommitment> {
		// ... (omitted non-relevant code)

		for transaction in block.transactions() {
			let signed_transaction: SignedTransaction = bcs::from_bytes(transaction.data())?;
        
        // ... (omitted non-relevant code)

        }
    }
```

If `transaction.data()` is not a valid `SignedTransaction`, the `bcs::from_bytes` call will return an error, which halts block execution.

Although blocks are sourced from the DA Light Node (assumed to be honest and under Movement's control), there is a validation gap during `batch_write`, which publishes transactions to the DA:

```rs
	async fn batch_write(
		&self,
		request: tonic::Request<grpc::BatchWriteRequest>,
	) -> std::result::Result<tonic::Response<grpc::BatchWriteResponse>, tonic::Status> {
		let blobs_for_submission = request.into_inner().blobs;

		// make transactions from the blobs
		let mut transactions = Vec::new();
		for blob in blobs_for_submission {
			let transaction: Transaction = serde_json::from_slice(&blob.data)
				.map_err(|e| tonic::Status::internal(e.to_string()))?;

			match &self.prevalidator {
				Some(prevalidator) => {
				// ... (omitted non-relevant code)
				}
				None => transactions.push(transaction),
			}
		}

		// publish the transactions
		let memseq = self.memseq.clone();
		memseq
			.publish_many(transactions)
			.await
			.map_err(|e| tonic::Status::internal(e.to_string()))?;

		Ok(tonic::Response::new(grpc::BatchWriteResponse { blobs: vec![] }))
	}
```

In the absence of a `prevalidator`, transactions are published without verifying that `transaction.data` is a valid `SignedTransaction`. The only check performed ensures it's a valid `Vec<u8>`, which is insufficient to guarantee executable block integrity.

### Impact

An attacker can exploit this validation gap by submitting a malformed transaction payload to the DA Light Node.

When an honest node subsequently pulls and attempts to execute a block containing this transaction, it will fail during deserialization, resulting in:

* Complete failure to process the block.
* Potential denial-of-service (DoS) vectors if such malformed blocks are propagated repeatedly.
* Loss of liveness in the network due to execution halts on otherwise valid blocks.

### Proposed Fixes

Introduce stricter validation logic in `batch_write` to ensure that all submitted transactions conform to the `SignedTransaction` format before being published.

### Proof of Concept

### Proof of Concept

1. Start the DA Light Node.
2. Create a malformed transaction with the following arbitrary values:
   * `data` = random `Vec<u8>`
   * `application_priority` = random `u64`
   * `sequence_number` = random `u64`
   * `id` = random `[u8; 32]`
3. Send a gRPC request to the Light Node's `write_batch` endpoint with the malformed transaction.

```rs
// Example: Randomly constructed Transaction (pseudo-code)
let corrupt_transaction = Transaction {
	data: vec![1, 255, 42, 0, 0, 100, 200],
	application_priority: 1,
	sequence_number: 1,
	id: [0u8; 32],
};
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reports.immunefi.com/movement-labs-attackathon/43322-bc-high-inadequate-transaction-validation-in-da-light-node-allows-unprocessable-block-creation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
