diff --git a/Cargo.lock b/Cargo.lock index e3ed656..fc8036e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,9 +331,9 @@ dependencies = [ [[package]] name = "const_panic" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7782af8f90fe69a4bb41e460abe1727d493403d8b2cc43201a3a3e906b24379f" +checksum = "013b6c2c3a14d678f38cd23994b02da3a1a1b6a5d1eedddfe63a5a5f11b13a81" [[package]] name = "crypto-common" diff --git a/src/bigint/cmpeq/mod.rs b/src/bigint/cmpeq/mod.rs index 7d69c75..4cc8410 100644 --- a/src/bigint/cmpeq/mod.rs +++ b/src/bigint/cmpeq/mod.rs @@ -168,6 +168,12 @@ where { T::OP_EXTEND::() } + fn OP_COMPRESS() -> Script + where + Q: NonNativeLimbInteger, + { + T::OP_COMPRESS::() + } } #[allow(non_snake_case)] diff --git a/src/bigint/implementation.rs b/src/bigint/implementation.rs index f28f903..57530e9 100644 --- a/src/bigint/implementation.rs +++ b/src/bigint/implementation.rs @@ -167,4 +167,10 @@ impl NonNativeInteger { Self::handle_OP_EXTEND::() } + fn OP_COMPRESS() -> Script + where + T: NonNativeLimbInteger, + { + Self::handle_OP_COMPRESS::() + } } diff --git a/src/bigint/naf/implementation.rs b/src/bigint/naf/implementation.rs index a7ab8e4..9eab0ba 100644 --- a/src/bigint/naf/implementation.rs +++ b/src/bigint/naf/implementation.rs @@ -85,7 +85,7 @@ pub fn binary_to_be_naf(num_bits: usize) -> Script { OP_2DUP OP_BITAND OP_IF // In case they are both 1, we need to change them to -1 and 0, while the carry must be one OP_3DROP - 1 -1 0 + 1 (-1) 0 OP_ENDIF OP_ROT diff --git a/src/bigint/stack/implementation.rs b/src/bigint/stack/implementation.rs index 68c2ce0..8274bcc 100644 --- a/src/bigint/stack/implementation.rs +++ b/src/bigint/stack/implementation.rs @@ -221,6 +221,7 @@ impl NonNativeBigIntImpl NonNativeBigIntImpl() -> Script + where + T: NonNativeLimbInteger, + { + assert!( + T::N_BITS < Self::N_BITS, + "The integer to be compressed to must have less bits than the current integer" + ); + assert!( + T::LIMB_SIZE == Self::LIMB_SIZE, + "The integers to be compressed to must have the same number of bits in limb" + ); + + // Calculating the number of limbs to remove + let n_limbs_self = (Self::N_BITS + Self::LIMB_SIZE - 1) / Self::LIMB_SIZE; + let n_limbs_compress = (T::N_BITS + T::LIMB_SIZE - 1) / T::LIMB_SIZE; + let n_limbs_to_remove = n_limbs_self - n_limbs_compress; + + if n_limbs_to_remove == 0 { + return script! {}; + } + + script! { + for i in 0..n_limbs_to_remove { + { Self::N_LIMBS - i - 1 } OP_ROLL OP_DROP + } + } + } } impl NonNativeBigIntImpl { diff --git a/src/bigint/stack/test.rs b/src/bigint/stack/test.rs index 3bd5e01..ab0485d 100644 --- a/src/bigint/stack/test.rs +++ b/src/bigint/stack/test.rs @@ -488,3 +488,26 @@ fn test_254_bit_widening() { assert!(exec_result.success); } } + +#[test] +/// Tests the extension of 254-bit number to 508-bit number and then +/// compressing it back to 254-bit number. +fn test_254_bit_compress() { + print_script_size("254-bit compression", U508::OP_COMPRESS::()); + + let mut prng = ChaCha20Rng::seed_from_u64(0); + for _ in 0..100 { + let a: BigUint = prng.sample(RandomBits::new(254)); + let script = script! { + { U254::OP_PUSH_U32LESLICE(&a.to_u32_digits()) } + { U254::OP_EXTEND::() } + { U508::OP_COMPRESS::() } + { U254::OP_PUSH_U32LESLICE(&a.to_u32_digits()) } + { U254::OP_EQUALVERIFY(1, 0) } + OP_TRUE + }; + + let exec_result = execute_script(script); + assert!(exec_result.success); + } +} diff --git a/src/bigint/window/mod.rs b/src/bigint/window/mod.rs index 22af380..5553d04 100644 --- a/src/bigint/window/mod.rs +++ b/src/bigint/window/mod.rs @@ -204,6 +204,12 @@ where { T::OP_EXTEND::() } + fn OP_COMPRESS() -> Script + where + Q: NonNativeLimbInteger, + { + T::OP_COMPRESS::() + } } #[allow(non_snake_case)] diff --git a/src/bigint/window/precompute.rs b/src/bigint/window/precompute.rs index d14ecd1..abaeec8 100644 --- a/src/bigint/window/precompute.rs +++ b/src/bigint/window/precompute.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use crate::traits::integer::NonNativeLimbInteger; use crate::treepp::*; -pub(in super::super) struct WindowedPrecomputeTable +pub struct WindowedPrecomputeTable where T: NonNativeLimbInteger, { diff --git a/src/traits/integer.rs b/src/traits/integer.rs index 41f338c..3b2c624 100644 --- a/src/traits/integer.rs +++ b/src/traits/integer.rs @@ -46,6 +46,11 @@ pub trait NonNativeInteger: Comparable + Arithmeticable + Bitable { where T: NonNativeLimbInteger; + /// Compresses the given [`NonNativeInteger`] back to the specified type. + fn OP_COMPRESS() -> Script + where + T: NonNativeLimbInteger; + // --- Stack operations --- /// Zips two [`NonNativeInteger`]s at specified depths.