Skip to content

[Vela OTA] Sub-Issue 11+12: Delta update engine + FlashPack Builder CLI#203

Closed
JusterZhu wants to merge 4 commits into
masterfrom
feat/vela-ota-11
Closed

[Vela OTA] Sub-Issue 11+12: Delta update engine + FlashPack Builder CLI#203
JusterZhu wants to merge 4 commits into
masterfrom
feat/vela-ota-11

Conversation

@JusterZhu

Copy link
Copy Markdown
Collaborator

Summary

Sub-Issue #11: Delta Update Engine

New \�ela-delta\ crate with sliding-window binary diff/patch:

  • \generate_delta(old, new)\ — diff generator
  • \�pply_patch(base, delta)\ — patch applier
  • \DeltaManifest\ — metadata for delta.manifest in .fpk
  • VDLT magic + SHA-256 dual hash integrity verification
  • 19 Rust tests, all passing

Sub-Issue #12: FlashPack Builder CLI

New \�ela-builder\ binary crate with 5 subcommands:

  • \�uild\ — construct .fpk from payload
  • \�erify\ — validate FlashPack structure
  • \info\ — detailed metadata display
  • \delta\ — binary diff generation via vela-delta
  • \sign\ — signature stub

Also fixed 40+ pre-existing compilation errors across the workspace.

Closes #202

Juster Zhu added 4 commits May 19, 2026 18:09
…ation (#199)

- Add vela-e2e integration test crate with 6 test suites (55 tests)
- Suite 1: Watchdog + EventBus — event emission, subscribers, history
- Suite 2: Slot Manager + Lifecycle — transitions, metrics, terminal states
- Suite 3: Hub Client + Retry + Download — retry exhaustion, checksum, auth
- Suite 4: Full Pipeline — phase order, terminal states, config
- Suite 5: Error Recovery — space errors, retry behavior, fallback path
- Suite 6: Configuration — defaults, custom configs, error conversions
- Add SlotManager + SlotLabel types to vela-slotmgr
- Fix 40+ pre-existing compilation errors across workspace crates
- Fix dependency versions (x509-cert, csbindgen, hmac, ring compat)
- Fix platform compatibility (watchdog on Windows via cfg guards)
- Fix API mismatches in orchestrator, hub client, download, flashpack
…202)

- Add vela-delta crate with sliding-window block-matching algorithm
- Binary diff generator: generate_delta(old, new) -> DeltaResult<Vec<u8>>
- Patch applier: apply_patch(base, delta) -> DeltaResult<Vec<u8>>
- DeltaManifest format for .fpk delta.manifest metadata
- VDLT magic header with SHA-256 integrity verification
- 19 unit tests including roundtrip, hash verification, edge cases
- Integrates with FlashPack PayloadType::Delta
- Add vela-builder binary crate with 5 subcommands
- build: construct .fpk from payload with configurable metadata
- verify: validate FlashPack structure and display header info
- info: detailed FlashPack metadata display (all header fields + SHA-256)
- delta: generate binary delta between two files via vela-delta
- sign: stub for future PEM key signing integration
- Fix import in vela-delta diff.rs
@JusterZhu

Copy link
Copy Markdown
Collaborator Author

Splitting into separate per-issue PRs

@JusterZhu JusterZhu closed this May 19, 2026

Copilot AI 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.

Pull request overview

Adds a new delta patching engine (vela-delta) and a FlashPack builder CLI (vela-builder) to support incremental OTA workflows within the vela-core workspace.

Changes:

  • Introduces vela-delta with a binary diff/patch format, manifest metadata, and unit tests.
  • Adds vela-builder CLI with subcommands to build/inspect/verify FlashPacks and generate deltas.
  • Registers both crates in the vela-core Cargo workspace.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/vela/vela-core/crates/vela-delta/src/lib.rs Defines public API, constants, hashing helper, and error types for delta engine.
