From 7635f1676f7f985d2a3d8ac247b3fd562a8dee0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Mon, 1 Dec 2025 09:56:02 +0000 Subject: [PATCH 1/2] Fix SparseRoots deserialization --- crates/raito-assumevalid/src/adapters.rs | 6 ++--- crates/raito-cairo-serialize/src/lib.rs | 31 +----------------------- crates/raito-spv-mmr/src/sparse_roots.rs | 2 +- packages/utils/src/mmr.cairo | 2 +- 4 files changed, 6 insertions(+), 35 deletions(-) diff --git a/crates/raito-assumevalid/src/adapters.rs b/crates/raito-assumevalid/src/adapters.rs index 72cfc6ea..2ebe662a 100644 --- a/crates/raito-assumevalid/src/adapters.rs +++ b/crates/raito-assumevalid/src/adapters.rs @@ -3,7 +3,7 @@ use bitcoin::block::Header; use stwo::core::vcs::blake2_merkle::Blake2sMerkleHasher; use stwo_cairo_serialize::CairoSerialize; -use raito_cairo_serialize::{DigestString, U256String, U256StringLittleEndian}; +use raito_cairo_serialize::{DigestString, U256String}; use raito_spv_mmr::sparse_roots::SparseRoots; use raito_spv_verify::ChainState; @@ -32,7 +32,7 @@ struct ChainStateView { #[derive(CairoSerialize)] pub struct SparseRootsView { - pub roots: Vec, + pub roots: Vec, } /// View for a single block matching Cairo's Block structure @@ -85,7 +85,7 @@ pub fn to_runner_args_hex( roots: block_mmr .roots .iter() - .map(|root_hex| U256StringLittleEndian(hex_u256_to_decimal_string(root_hex))) + .map(|root_hex| U256String(hex_u256_to_decimal_string(root_hex))) .collect(), }; diff --git a/crates/raito-cairo-serialize/src/lib.rs b/crates/raito-cairo-serialize/src/lib.rs index 88ef9395..5ca49a32 100644 --- a/crates/raito-cairo-serialize/src/lib.rs +++ b/crates/raito-cairo-serialize/src/lib.rs @@ -14,7 +14,6 @@ use stwo_cairo_serialize::serialize::CairoSerialize; pub struct U256String(pub String); pub struct ByteArrayString(pub String); pub struct DigestString(pub String); -pub struct U256StringLittleEndian(pub String); impl CairoSerialize for U256String { fn serialize(&self, output: &mut Vec) { @@ -43,34 +42,6 @@ impl CairoSerialize for U256String { } } -impl CairoSerialize for U256StringLittleEndian { - fn serialize(&self, output: &mut Vec) { - // Accept decimal string only, produce 32-byte big-endian - let s = self.0.trim(); - assert!( - !s.starts_with("0x") && !s.starts_with("0X"), - "Hex not supported for U256StringHiLo; use decimal", - ); - let n = BigUint::from_str_radix(s, 10).expect("Invalid decimal string for U256"); - let bytes = n.to_bytes_be(); - assert!(bytes.len() <= 32, "U256 value exceeds 256 bits"); - let mut be = [0u8; 32]; - be[32 - bytes.len()..].copy_from_slice(&bytes); - - // hi = most-significant 16 bytes, lo = least-significant 16 bytes - let (lo16, hi16) = be.split_at(16); - - let mut hi_bytes = [0u8; 32]; - hi_bytes[16..].copy_from_slice(hi16); - let mut lo_bytes = [0u8; 32]; - lo_bytes[16..].copy_from_slice(lo16); - - // Note: emit HI first, then LO to match Cairo MMR Serde (high, low) - output.push(FieldElement::from_bytes_be(&lo_bytes).unwrap()); - output.push(FieldElement::from_bytes_be(&hi_bytes).unwrap()); - } -} - impl CairoSerialize for ByteArrayString { // Split into 31-byte chunks and save the remainder fn serialize(&self, output: &mut Vec) { @@ -142,7 +113,7 @@ impl CairoSerialize for DigestString { // Backwards-compatibility: preserve `serializer::...` path pub mod serializer { - pub use super::{ByteArrayString, DigestString, U256String, U256StringLittleEndian}; + pub use super::{ByteArrayString, DigestString, U256String}; } #[cfg(test)] diff --git a/crates/raito-spv-mmr/src/sparse_roots.rs b/crates/raito-spv-mmr/src/sparse_roots.rs index 0a53cd69..c586a12d 100644 --- a/crates/raito-spv-mmr/src/sparse_roots.rs +++ b/crates/raito-spv-mmr/src/sparse_roots.rs @@ -83,8 +83,8 @@ where let lo_json_number = num_str_to_json_number::(lo)?; // Serialize as a dict with `hi` and `lo` keys (u256 in Cairo) let mut dict = serde_json::Map::new(); - dict.insert("hi".to_string(), hi_json_number.into()); dict.insert("lo".to_string(), lo_json_number.into()); + dict.insert("hi".to_string(), hi_json_number.into()); seq.serialize_element(&dict)?; } } diff --git a/packages/utils/src/mmr.cairo b/packages/utils/src/mmr.cairo index 1a031437..ba2856ed 100644 --- a/packages/utils/src/mmr.cairo +++ b/packages/utils/src/mmr.cairo @@ -41,8 +41,8 @@ pub impl MaybeBlake2sDigestSerde of Serde> { } fn deserialize(ref serialized: Span) -> Option> { - let high: u128 = Serde::deserialize(ref serialized).expect('digest::high'); let low: u128 = Serde::deserialize(ref serialized).expect('digest::low'); + let high: u128 = Serde::deserialize(ref serialized).expect('digest::high'); if high == 0 && low == 0 { Some(None) } else { From 87f8322fc74f6969dee387c1e99906455950a9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Mon, 1 Dec 2025 10:27:18 +0000 Subject: [PATCH 2/2] Fix integration tests --- packages/assumevalid/tests/data/batch_100.json | 4 ++-- packages/assumevalid/tests/data/batch_200.json | 6 +++--- packages/assumevalid/tests/data/batch_400.json | 4 ++-- packages/assumevalid/tests/data/blocks_0_1.json | 4 ++-- packages/assumevalid/tests/data/blocks_1_2.json | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/assumevalid/tests/data/batch_100.json b/packages/assumevalid/tests/data/batch_100.json index 5b5d2621..d57de314 100644 --- a/packages/assumevalid/tests/data/batch_100.json +++ b/packages/assumevalid/tests/data/batch_100.json @@ -1214,8 +1214,8 @@ "block_mmr": { "roots": [ { - "hi": 127393669198796545867873666634899495693, - "lo": 18179848941975845720653830328566420889 + "lo": 18179848941975845720653830328566420889, + "hi": 127393669198796545867873666634899495693 }, { "hi": 0, diff --git a/packages/assumevalid/tests/data/batch_200.json b/packages/assumevalid/tests/data/batch_200.json index 1ce5cd6c..80e92461 100644 --- a/packages/assumevalid/tests/data/batch_200.json +++ b/packages/assumevalid/tests/data/batch_200.json @@ -2414,9 +2414,9 @@ "block_mmr": { "roots": [ { - "hi": 127393669198796545867873666634899495693, - "lo": 18179848941975845720653830328566420889 - }, + "lo": 18179848941975845720653830328566420889, + "hi": 127393669198796545867873666634899495693 + }, { "hi": 0, "lo": 0 diff --git a/packages/assumevalid/tests/data/batch_400.json b/packages/assumevalid/tests/data/batch_400.json index 68319127..14ed0c79 100644 --- a/packages/assumevalid/tests/data/batch_400.json +++ b/packages/assumevalid/tests/data/batch_400.json @@ -4814,8 +4814,8 @@ "block_mmr": { "roots": [ { - "hi": 127393669198796545867873666634899495693, - "lo": 18179848941975845720653830328566420889 + "lo": 18179848941975845720653830328566420889, + "hi": 127393669198796545867873666634899495693 }, { "hi": 0, diff --git a/packages/assumevalid/tests/data/blocks_0_1.json b/packages/assumevalid/tests/data/blocks_0_1.json index 67d62c0e..7a5cea3b 100644 --- a/packages/assumevalid/tests/data/blocks_0_1.json +++ b/packages/assumevalid/tests/data/blocks_0_1.json @@ -26,8 +26,8 @@ "block_mmr": { "roots": [ { - "hi": 127393669198796545867873666634899495693, - "lo": 18179848941975845720653830328566420889 + "lo": 18179848941975845720653830328566420889, + "hi": 127393669198796545867873666634899495693 }, { "hi": 0, diff --git a/packages/assumevalid/tests/data/blocks_1_2.json b/packages/assumevalid/tests/data/blocks_1_2.json index cb1ad663..f5b9f112 100644 --- a/packages/assumevalid/tests/data/blocks_1_2.json +++ b/packages/assumevalid/tests/data/blocks_1_2.json @@ -31,8 +31,8 @@ "lo": 0 }, { - "hi": 214426372237413499259359749835690602779, - "lo": 60633371617111020730067693523639793590 + "lo": 60633371617111020730067693523639793590, + "hi": 214426372237413499259359749835690602779 }, { "hi": 0,