From 0176bf331085908ffbb697da04ef9d3160b5d9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Wed, 21 May 2025 16:17:00 +0200 Subject: [PATCH 1/5] mine and verify Alephium PoW in script --- Cargo.lock | 3 + Cargo.toml | 3 + src/{main.rs => bin/demo.rs} | 15 +- src/bin/mine-pow-alephium.rs | 467 +++++++++++++++++++++++++++++++++++ src/core.rs | 65 +++-- src/lib.rs | 1 + src/output.rs | 2 +- 7 files changed, 530 insertions(+), 26 deletions(-) rename src/{main.rs => bin/demo.rs} (98%) create mode 100644 src/bin/mine-pow-alephium.rs diff --git a/Cargo.lock b/Cargo.lock index d51ee5c..cec39cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -653,11 +653,14 @@ dependencies = [ "bitcoincore-rpc", "bitvm", "blake3", + "byteorder", "clap", "hex", "indicatif", "itertools 0.14.0", "musig2", + "num-bigint", + "num-traits", "rand", "rstest", "secp256k1 0.29.1", diff --git a/Cargo.toml b/Cargo.toml index 5f7052b..e394e38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,9 @@ anyhow = "1.0.98" bitcoincore-rpc = "0.19.0" serde_json = "1.0" musig2 = { version = "0.2.4", features = ["serde", "rand", "k256"]} +byteorder = "1.5.0" +num-bigint = "0.4.6" +num-traits = "0.2.19" [profile.dev] opt-level = 3 diff --git a/src/main.rs b/src/bin/demo.rs similarity index 98% rename from src/main.rs rename to src/bin/demo.rs index 59cd2f4..bdeb30f 100644 --- a/src/main.rs +++ b/src/bin/demo.rs @@ -1,3 +1,7 @@ +//! ColliderVM Signet Demo Binary +// ...existing code from main.rs... +// ...existing code... + //! ColliderVM Signet Demo Binary //! //! This binary generates **real Bitcoin Signet transactions** that execute the @@ -38,6 +42,10 @@ use bitcoincore_rpc::{Auth, Client, RpcApi}; use clap::Parser; use collidervm_toy::core::{find_valid_nonce, flow_id_to_prefix_bytes}; use collidervm_toy::musig2::simulate_musig2; +use collidervm_toy::output::{ + DemoOutput, DemoParameters, KeyInfo, KeyPair, TransactionInfo, TxInfo, + write_demo_output_to_file, +}; use collidervm_toy::transactions::{ create_f1_tx, create_f2_tx, create_spending_tx, finalize_f1_tx, finalize_lock_tx, @@ -46,13 +54,8 @@ use collidervm_toy::utils::inner_from; use collidervm_toy::utils::{ wait_for_confirmation, wrap_network, write_transaction_to_file, }; -use std::str::FromStr; -mod output; -use output::{ - DemoOutput, DemoParameters, KeyInfo, KeyPair, TransactionInfo, TxInfo, - write_demo_output_to_file, -}; +use std::str::FromStr; /// Minimal amount we ask the user to deposit (200 000 sat ≈ 0.002 BTC) const REQUIRED_AMOUNT_SAT: u64 = 150_000; diff --git a/src/bin/mine-pow-alephium.rs b/src/bin/mine-pow-alephium.rs new file mode 100644 index 0000000..2db8aad --- /dev/null +++ b/src/bin/mine-pow-alephium.rs @@ -0,0 +1,467 @@ +// src/bin/mock_pool.rs +// Rust port of mock_pool.py: Alephium mock pool for gpu-miner connectivity tests +// Usage: cargo run --bin mock_pool -- --host 0.0.0.0 --port 10973 --difficulty 1 + +use bitcoin::opcodes::OP_TRUE; +use bitcoin::script::Builder; +use bitcoin::ScriptBuf; + +use bitcoin_script_stack::optimizer; +use bitvm::hash::blake3::blake3_push_message_script_with_limb; +use bitvm::{ + ExecuteInfo, + execute_script_buf, + hash::blake3::blake3_compute_script_with_limb, +}; + +use clap::Parser; + +use collidervm_toy::core::{ + blake3_message_to_limbs, build_drop, build_prefix_equalverify, + build_script_hash_to_limbs, combine_scripts, +}; + +use num_bigint::BigUint; +use num_traits::One; +use rand::RngCore; +use std::io::{self, Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::thread; + +const PROTO_VERSION: u8 = 1; +const MSG_JOBS: u8 = 0; +const MSG_SUBMIT_BLOCK: u8 = 0; +const HEADER_LEN: usize = 208; +const NONCE_LEN: usize = 24; +const BLAKE3_BUF_LEN: usize = 326; + +#[derive(Parser, Debug)] +struct Args { + #[arg(long, default_value = "0.0.0.0")] + host: String, + #[arg(long, default_value_t = 10973)] + port: u16, + #[arg(long, default_value_t = 1)] + difficulty: u64, +} + +fn u32be(i: u32) -> [u8; 4] { + i.to_be_bytes() +} + +fn blob(data: &[u8]) -> Vec { + let mut v = Vec::with_capacity(4 + data.len()); + v.extend(&(data.len() as u32).to_be_bytes()); + v.extend(data); + v +} + +fn build_job( + from_group: u32, + to_group: u32, + header_blob: &[u8], + txs_blob: &[u8], + target_blob: &[u8], + height: u32, +) -> Vec { + let mut v = Vec::new(); + v.extend(&u32be(from_group)); + v.extend(&u32be(to_group)); + v.extend(blob(header_blob)); + v.extend(blob(txs_blob)); + v.extend(blob(target_blob)); + v.extend(&u32be(height)); + v +} + +fn build_jobs_message(jobs: &[Vec]) -> Vec { + let mut body = vec![PROTO_VERSION, MSG_JOBS]; + body.extend(&u32be(jobs.len() as u32)); + for job in jobs { + body.extend(job); + } + let mut msg = Vec::new(); + msg.extend(&u32be(body.len() as u32)); + msg.extend(body); + msg +} + +pub fn target_from_difficulty(diff: u64) -> [u8; 32] { + if diff == 0 { + panic!("difficulty must be ≥ 1"); + } + + // max_target = 2^256 − 1 + let max_target = (BigUint::one() << 256) - BigUint::one(); + + let target: BigUint = max_target / BigUint::from(diff); + + // Convert to big-endian bytes and left-pad to 32 bytes + let raw = target.to_bytes_be(); + + if raw.len() > 32 { + panic!("target doesn’t fit in 32 bytes"); + } + + let mut bytes = [0u8; 32]; + + bytes[32 - raw.len()..].copy_from_slice(&raw); + bytes +} + +fn make_jobs(batch_id: u64, diff: u64) -> Vec> { + let mut jobs = Vec::new(); + let mut header_seed = [0u8; 32]; + let mut hasher = blake3::Hasher::new(); + hasher.update(&batch_id.to_le_bytes()); + header_seed.copy_from_slice(&hasher.finalize().as_bytes()[..32]); + for fg in 0..4 { + for tg in 0..4 { + let mut header = vec![0u8; HEADER_LEN]; + rand::thread_rng().fill_bytes(&mut header); + header[..header_seed.len()].copy_from_slice(&header_seed); + jobs.push(build_job( + fg, + tg, + &header, + &[], + &target_from_difficulty(diff), + 0, + )); + } + } + jobs +} + +fn recv_exact(stream: &mut TcpStream, n: usize) -> io::Result> { + let mut buf = vec![0u8; n]; + let mut read = 0; + while read < n { + let r = stream.read(&mut buf[read..])?; + if r == 0 { + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "socket closed", + )); + } + read += r; + } + Ok(buf) +} + +fn alephium_block_hash(nonce: &[u8], header: &[u8]) -> [u8; 32] { + if nonce.len() != NONCE_LEN || header.len() != HEADER_LEN { + panic!( + "Invalid nonce or header length: nonce={} bytes, header={} bytes", + nonce.len(), + header.len() + ); + } + let mut full_header = Vec::with_capacity(BLAKE3_BUF_LEN); + full_header.extend(nonce); + full_header.extend(header); + full_header.resize(BLAKE3_BUF_LEN, 0); + + let h1 = blake3::hash(&full_header); + let h2 = blake3::hash(h1.as_bytes()); + + // let h1_int = BigUint::from_bytes_be(h1.as_bytes()); + // let h2_int = BigUint::from_bytes_be(h2.as_bytes()); + // println!(" h1: {:0>64x}", h1_int); + // println!(" h2: {:0>64x}", h2_int); + + *h2.as_bytes() +} + +fn is_ok(nonce: &[u8], header: &[u8], target: &[u8]) -> bool { + let h2 = alephium_block_hash(nonce, header); + + let h2_int = BigUint::from_bytes_be(&h2); + let target_int = BigUint::from_bytes_be(target); + + h2_int < target_int +} + +// For debugging purposes, reconstruct the hash from the stack +#[allow(dead_code)] +fn reconstruct_hash_from_stack(result: &ExecuteInfo) -> BigUint { + // Reconstruct hash from nibbles on stack + let stack: Vec = result + .final_stack + .0 + .iter_str() + .map(|v| { + if v.len() > 4 { + panic!("Stack element too large to fit in u32: {:?}", v); + } + let mut arr = [0u8; 4]; + arr[4 - v.len()..].copy_from_slice(&v); + u32::from_be_bytes(arr) + }) + .collect(); + + let mut hash: Vec = Vec::with_capacity(32); + for i in 0..32 { + let hi = stack + .get(2 * i) + .copied() + .expect("Not enough stack elements for hi nibble"); + let lo = stack + .get(2 * i + 1) + .copied() + .expect("Not enough stack elements for lo nibble"); + if hi > 0xF || lo > 0xF { + panic!("Nibble value out of range: hi={}, lo={}", hi, lo); + } + let byte = ((hi as u8) << 4) | (lo as u8); + hash.push(byte); + } + BigUint::from_bytes_be(&hash) +} + +fn build_check_alephium_block_hash( + block: &[u8], + expected_block_hash: &[u8], +) -> ScriptBuf { + let limb_len = 16; + + // let message_limbs = blake3_message_to_limbs(&block, limb_len) + // .iter() + // .map(|&limb| limb as i64) + // .fold(Builder::new(), |b, limb| b.push_int(limb)) + // .into_script(); + + let message_limbs = blake3_push_message_script_with_limb(block, limb_len).compile(); + + let h1 = optimizer::optimize( + blake3_compute_script_with_limb(BLAKE3_BUF_LEN, limb_len).compile(), + ); + + let hash_to_limbs = build_script_hash_to_limbs(); + + let h2 = + optimizer::optimize(blake3_compute_script_with_limb(32, 4).compile()); + + let expected_nibbles = expected_block_hash + .iter() + .flat_map(|&byte| vec![(byte >> 4) & 0xF, byte & 0xF]) + .collect::>(); + + let to_drop = 64 - expected_nibbles.len(); + + let drop_tail = build_drop(to_drop); + + let prefix_cmp = build_prefix_equalverify(&expected_nibbles); + + let success_script = Builder::new().push_opcode(OP_TRUE).into_script(); + + combine_scripts(&[ + message_limbs, + h1, + hash_to_limbs, + h2, + drop_tail, + prefix_cmp, + success_script, + ]) +} + +pub fn verify_alephium_block_hash_with_script( + nonce: &[u8], + header: &[u8], + block_hash: &[u8], +) -> bool { + assert_eq!(nonce.len(), NONCE_LEN, "nonce must be 24 bytes"); + assert_eq!(header.len(), HEADER_LEN, "header must be 208 bytes"); + assert_eq!(block_hash.len(), 32, "block_hash must be 32 bytes"); + + let mut message = Vec::default(); + message.extend_from_slice(&nonce); + message.extend_from_slice(&header); + message.resize(BLAKE3_BUF_LEN, 0); + + let script = build_check_alephium_block_hash(&message, block_hash); + + let res = execute_script_buf(script); + + println!( + "Script executed with success: {}", + res.success + ); + println!("stack: {:?}", res.final_stack); + + return res.success; +} + +fn decode_submit_block(frame: &[u8]) -> Option<(Vec, Vec, Vec)> { + if frame.len() < 10 { + return None; + } + let total_len = + u32::from_be_bytes(frame[0..4].try_into().unwrap()) as usize; + let _ver = frame[4]; + let kind = frame[5]; + let block_size = + u32::from_be_bytes(frame[6..10].try_into().unwrap()) as usize; + if kind != MSG_SUBMIT_BLOCK + || total_len != frame.len() - 4 + || block_size != frame.len() - 10 + { + return None; + } + let mut pos = 10; + let nonce = frame[pos..pos + NONCE_LEN].to_vec(); + pos += NONCE_LEN; + let header = frame[pos..pos + HEADER_LEN].to_vec(); + pos += HEADER_LEN; + let txs = frame[pos..].to_vec(); + Some((nonce, header, txs)) +} + +fn handle_miner(mut stream: TcpStream, diff: u64) -> io::Result<()> { + println!("[+] Miner connected from {}", stream.peer_addr()?); + let batch_ctr = 0u64; + let target = target_from_difficulty(diff); + + // Send initial job set + let jobs_msg = build_jobs_message(&make_jobs(batch_ctr, diff)); + stream.write_all(&jobs_msg)?; + println!("[>] Pushed 16 templates"); + + loop { + let prefix = match recv_exact(&mut stream, 4) { + Ok(p) => p, + Err(_) => { + println!("[*] Miner disconnected"); + break Ok(()); + } + }; + let pay_len = + u32::from_be_bytes(prefix[..4].try_into().unwrap()) as usize; + let payload = match recv_exact(&mut stream, pay_len) { + Ok(p) => p, + Err(_) => { + println!("[*] Miner disconnected"); + break Ok(()); + } + }; + + let mut frame = prefix.clone(); + frame.extend(payload); + + if let Some((nonce, header, txs)) = decode_submit_block(&frame) { + let pow_ok = is_ok(&nonce, &header, &target); + + let block_hash = alephium_block_hash(&nonce, &header); + + let hash_ok = verify_alephium_block_hash_with_script( + &nonce, + &header, + &block_hash, + ); + println!( + "[{}] nonce {} txs {}", + if pow_ok && hash_ok { "✓" } else { "✗" }, + hex::encode(&nonce), + txs.len(), + ); + return Ok(()); + } else { + println!("[!] Bad frame"); + } + } +} + +fn main() -> io::Result<()> { + let args = Args::parse(); + let addr = format!("{}:{}", args.host, args.port); + let listener = TcpListener::bind(&addr)?; + println!("[+] Listening on {} diff={}", addr, args.difficulty); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let diff = args.difficulty; + thread::spawn(move || { + if let Err(e) = handle_miner(stream, diff) { + eprintln!("[!] Error handling miner: {}", e); + } + std::process::exit(0); + }); + } + Err(e) => { + eprintln!("Connection failed: {}", e); + } + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + fn hex_to_array(hex: &str) -> [u8; N] { + let bytes = hex::decode(hex).expect("Invalid hex string"); + assert_eq!(bytes.len(), N, "Length mismatch"); + let mut arr = [0u8; N]; + arr.copy_from_slice(&bytes); + arr + } + + const NONCE_HEX: &str = "bd193b24440aca7894a1edea53fc7bf0cc52c06e7b970562"; + const HEADER_HEX: &str = "71e0a99173564931c0b8acc52d2685a8e39c64dc52e3d02390fdac2a12b155cbfbd480ea895758fa18cb534cd1a8f2617a299636d8b77e186fa09b7e369036edadf5d00d823b299d67b91384bcfe977e1efdaf56575410bb59c9ef4dced5df13304357f20c8f8958499833c9d9385534929515b30aea4e19e8dabd1890d970e206d5088ec1125b2d2c9b15c008bff7e0e23cebe0a26fc2fdfc16d13443465828337e4e43ef84b0aee9a348a3baab8d3002e2de9b7adc6ccf3ac6b6d0d881a214914d16e6fcb595768e273e606379fd0e"; + const TARGET_HEX: &str = + "000000068db8bac710cb295e9e1b089a027525460aa64c2f837b4a2339c0ebed"; + + fn fixtures() -> ([u8; NONCE_LEN], [u8; HEADER_LEN], [u8; 32]) { + ( + hex_to_array::(NONCE_HEX), + hex_to_array::(HEADER_HEX), + hex_to_array::<32>(TARGET_HEX), + ) + } + + #[rstest] + #[case::valid(fixtures())] + fn test_verify_alephium_pow_with_script_valid( + #[case] (nonce, header, target): ( + [u8; NONCE_LEN], + [u8; HEADER_LEN], + [u8; 32], + ), + ) { + assert!(is_ok(&nonce, &header, &target)); + + let block_hash = alephium_block_hash(&nonce, &header); + + let res = verify_alephium_block_hash_with_script( + &nonce, + &header, + &block_hash, + ); + + assert!(res, "Expected success for valid PoW"); + } + + #[rstest] + #[case::invalid(fixtures())] + fn test_verify_alephium_pow_with_script_invalid( + #[case] (nonce, header, _): ( + [u8; NONCE_LEN], + [u8; HEADER_LEN], + [u8; 32], + ), + ) { + let mut block_hash = alephium_block_hash(&nonce, &header); + block_hash[0] ^= 0xFF; + + let res = verify_alephium_block_hash_with_script( + &nonce, + &header, + &block_hash, + ); + assert!(!res, "Expected failure for invalid PoW"); + } +} diff --git a/src/core.rs b/src/core.rs index f27ebde..68e0bf2 100644 --- a/src/core.rs +++ b/src/core.rs @@ -137,7 +137,7 @@ pub fn flow_id_to_prefix_bytes(flow_id: u32, b_bits: usize) -> Vec { } /// Helper: combine scripts (by just concatenating the raw bytes). -fn combine_scripts(fragments: &[ScriptBuf]) -> ScriptBuf { +pub fn combine_scripts(fragments: &[ScriptBuf]) -> ScriptBuf { let mut combined = Vec::new(); for frag in fragments { combined.extend(frag.to_bytes()); @@ -153,7 +153,7 @@ fn combine_scripts(fragments: &[ScriptBuf]) -> ScriptBuf { /// We need to take care of the fact that the prefix is now in nibbles. /// Also the ordering of elements on the stack. /// We need to push the prefix in reverse order to the stack. -fn build_prefix_equalverify(prefix_data: &[u8]) -> ScriptBuf { +pub fn build_prefix_equalverify(prefix_data: &[u8]) -> ScriptBuf { let mut b = Builder::new(); // Check each nibble individually, pushing in reverse order to match stack evaluation @@ -166,6 +166,14 @@ fn build_prefix_equalverify(prefix_data: &[u8]) -> ScriptBuf { b.into_script() } +pub fn build_drop(items: usize) -> ScriptBuf { + let mut b = Builder::new(); + for _ in 0..items { + b = b.push_opcode(opcodes::all::OP_DROP); + } + b.into_script() +} + /// duplicates (keeps) the first 8 nibbles, accumulates them into `x`, /// leaves `x` on the stack, original 24 nibbles untouched. fn build_script_reconstruct_x() -> ScriptBuf { @@ -229,14 +237,9 @@ pub fn build_script_f1_blake3_locked( // Needed nibbles: prefix_len (because now represented as nibbles) or B / 4 let needed_nibbles = prefix_len; let blake3_script_hash_len_nibbles = 64; - let to_drop = blake3_script_hash_len_nibbles - needed_nibbles; - let drop_script = { - let mut b = Builder::new(); - for _ in 0..to_drop { - b = b.push_opcode(opcodes::all::OP_DROP); - } - b.into_script() - }; + + let drop_script = + build_drop(blake3_script_hash_len_nibbles - needed_nibbles); // 6) compare prefix => OP_EQUALVERIFY let prefix_cmp_script = build_prefix_equalverify(flow_id_prefix); @@ -302,14 +305,9 @@ fn build_script_f2_blake3_locked_with_mode( // Needed nibbles: prefix_len (because now represented as nibbles) or B / 4 let needed_nibbles = prefix_len; let blake3_script_hash_len_nibbles = 64; - let to_drop = blake3_script_hash_len_nibbles - needed_nibbles; - let drop_script = { - let mut b = Builder::new(); - for _ in 0..to_drop { - b = b.push_opcode(opcodes::all::OP_DROP); - } - b.into_script() - }; + + let drop_script = + build_drop(blake3_script_hash_len_nibbles - needed_nibbles); // 6) compare prefix => OP_EQUALVERIFY let prefix_cmp_script = build_prefix_equalverify(flow_id_prefix); @@ -373,7 +371,7 @@ pub fn benchmark_hash_rate(duration_secs: u64) -> u64 { rate as u64 } -fn chunk_message(message_bytes: &[u8]) -> Vec<[u8; 64]> { +pub fn chunk_message(message_bytes: &[u8]) -> Vec<[u8; 64]> { let len = message_bytes.len(); let needed_padding_bytes = if len % 64 == 0 { 0 } else { 64 - (len % 64) }; @@ -443,6 +441,35 @@ pub fn blake3_message_to_limbs(message_bytes: &[u8], limb_len: u8) -> Vec { limbs } +pub fn build_script_hash_to_limbs() -> ScriptBuf { + let mut builder = Builder::new(); + + for _ in 0..56 { + builder = builder.push_opcode(opcodes::all::OP_TOALTSTACK); + } + for i in 0..8 { + for j in (0..8).step_by(2) { + builder = builder + .push_int(j) + .push_opcode(opcodes::all::OP_ROLL) + .push_int(j + 1) + .push_opcode(opcodes::all::OP_ROLL) + .push_opcode(opcodes::all::OP_SWAP); + } + if i != 7 { + for _ in 0..8 { + builder = builder.push_opcode(opcodes::all::OP_FROMALTSTACK); + } + } + } + + for _ in 0..64 { + builder = builder.push_int(0); + } + + builder.into_script() +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/lib.rs b/src/lib.rs index 379ae8f..ec99d52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod core; pub mod musig2; +pub mod output; pub mod transactions; pub mod utils; diff --git a/src/output.rs b/src/output.rs index 40af212..5d452e5 100644 --- a/src/output.rs +++ b/src/output.rs @@ -46,7 +46,7 @@ pub struct DemoParameters { } pub fn write_demo_output_to_file( - output: &crate::DemoOutput, + output: &DemoOutput, output_dir: &str, path: &str, ) -> Result<()> { From 3396a79a5afd8534b193576548c2b30ce494f475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Mon, 2 Jun 2025 15:59:13 +0200 Subject: [PATCH 2/5] fmt --- src/bin/mine-pow-alephium.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/bin/mine-pow-alephium.rs b/src/bin/mine-pow-alephium.rs index 2db8aad..8754f22 100644 --- a/src/bin/mine-pow-alephium.rs +++ b/src/bin/mine-pow-alephium.rs @@ -2,15 +2,14 @@ // Rust port of mock_pool.py: Alephium mock pool for gpu-miner connectivity tests // Usage: cargo run --bin mock_pool -- --host 0.0.0.0 --port 10973 --difficulty 1 +use bitcoin::ScriptBuf; use bitcoin::opcodes::OP_TRUE; use bitcoin::script::Builder; -use bitcoin::ScriptBuf; use bitcoin_script_stack::optimizer; use bitvm::hash::blake3::blake3_push_message_script_with_limb; use bitvm::{ - ExecuteInfo, - execute_script_buf, + ExecuteInfo, execute_script_buf, hash::blake3::blake3_compute_script_with_limb, }; @@ -231,7 +230,8 @@ fn build_check_alephium_block_hash( // .fold(Builder::new(), |b, limb| b.push_int(limb)) // .into_script(); - let message_limbs = blake3_push_message_script_with_limb(block, limb_len).compile(); + let message_limbs = + blake3_push_message_script_with_limb(block, limb_len).compile(); let h1 = optimizer::optimize( blake3_compute_script_with_limb(BLAKE3_BUF_LEN, limb_len).compile(), @@ -284,10 +284,7 @@ pub fn verify_alephium_block_hash_with_script( let res = execute_script_buf(script); - println!( - "Script executed with success: {}", - res.success - ); + println!("Script executed with success: {}", res.success); println!("stack: {:?}", res.final_stack); return res.success; From 1062ace12b03d01d1dd7412d04501ec4e608e849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Mon, 2 Jun 2025 16:05:37 +0200 Subject: [PATCH 3/5] clippy+fmt --- src/bin/mine-pow-alephium.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bin/mine-pow-alephium.rs b/src/bin/mine-pow-alephium.rs index 8754f22..60e27fd 100644 --- a/src/bin/mine-pow-alephium.rs +++ b/src/bin/mine-pow-alephium.rs @@ -16,8 +16,8 @@ use bitvm::{ use clap::Parser; use collidervm_toy::core::{ - blake3_message_to_limbs, build_drop, build_prefix_equalverify, - build_script_hash_to_limbs, combine_scripts, + build_drop, build_prefix_equalverify, build_script_hash_to_limbs, + combine_scripts, }; use num_bigint::BigUint; @@ -191,7 +191,7 @@ fn reconstruct_hash_from_stack(result: &ExecuteInfo) -> BigUint { .iter_str() .map(|v| { if v.len() > 4 { - panic!("Stack element too large to fit in u32: {:?}", v); + panic!("Stack element too large to fit in u32: {v:?}"); } let mut arr = [0u8; 4]; arr[4 - v.len()..].copy_from_slice(&v); @@ -210,7 +210,7 @@ fn reconstruct_hash_from_stack(result: &ExecuteInfo) -> BigUint { .copied() .expect("Not enough stack elements for lo nibble"); if hi > 0xF || lo > 0xF { - panic!("Nibble value out of range: hi={}, lo={}", hi, lo); + panic!("Nibble value out of range: hi={hi}, lo={lo}"); } let byte = ((hi as u8) << 4) | (lo as u8); hash.push(byte); @@ -276,8 +276,8 @@ pub fn verify_alephium_block_hash_with_script( assert_eq!(block_hash.len(), 32, "block_hash must be 32 bytes"); let mut message = Vec::default(); - message.extend_from_slice(&nonce); - message.extend_from_slice(&header); + message.extend_from_slice(nonce); + message.extend_from_slice(header); message.resize(BLAKE3_BUF_LEN, 0); let script = build_check_alephium_block_hash(&message, block_hash); @@ -287,7 +287,7 @@ pub fn verify_alephium_block_hash_with_script( println!("Script executed with success: {}", res.success); println!("stack: {:?}", res.final_stack); - return res.success; + res.success } fn decode_submit_block(frame: &[u8]) -> Option<(Vec, Vec, Vec)> { @@ -381,13 +381,13 @@ fn main() -> io::Result<()> { let diff = args.difficulty; thread::spawn(move || { if let Err(e) = handle_miner(stream, diff) { - eprintln!("[!] Error handling miner: {}", e); + eprintln!("[!] Error handling miner: {e}"); } std::process::exit(0); }); } Err(e) => { - eprintln!("Connection failed: {}", e); + eprintln!("Connection failed: {e}"); } } } From 079a9e73d3a5d65244887fb12feb53d28e89c26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Mon, 2 Jun 2025 16:18:59 +0200 Subject: [PATCH 4/5] fix demo CI --- .github/workflows/demo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index 35e7d65..d224863 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -49,7 +49,7 @@ jobs: run: docker exec bitcoind-regtest bitcoin-cli -regtest --rpcuser=user --rpcpassword=PaSsWoRd -generate 101 - name: Run - run: ./target/release/collidervm_toy + run: ./target/release/demo - name: Stop Bitcoin Regtest working-directory: scripts/demo From 901d507cf1a2cbf77954a400fe031d85c6735fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Tue, 3 Jun 2025 09:49:43 +0200 Subject: [PATCH 5/5] fix comments --- src/bin/mine-pow-alephium.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bin/mine-pow-alephium.rs b/src/bin/mine-pow-alephium.rs index 60e27fd..30180cc 100644 --- a/src/bin/mine-pow-alephium.rs +++ b/src/bin/mine-pow-alephium.rs @@ -44,10 +44,6 @@ struct Args { difficulty: u64, } -fn u32be(i: u32) -> [u8; 4] { - i.to_be_bytes() -} - fn blob(data: &[u8]) -> Vec { let mut v = Vec::with_capacity(4 + data.len()); v.extend(&(data.len() as u32).to_be_bytes()); @@ -64,23 +60,23 @@ fn build_job( height: u32, ) -> Vec { let mut v = Vec::new(); - v.extend(&u32be(from_group)); - v.extend(&u32be(to_group)); + v.extend(&from_group.to_be_bytes()); + v.extend(&to_group.to_be_bytes()); v.extend(blob(header_blob)); v.extend(blob(txs_blob)); v.extend(blob(target_blob)); - v.extend(&u32be(height)); + v.extend(&height.to_be_bytes()); v } fn build_jobs_message(jobs: &[Vec]) -> Vec { let mut body = vec![PROTO_VERSION, MSG_JOBS]; - body.extend(&u32be(jobs.len() as u32)); + body.extend(&jobs.len().to_be_bytes()); for job in jobs { body.extend(job); } let mut msg = Vec::new(); - msg.extend(&u32be(body.len() as u32)); + msg.extend(&body.len().to_be_bytes()); msg.extend(body); msg }