Skip to content
Open
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
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ members = [
"examples/syscall-cycles",
"examples/std-smoke",
"examples/c-smoke/rust",
"examples/parallel-keccak",
"examples/batched-signatures",
"examples/merkle-tree",
"examples/parallel-mergesort",
"examples/matrix-multiply",
"examples/prefix-sum",
"examples/fft",
"examples/wavelet-transform",
"examples/graph-bfs",
"examples/block-compression",
"examples/polynomial-eval",
]
resolver = "2"

Expand Down
29 changes: 29 additions & 0 deletions examples/batched-signatures/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "batched-signatures"
publish = false
version.workspace = true
edition.workspace = true
description = "Batched Ed25519 signature verification demo"

[dependencies]
platform.workspace = true
debug.workspace = true
cfg-if.workspace = true

[features]
default = ["with-spike"]

debug = ["platform/debug"]

std = [
"platform/std",
"platform/vfs-device-console",
"platform/memory",
"platform/bounds-checks",
]

with-spike = ["platform/with-spike"]
# with-jolt = ["platform/with-jolt"] # Uncomment when jolt-platform exists

[target.'cfg(target_os = "none")'.dependencies]
platform = { workspace = true, features = ["memory"] }
166 changes: 166 additions & 0 deletions examples/batched-signatures/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//! Simplified Ed25519-like signature verification.
//!
//! This is a toy implementation for demonstration purposes.
//! In production, use a proper cryptographic library.
//!
//! The implementation focuses on exercising the computation patterns
//! without full cryptographic security.

#![no_std]

/// A simplified "public key" (32 bytes)
pub type PublicKey = [u8; 32];

/// A simplified "signature" (64 bytes)
pub type Signature = [u8; 64];

/// A message to verify
pub type Message<'a> = &'a [u8];

/// Verification result
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VerifyResult {
Valid,
Invalid,
}

/// Simple hash function for demonstration (not cryptographically secure!)
fn simple_hash(data: &[u8]) -> [u8; 32] {
let mut hash = [0u8; 32];
let mut acc: u64 = 0x5555555555555555;

for (i, &byte) in data.iter().enumerate() {
acc = acc.wrapping_mul(31).wrapping_add(byte as u64);
acc ^= acc.rotate_left(13);
hash[i % 32] ^= (acc & 0xFF) as u8;
acc = acc.wrapping_add((i as u64).wrapping_mul(17));
}

// Final mixing
for i in 0..32 {
acc = acc.wrapping_mul(0x5851F42D4C957F2D);
acc ^= acc >> 33;
hash[i] ^= (acc & 0xFF) as u8;
}

hash
}

/// Generate a deterministic "signature" for testing.
/// This is NOT real Ed25519 - just a demo to exercise computation patterns.
pub fn sign_message(secret_key: &[u8; 32], message: &[u8]) -> Signature {
let mut sig = [0u8; 64];

// First 32 bytes: hash of secret_key || message
let mut combined = [0u8; 64];
combined[..32].copy_from_slice(secret_key);
let msg_len = core::cmp::min(message.len(), 32);
combined[32..32 + msg_len].copy_from_slice(&message[..msg_len]);

let r = simple_hash(&combined);
sig[..32].copy_from_slice(&r);

// Second 32 bytes: hash of r || public_key || message
let public_key = derive_public_key(secret_key);
let mut combined2 = [0u8; 96];
combined2[..32].copy_from_slice(&r);
combined2[32..64].copy_from_slice(&public_key);
let msg_len2 = core::cmp::min(message.len(), 32);
combined2[64..64 + msg_len2].copy_from_slice(&message[..msg_len2]);

let s = simple_hash(&combined2);
sig[32..].copy_from_slice(&s);

sig
}

/// Derive "public key" from secret key (simplified)
pub fn derive_public_key(secret_key: &[u8; 32]) -> PublicKey {
simple_hash(secret_key)
}

/// Verify a signature against a public key and message.
/// Returns Valid if the signature matches, Invalid otherwise.
pub fn verify_signature(
public_key: &PublicKey,
message: &[u8],
signature: &Signature,
) -> VerifyResult {
// Reconstruct expected signature components
let r = &signature[..32];
let s = &signature[32..];

// Recompute s' = hash(r || public_key || message)
let mut combined = [0u8; 96];
combined[..32].copy_from_slice(r);
combined[32..64].copy_from_slice(public_key);
let msg_len = core::cmp::min(message.len(), 32);
combined[64..64 + msg_len].copy_from_slice(&message[..msg_len]);

let expected_s = simple_hash(&combined);

// Check if s matches expected
if s == expected_s {
VerifyResult::Valid
} else {
VerifyResult::Invalid
}
}