src/vela/vela-core/crates/vela-delta/src/diff.rs Implements delta generation (sliding-window matching) and delta encoding format.
src/vela/vela-core/crates/vela-delta/src/patch.rs Implements patch application + integrity checks and patch-related tests.
src/vela/vela-core/crates/vela-delta/src/manifest.rs Adds DeltaManifest for recording baseline/target metadata and validation helpers.
src/vela/vela-core/crates/vela-delta/Cargo.toml Declares vela-delta crate dependencies.
src/vela/vela-core/crates/vela-builder/src/main.rs Adds vela-builder CLI entrypoint and subcommands.
src/vela/vela-core/crates/vela-builder/Cargo.toml Declares vela-builder binary crate and dependencies.
src/vela/vela-core/Cargo.toml Adds vela-delta and vela-builder to workspace members.
.github/issue-11-body.md Adds issue template/body documentation for Sub-Issue 11 (delta engine).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +22
// Validate magic
if delta.len() < 68 {
return Err(DeltaError::InvalidFormat(
"delta file too small — missing header".into(),
Comment on lines +125 to +133
Instruction::Copy { offset, length } => {
let start = *offset as usize;
let end = start + *length as usize;
if end > base.len() {
return Err(DeltaError::InvalidFormat(format!(
"COPY instruction {i}: offset {start} + length {length} exceeds base size {}",
base.len()
)));
}
Comment on lines +112 to +127
// Estimate target size from COPY+INSERT lengths
let target_size: usize = instructions
.iter()
.map(|i| match i {
Instruction::Copy { length, .. } => *length as usize,
Instruction::Insert { length, .. } => *length as usize,
})
.sum();

let mut target = Vec::with_capacity(target_size);

for (i, instr) in instructions.iter().enumerate() {
match instr {
Instruction::Copy { offset, length } => {
let start = *offset as usize;
let end = start + *length as usize;
Comment on lines +100 to +104
debug!(
parsed = pos,
total = data.len(),
"Extra bytes after instructions (ignored)"
);
Comment on lines +77 to +86
/// Generate a binary delta patch from `old` to `new`.
#[instrument(skip(old, new), fields(old_len = old.len(), new_len = new.len()))]
pub fn generate_delta(old: &[u8], new: &[u8]) -> DeltaResult<Vec<u8>> {
let instructions = if old.is_empty() {
vec![Instruction::Insert { length: new.len() as u32, data: new.to_vec() }]
} else if new.is_empty() {
return Err(DeltaError::InvalidFormat("cannot generate delta for empty target".into()));
} else {
sliding_window_diff(old, new)
};
Comment on lines +49 to +59
fn print_usage(prog: &str) {
eprintln!("FlashPack Builder CLI — Vela OTA update bundle tool\n");
eprintln!("Usage: {prog} <command> [args...]\n");
eprintln!("Commands:");
eprintln!(" build <payload> <output.fpk> Build a FlashPack bundle from a payload file");
eprintln!(" [--name <NAME>] [--version <VER>] [--requires <VER>]");
eprintln!(" sign <input.fpk> <key.pem> <output.fpk> Sign a FlashPack bundle");
eprintln!(" verify <input.fpk> <key.pub> Verify a FlashPack signature");
eprintln!(" info <input.fpk> Display FlashPack metadata and structure");
eprintln!(" delta <old> <new> <output.delta> Generate binary delta between two files");
}
Comment on lines +75 to +84
let mut i = 2;
while i < args.len() {
match args[i].as_str() {
"--name" => { i += 1; if i < args.len() { bundle_name = args[i].clone(); } }
"--version" => { i += 1; if i < args.len() { bundle_version = args[i].clone(); } }
"--requires" => { i += 1; if i < args.len() { requires_version = args[i].clone(); } }
_ => return Err(format!("unknown flag: {}", args[i])),
}
i += 1;
}
Comment on lines +83 to +95
/// Validate that the device's current version matches the required baseline.
pub fn validate_baseline(
&self,
device_version: &str,
) -> Result<(), String> {
if device_version != self.requires_version {
return Err(format!(
"Baseline version mismatch: device has {}, delta requires {}",
device_version, self.requires_version
));
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Vela OTA] Sub-Issue 11: Delta update engine — binary diff/patch

2 participants