Skip to content

Commit

Permalink
Add Assert,Disprove,Payout transactions (#13)
Browse files Browse the repository at this point in the history
Add core types of transactions including Assert, Disprove and Payout
spending. Add integration tests. Change u29mul to 32-bit multiplication.
  • Loading branch information
Velnbur authored Oct 21, 2024
1 parent 1da4239 commit 768aa3d
Show file tree
Hide file tree
Showing 12 changed files with 852 additions and 31 deletions.
2 changes: 1 addition & 1 deletion bitcoin-testscripts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod int_mul_karatsuba;
pub mod int_mul_windowed;
pub mod sha256;
pub mod square_fibonacci;
pub mod u29mul;
pub mod u32mul;

#[cfg(test)]
pub mod tests;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
//! for performing the multiplication of two large integers
//! (exceeding standard Bitcoin 31-bit integers)
use bitcoin_splitter::split::script::{IOPair, SplitableScript};
use bitcoin_splitter::split::{
core::SplitType,
script::{IOPair, SplitResult, SplitableScript},
};
use bitcoin_utils::treepp::*;
use bitcoin_window_mul::{
bigint::implementation::NonNativeBigIntImpl,
Expand All @@ -13,36 +16,36 @@ use num_bigint::{BigUint, RandomBits};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;

pub type U29 = NonNativeBigIntImpl<29, 29>;
pub type U58 = NonNativeBigIntImpl<58, 29>;
pub type U32 = NonNativeBigIntImpl<32, 29>;
pub type U64 = NonNativeBigIntImpl<64, 29>;

/// Script that performs the addition of two 255-bit numbers
pub struct U29MulScript;
pub struct U32MulScript;

/// Input size is double the number of limbs of U254 since we are multiplying two numbers
const INPUT_SIZE: usize = 2 * U29::N_LIMBS;
const INPUT_SIZE: usize = 2 * U32::N_LIMBS;
/// Output size is the number of limbs of U508
const OUTPUT_SIZE: usize = U58::N_LIMBS;
const OUTPUT_SIZE: usize = U64::N_LIMBS;

impl SplitableScript<{ INPUT_SIZE }, { OUTPUT_SIZE }> for U29MulScript {
impl SplitableScript<{ INPUT_SIZE }, { OUTPUT_SIZE }> for U32MulScript {
fn script() -> Script {
U29::OP_WIDENINGMUL::<U58>()
U32::OP_WIDENINGMUL::<U64>()
}

fn generate_valid_io_pair() -> IOPair<{ INPUT_SIZE }, { OUTPUT_SIZE }> {
let mut prng = ChaCha20Rng::seed_from_u64(0);

// Generate two random 254-bit numbers and calculate their sum
let num_1: BigUint = prng.sample(RandomBits::new(29));
let num_1: BigUint = prng.sample(RandomBits::new(32));
let num_2: BigUint = prng.sample(RandomBits::new(29));
let product: BigUint = num_1.clone() * num_2.clone();

IOPair {
input: script! {
{ U29::OP_PUSH_U32LESLICE(&num_1.to_u32_digits()) }
{ U29::OP_PUSH_U32LESLICE(&num_2.to_u32_digits()) }
{ U32::OP_PUSH_U32LESLICE(&num_1.to_u32_digits()) }
{ U32::OP_PUSH_U32LESLICE(&num_2.to_u32_digits()) }
},
output: U58::OP_PUSH_U32LESLICE(&product.to_u32_digits()),
output: U64::OP_PUSH_U32LESLICE(&product.to_u32_digits()),
}
}

Expand All @@ -60,12 +63,16 @@ impl SplitableScript<{ INPUT_SIZE }, { OUTPUT_SIZE }> for U29MulScript {

IOPair {
input: script! {
{ U29::OP_PUSH_U32LESLICE(&num_1.to_u32_digits()) }
{ U29::OP_PUSH_U32LESLICE(&num_2.to_u32_digits()) }
{ U32::OP_PUSH_U32LESLICE(&num_1.to_u32_digits()) }
{ U32::OP_PUSH_U32LESLICE(&num_2.to_u32_digits()) }
},
output: U58::OP_PUSH_U32LESLICE(&product.to_u32_digits()),
output: U64::OP_PUSH_U32LESLICE(&product.to_u32_digits()),
}
}

fn default_split(input: Script, split_type: SplitType) -> SplitResult {
Self::split(input, split_type, 300)
}
}

#[cfg(test)]
Expand All @@ -77,20 +84,20 @@ mod tests {

#[test]
fn test_verify() {
assert!(U29MulScript::verify_random());
assert!(U32MulScript::verify_random());
}

#[test]
fn test_naive_split_correctness() {
// Generating a random valid input for the script and the script itself
let IOPair { input, output } = U29MulScript::generate_valid_io_pair();
let IOPair { input, output } = U32MulScript::generate_valid_io_pair();
assert!(
U29MulScript::verify(input.clone(), output.clone()),
U32MulScript::verify(input.clone(), output.clone()),
"input/output is not correct"
);

// Splitting the script into shards
let split_result = U29MulScript::default_split(input.clone(), SplitType::ByInstructions);
let split_result = U32MulScript::default_split(input.clone(), SplitType::ByInstructions);

// Now, we are going to concatenate all the shards and verify that the script is also correct
let verification_script = script! {
Expand All @@ -101,7 +108,7 @@ mod tests {
{ output }

// Now, we need to verify that the output is correct.
for i in (0..U29MulScript::OUTPUT_SIZE).rev() {
for i in (0..U32MulScript::OUTPUT_SIZE).rev() {
// { <a_1> <a_2> ... <a_n> <b_1> <b_2> ... <b_n> } <- we need to push element <a_n> to the top of the stack
{ i+1 } OP_ROLL
OP_EQUALVERIFY
Expand All @@ -117,10 +124,10 @@ mod tests {
#[test]
fn test_naive_split() {
// First, we generate the pair of input and output scripts
let IOPair { input, output } = U29MulScript::generate_valid_io_pair();
let IOPair { input, output } = U32MulScript::generate_valid_io_pair();

// Splitting the script into shards
let split_result = U29MulScript::default_split(input, SplitType::ByInstructions);
let split_result = U32MulScript::default_split(input, SplitType::ByInstructions);

for shard in split_result.shards.iter() {
println!("Shard: {:?}", shard.len());
Expand All @@ -139,7 +146,7 @@ mod tests {
let verification_script = script! {
{ stack_to_script(&last_state.stack) }
{ output }
{ U58::OP_EQUAL(0, 1) }
{ U64::OP_EQUAL(0, 1) }
};

let result = execute_script(verification_script);
Expand All @@ -163,10 +170,10 @@ mod tests {
#[ignore = "too-large computation, run separately"]
fn test_fuzzy_split() {
// First, we generate the pair of input and output scripts
let IOPair { input, output } = U29MulScript::generate_valid_io_pair();
let IOPair { input, output } = U32MulScript::generate_valid_io_pair();

// Splitting the script into shards
let split_result = U29MulScript::fuzzy_split(input, SplitType::ByInstructions);
let split_result = U32MulScript::fuzzy_split(input, SplitType::ByInstructions);

for shard in split_result.shards.iter() {
println!("Shard: {:?}", shard.len());
Expand All @@ -185,7 +192,7 @@ mod tests {
let verification_script = script! {
{ stack_to_script(&last_state.stack) }
{ output }
{ U58::OP_EQUAL(0, 1) }
{ U64::OP_EQUAL(0, 1) }
};

let result = execute_script(verification_script);
Expand Down
2 changes: 2 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ rand = { version = "0.8.5", default-features = false, features = ["min_co
rand_chacha = "0.3.1"
ark-std = "0.4.0"
konst = "0.3.9"
once_cell = "1.19.0"
eyre = "0.6.12"

Loading

0 comments on commit 768aa3d

Please sign in to comment.