/// Batch verify multiple signatures (single-threaded baseline)
pub fn batch_verify(
public_keys: &[PublicKey],
messages: &[&[u8]],
signatures: &[Signature],
results: &mut [VerifyResult],
) {
let n = core::cmp::min(
core::cmp::min(public_keys.len(), messages.len()),
core::cmp::min(signatures.len(), results.len()),
);

for i in 0..n {
results[i] = verify_signature(&public_keys[i], messages[i], &signatures[i]);
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_sign_and_verify() {
let secret_key = [0x42u8; 32];
let public_key = derive_public_key(&secret_key);
let message = b"hello world";

let signature = sign_message(&secret_key, message);
let result = verify_signature(&public_key, message, &signature);

assert_eq!(result, VerifyResult::Valid);
}

#[test]
fn test_invalid_signature() {
let secret_key = [0x42u8; 32];
let public_key = derive_public_key(&secret_key);
let message = b"hello world";
let wrong_message = b"wrong message";

let signature = sign_message(&secret_key, message);
let result = verify_signature(&public_key, wrong_message, &signature);

assert_eq!(result, VerifyResult::Invalid);
}

#[test]
fn test_deterministic() {
let secret_key = [0x42u8; 32];
let message = b"test message";

let sig1 = sign_message(&secret_key, message);
let sig2 = sign_message(&secret_key, message);

assert_eq!(sig1, sig2);
}
}
96 changes: 96 additions & 0 deletions examples/batched-signatures/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! Batched signature verification demo.
//!
//! Demonstrates verifying multiple signatures using ZeroOS.
//! Each signature verification can be handled by a separate thread.

#![cfg_attr(target_os = "none", no_std)]
#![no_main]

use batched_signatures::{
batch_verify, derive_public_key, sign_message, verify_signature,
PublicKey, Signature, VerifyResult,
};

cfg_if::cfg_if! {
if #[cfg(target_os = "none")] {
use platform::println;
} else {
use std::println;
}
}

/// Number of signatures to verify in the batch
const BATCH_SIZE: usize = 8;

/// Generate test keypairs deterministically
fn generate_test_keypair(seed: u8) -> ([u8; 32], PublicKey) {
let mut secret = [0u8; 32];
for i in 0..32 {
secret[i] = seed.wrapping_add(i as u8).wrapping_mul(17);
}
let public = derive_public_key(&secret);
(secret, public)
}

#[no_mangle]
fn main() -> ! {
debug::writeln!("[batched-signatures] Starting signature verification demo");

// Generate test data
let mut secret_keys = [[0u8; 32]; BATCH_SIZE];
let mut public_keys = [[0u8; 32]; BATCH_SIZE];
let mut signatures = [[0u8; 64]; BATCH_SIZE];
let mut results = [VerifyResult::Invalid; BATCH_SIZE];

// Messages to sign/verify
let messages: [&[u8]; BATCH_SIZE] = [
b"transaction_0_transfer_100",
b"transaction_1_approve_token",
b"transaction_2_stake_amount",
b"transaction_3_withdraw_eth",
b"transaction_4_swap_tokens",
b"transaction_5_add_liquidity",
b"transaction_6_vote_proposal",
b"transaction_7_claim_reward",
];

// Generate keypairs and sign messages
debug::writeln!("[batched-signatures] Generating {} signatures", BATCH_SIZE);
for i in 0..BATCH_SIZE {
let (secret, public) = generate_test_keypair(i as u8);
secret_keys[i] = secret;
public_keys[i] = public;
signatures[i] = sign_message(&secret, messages[i]);
}

// Batch verify all signatures
debug::writeln!("[batched-signatures] Verifying signatures...");
batch_verify(&public_keys, &messages, &signatures, &mut results);

// Report results
let mut valid_count = 0;
for (i, result) in results.iter().enumerate() {
let status = match result {
VerifyResult::Valid => {
valid_count += 1;
"VALID"
}
VerifyResult::Invalid => "INVALID",
};
println!("sig[{}] = {}", i, status);
}

println!("Verified {}/{} signatures as valid", valid_count, BATCH_SIZE);

// Test with an invalid signature (wrong message)
debug::writeln!("[batched-signatures] Testing invalid signature detection...");
let invalid_result = verify_signature(&public_keys[0], b"wrong_message", &signatures[0]);
if invalid_result == VerifyResult::Invalid {
println!("Invalid signature correctly rejected");
} else {
println!("ERROR: Invalid signature was accepted!");
}

debug::writeln!("[batched-signatures] Demo complete!");
platform::exit(0)
}
29 changes: 29 additions & 0 deletions examples/block-compression/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "block-compression"
publish = false
version.workspace = true
edition.workspace = true
description = "Parallel block-wise LZ/RLE compression"

[dependencies]
platform.workspace = true
debug.workspace = true
cfg-if.workspace = true

[features]
default = ["with-spike"]

debug = ["platform/debug"]

std = [
"platform/std",
"platform/vfs-device-console",
"platform/memory",
"platform/bounds-checks",
]

with-spike = ["platform/with-spike"]
# with-jolt = ["platform/with-jolt"] # Uncomment when jolt-platform exists

[target.'cfg(target_os = "none")'.dependencies]
platform = { workspace = true, features = ["memory"] }
Loading
Loading