From 6aa388b4a386f9d661ec46241a99305d048d52fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Wed, 7 Aug 2024 23:39:55 +0200 Subject: [PATCH 01/23] merkle tree draft --- src/lib.cairo | 1 + src/merkle_tree.cairo | 17 +++++++++++++++++ src/utils.cairo | 26 ++++++++++++++++++++++++-- src/validation.cairo | 16 +++------------- 4 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 src/merkle_tree.cairo diff --git a/src/lib.cairo b/src/lib.cairo index 7778f44f..962ed1da 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -2,3 +2,4 @@ mod utils; pub mod validation; mod state; mod main; +mod merkle_tree; diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo new file mode 100644 index 00000000..93570768 --- /dev/null +++ b/src/merkle_tree.cairo @@ -0,0 +1,17 @@ +use super::utils::double_sha256; + +pub fn merkle_root(ref txids: Array) -> u256 { + if txids.len() % 2 == 1 { + txids.append(*txids.at(txids.len() - 1)); + } + + let mut next_txids = ArrayTrait::new(); + let mut i = 0; + let len = txids.len(); + while i < len { + next_txids.append(double_sha256(*txids.at(i), *txids.at(i + 1))); + i += 2; + }; + + merkle_root(ref next_txids) +} diff --git a/src/utils.cairo b/src/utils.cairo index 0e542db3..fc4010b0 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,5 +1,4 @@ -use core::traits::Into; -use core::traits::TryInto; +use core::sha256::{compute_sha256_byte_array, compute_sha256_u32_array}; // Bitwise shift left for u256 pub fn shl(value: u256, shift: u32) -> u256 { @@ -34,3 +33,26 @@ pub fn fast_pow(base: u256, exp: u32) -> u256 { base = base * base; } } + +const TWO_POW_32: u128 = 0x100000000; +const TWO_POW_64: u128 = 0x10000000000000000; +const TWO_POW_96: u128 = 0x1000000000000000000000000; + +pub fn double_sha256(a: u256, b: u256) -> u256 { + let mut ba = Default::default(); + + ba.append_word(a.high.into(), 16); + ba.append_word(a.low.into(), 16); + ba.append_word(b.high.into(), 16); + ba.append_word(b.low.into(), 16); + + let mut input1 = Default::default(); + input1.append_span(compute_sha256_byte_array(@ba).span()); + + let [x0, x1, x2, x3, x4, x5, x6, x7] = compute_sha256_u32_array(input1, 0, 0); + + u256 { + high: x0.into() * TWO_POW_96 + x1.into() * TWO_POW_64 + x2.into() * TWO_POW_32 + x3.into(), + low: x4.into() * TWO_POW_96 + x5.into() * TWO_POW_64 + x6.into() * TWO_POW_32 + x7.into(), + } +} diff --git a/src/validation.cairo b/src/validation.cairo index ce17c749..177eae3b 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -1,4 +1,5 @@ -use super::utils::{shl, shr}; +use super::merkle_tree::merkle_root; +use super::utils::{shl, shr, double_sha256}; use super::state::{Block, ChainState, Transaction, UtreexoState}; const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; @@ -101,12 +102,6 @@ fn adjust_difficulty(self: @ChainState, block: @Block) -> (u32, u32) { (*self.current_target, *self.epoch_start_time) } -fn validate_merkle_root(self: @ChainState, block: @Block) -> Result<(), ByteArray> { - // TODO: implement - Result::Ok(()) -} - - pub fn target_to_bits(target: u256) -> Result { if target == 0 { return Result::Err('Target is zero'); @@ -160,12 +155,7 @@ fn fee_and_merkle_root(self: @ChainState, block: @Block) -> Result<(u256, u256), total_fee += tx.fee(); }; - Result::Ok((total_fee, merkle_root(txids))) -} - -fn merkle_root(txids: Array) -> u256 { - // TODO: implement - 0 + Result::Ok((total_fee, merkle_root(ref txids))) } fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { From 285467077456de464b0dcfe4c8ed421816ed10d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Wed, 7 Aug 2024 23:48:34 +0200 Subject: [PATCH 02/23] draft of merkle tree --- src/merkle_tree.cairo | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index 93570768..8495b3b9 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -1,13 +1,18 @@ use super::utils::double_sha256; pub fn merkle_root(ref txids: Array) -> u256 { - if txids.len() % 2 == 1 { - txids.append(*txids.at(txids.len() - 1)); + let len = txids.len(); + if len % 2 == 1 { + txids.append(*txids.at(len - 1)); + } else { + // CVE-2012-2459 bug fix + assert!( + txids.at(len - 1) != txids.at(len - 2), "unexpected node duplication in merkle tree" + ); } let mut next_txids = ArrayTrait::new(); let mut i = 0; - let len = txids.len(); while i < len { next_txids.append(double_sha256(*txids.at(i), *txids.at(i + 1))); i += 2; From 2cc25eec07ac9a8ae18256ac6cbdf53d353d4be0 Mon Sep 17 00:00:00 2001 From: mubarak23 Date: Thu, 8 Aug 2024 11:37:49 +0100 Subject: [PATCH 03/23] compute merkle root implementation --- src/lib.cairo | 1 + src/merkle_tree.cairo | 88 +++++++++++++++++++++++++++++++++++++++++++ src/utils.cairo | 26 ++++++++++++- src/validation.cairo | 49 ++---------------------- 4 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 src/merkle_tree.cairo diff --git a/src/lib.cairo b/src/lib.cairo index ce41db81..201712a7 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -3,3 +3,4 @@ pub mod validation; mod state; mod main; +mod merkle_tree; diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo new file mode 100644 index 00000000..e04d3d9d --- /dev/null +++ b/src/merkle_tree.cairo @@ -0,0 +1,88 @@ +use super::utils::double_sha256; + +pub fn merkle_root(ref txids: Array) -> u256 { + let len = txids.len(); + if len % 2 == 1 { + txids.append(*txids.at(len - 1)); + } else { + // CVE-2012-2459 bug fix + assert!( + txids.at(len - 1) != txids.at(len - 2), "unexpected node duplication in merkle tree" + ); + } + + let mut next_txids = ArrayTrait::new(); + let mut i = 0; + while i < len { + next_txids.append(double_sha256(*txids.at(i), *txids.at(i + 1))); + i += 2; + }; + + merkle_root(ref next_txids) +} + +#[cfg(test)] +mod tests { + use super::{merkle_root}; + use starknet::core::types::FieldElement; + + #[test] + fn test_merkle_root() { + let txids = vec![ + FieldElement::from_hex_be( + "50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38" + ) + .unwrap(), + FieldElement::from_hex_be( + "96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6" + ) + .unwrap(), + FieldElement::from_hex_be( + "65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4" + ) + .unwrap(), + FieldElement::from_hex_be( + "1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815" + ) + .unwrap(), + FieldElement::from_hex_be( + "ec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712" + ) + .unwrap(), + FieldElement::from_hex_be( + "5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50" + ) + .unwrap(), + FieldElement::from_hex_be( + "0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615" + ) + .unwrap(), + FieldElement::from_hex_be( + "d94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711" + ) + .unwrap(), + FieldElement::from_hex_be( + "c4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a" + ) + .unwrap(), + FieldElement::from_hex_be( + "d4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542" + ) + .unwrap(), + FieldElement::from_hex_be( + "b5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351" + ) + .unwrap(), + FieldElement::from_hex_be( + "f9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f" + ) + .unwrap(), + ]; + let expected_merkle_root = FieldElement::from_hex_be( + "17663ab10c2e13d92dccb4514b05b18815f5f38af1f21e06931c71d62b36d8af" + ) + .unwrap(); + assert_eq!(merkle_root(txids), expected_merkle_root); + } +} + diff --git a/src/utils.cairo b/src/utils.cairo index 0e542db3..fc4010b0 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,5 +1,4 @@ -use core::traits::Into; -use core::traits::TryInto; +use core::sha256::{compute_sha256_byte_array, compute_sha256_u32_array}; // Bitwise shift left for u256 pub fn shl(value: u256, shift: u32) -> u256 { @@ -34,3 +33,26 @@ pub fn fast_pow(base: u256, exp: u32) -> u256 { base = base * base; } } + +const TWO_POW_32: u128 = 0x100000000; +const TWO_POW_64: u128 = 0x10000000000000000; +const TWO_POW_96: u128 = 0x1000000000000000000000000; + +pub fn double_sha256(a: u256, b: u256) -> u256 { + let mut ba = Default::default(); + + ba.append_word(a.high.into(), 16); + ba.append_word(a.low.into(), 16); + ba.append_word(b.high.into(), 16); + ba.append_word(b.low.into(), 16); + + let mut input1 = Default::default(); + input1.append_span(compute_sha256_byte_array(@ba).span()); + + let [x0, x1, x2, x3, x4, x5, x6, x7] = compute_sha256_u32_array(input1, 0, 0); + + u256 { + high: x0.into() * TWO_POW_96 + x1.into() * TWO_POW_64 + x2.into() * TWO_POW_32 + x3.into(), + low: x4.into() * TWO_POW_96 + x5.into() * TWO_POW_64 + x6.into() * TWO_POW_32 + x7.into(), + } +} diff --git a/src/validation.cairo b/src/validation.cairo index 3ce23b23..177eae3b 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -1,5 +1,6 @@ +use super::merkle_tree::merkle_root; +use super::utils::{shl, shr, double_sha256}; use super::state::{Block, ChainState, Transaction, UtreexoState}; -use super::utils::{shl, shr}; const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; @@ -101,45 +102,6 @@ fn adjust_difficulty(self: @ChainState, block: @Block) -> (u32, u32) { (*self.current_target, *self.epoch_start_time) } -fn validate_merkle_root(self: @ChainState, block: @Block) -> Result<(), ByteArray> { - // TODO: implement - Result::Ok(()) -} - -// Helper functions -pub fn bits_to_target(bits: u32) -> Result { - // Extract exponent and mantissa - let exponent: u32 = (bits / 0x1000000); - let mantissa: u32 = bits & 0x00FFFFFF; - - // Check if mantissa is valid (should be less than 0x1000000) - if mantissa > 0x7FFFFF && exponent != 0 { - return Result::Err('Invalid mantissa'); - } - - // Calculate the full target value - let mut target: u256 = mantissa.into(); - - if exponent == 0 { - // Special case: exponent 0 means we use the mantissa as-is - return Result::Ok(target); - } else if exponent <= 3 { - // For exponents 1, 2, and 3, divide by 256^(3 - exponent) i.e right shift - let shift = 8 * (3 - exponent); - target = shr(target, shift); - } else { - let shift = 8 * (exponent - 3); - target = shl(target, shift); - } - - // Ensure the target doesn't exceed the maximum allowed value - if target > MAX_TARGET { - return Result::Err('Target exceeds maximum'); - } - - Result::Ok(target) -} - pub fn target_to_bits(target: u256) -> Result { if target == 0 { return Result::Err('Target is zero'); @@ -193,12 +155,7 @@ fn fee_and_merkle_root(self: @ChainState, block: @Block) -> Result<(u256, u256), total_fee += tx.fee(); }; - Result::Ok((total_fee, merkle_root(txids))) -} - -fn merkle_root(txids: Array) -> u256 { - // TODO: implement - 0 + Result::Ok((total_fee, merkle_root(ref txids))) } fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { From f9fc168c37e26dfab2165cccf2907650167fddd5 Mon Sep 17 00:00:00 2001 From: mubarak23 Date: Thu, 8 Aug 2024 14:37:27 +0100 Subject: [PATCH 04/23] fix changes --- src/merkle_tree.cairo | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index e04d3d9d..66836d00 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -28,7 +28,8 @@ mod tests { #[test] fn test_merkle_root() { - let txids = vec![ + + let txids = array![ FieldElement::from_hex_be( "50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38" ) @@ -79,7 +80,7 @@ mod tests { .unwrap(), ]; let expected_merkle_root = FieldElement::from_hex_be( - "17663ab10c2e13d92dccb4514b05b18815f5f38af1f21e06931c71d62b36d8af" + "0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256" ) .unwrap(); assert_eq!(merkle_root(txids), expected_merkle_root); From 651c3148ea6a36da432d7cdcb25f877bf4df1e0a Mon Sep 17 00:00:00 2001 From: mubarak23 Date: Thu, 8 Aug 2024 18:55:22 +0100 Subject: [PATCH 05/23] use u256 Array as transaction ids data in test --- src/merkle_tree.cairo | 70 ++++++++++--------------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index 533fb8ca..830d40e3 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -30,60 +30,22 @@ mod tests { #[test] fn test_merkle_root() { - let txids = array![ - FieldElement::from_hex_be( - "50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38" - ) - .unwrap(), - FieldElement::from_hex_be( - "96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6" - ) - .unwrap(), - FieldElement::from_hex_be( - "65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4" - ) - .unwrap(), - FieldElement::from_hex_be( - "1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815" - ) - .unwrap(), - FieldElement::from_hex_be( - "ec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712" - ) - .unwrap(), - FieldElement::from_hex_be( - "5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50" - ) - .unwrap(), - FieldElement::from_hex_be( - "0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615" - ) - .unwrap(), - FieldElement::from_hex_be( - "d94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711" - ) - .unwrap(), - FieldElement::from_hex_be( - "c4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a" - ) - .unwrap(), - FieldElement::from_hex_be( - "d4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542" - ) - .unwrap(), - FieldElement::from_hex_be( - "b5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351" - ) - .unwrap(), - FieldElement::from_hex_be( - "f9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f" - ) - .unwrap(), - ]; - let expected_merkle_root = FieldElement::from_hex_be( - "0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256" - ) - .unwrap(); + let txids = array![0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, + 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, + 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, + 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, + 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, + 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, + 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_256, + 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, + 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, + 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, + 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, + 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 + ] + + let expected_merkle_root = "0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256" + assert_eq!(merkle_root(txids), expected_merkle_root); } } From 18f05dbc337ddefda149460f342537e68378d360 Mon Sep 17 00:00:00 2001 From: mubarak23 Date: Thu, 8 Aug 2024 19:03:19 +0100 Subject: [PATCH 06/23] fix end of line --- src/merkle_tree.cairo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index 830d40e3..ca22fc78 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -42,9 +42,9 @@ mod tests { 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 - ] + ]; - let expected_merkle_root = "0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256" + let expected_merkle_root = "0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256"; assert_eq!(merkle_root(txids), expected_merkle_root); } From db66e5d5b3e80b7748c5991b64d21001835b25c9 Mon Sep 17 00:00:00 2001 From: mubarak23 Date: Thu, 8 Aug 2024 21:43:43 +0100 Subject: [PATCH 07/23] use ref in txids --- src/merkle_tree.cairo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index c922e916..a770ebdd 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -24,7 +24,7 @@ pub fn merkle_root(ref txids: Array) -> u256 { #[cfg(test)] mod tests { use super::{merkle_root}; - use starknet::core::types::FieldElement; + #[test] fn test_merkle_root() { @@ -45,6 +45,6 @@ mod tests { let expected_merkle_root = 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256; - assert_eq!(merkle_root(txids), expected_merkle_root); + assert_eq!(merkle_root(ref txids), expected_merkle_root); } } From 8ecb8cc3db1bb6f32adb198ed366feb5f4b7fdec Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 12:29:22 +0200 Subject: [PATCH 08/23] make shl/shr and fastpow generics --- src/utils.cairo | 94 ++++++++++++++++++++++++++++++++++++-------- src/validation.cairo | 12 +++--- 2 files changed, 83 insertions(+), 23 deletions(-) diff --git a/src/utils.cairo b/src/utils.cairo index 0e542db3..a2de7942 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,34 +1,94 @@ -use core::traits::Into; -use core::traits::TryInto; +use core::num::traits::{Zero, One, BitSize}; +use core::panic_with_felt252; +use core::starknet::secp256_trait::Secp256PointTrait; -// Bitwise shift left for u256 -pub fn shl(value: u256, shift: u32) -> u256 { - value * fast_pow(2.into(), shift.into()) + +pub trait Bitshift { + fn shl(self: T, shift: U) -> T; + fn shr(self: T, shift: U) -> T; } -// Bitwise shift right for u256 -pub fn shr(value: u256, shift: u32) -> u256 { - value / fast_pow(2.into(), shift.into()) +pub impl BitshiftImpl< + T, + U, + +Zero, + +Zero, + +One, + +One, + +Add, + +Add, + +Sub, + +Sub, + +Div, + +Mul, + +Rem, + +Div, + +Copy, + +Copy, + +Drop, + +Drop, + +PartialOrd, + +PartialOrd, + +PartialEq, + +BitSize, + +TryInto, + +Into +> of Bitshift { + fn shl(self: T, shift: U) -> T { + if shift > BitSize::::bits().into() - One::one() { + panic_with_felt252('mul Overflow'); + } + let two = One::one() + One::one(); + self * fast_pow(two, shift) + } + + fn shr(self: T, shift: U) -> T { + if shift > BitSize::::bits().try_into().unwrap() - One::one() { + panic_with_felt252('mul Overflow'); + } + let two = One::one() + One::one(); + self / fast_pow(two, shift) + } } // Fast exponentiation using the square-and-multiply algorithm // Reference: // https://github.com/keep-starknet-strange/alexandria/blob/bcdca70afdf59c9976148e95cebad5cf63d75a7f/packages/math/src/fast_power.cairo#L12 -pub fn fast_pow(base: u256, exp: u32) -> u256 { - if exp == 0 { - return 1_u256; +pub fn fast_pow< + T, + U, + +Copy, + +Copy, + +Drop, + +Drop, + +Zero, + +One, + +Zero, + +One, + +PartialEq, + +Add, + +Mul, + +Rem, + +Div +>( + base: T, exp: U +) -> T { + if exp == Zero::zero() { + return Zero::zero(); } - let mut res: u256 = 1_u256; - let mut base: u256 = base; - let mut exp: u32 = exp; + let mut res: T = One::one(); + let mut base: T = base; + let mut exp: U = exp; + + let two: U = One::one() + One::one(); loop { - if exp % 2 == 1 { + if exp % two == One::one() { res = res * base; } - exp = exp / 2; - if exp == 0 { + exp = exp / two; + if exp == Zero::zero() { break res; } base = base * base; diff --git a/src/validation.cairo b/src/validation.cairo index 3ce23b23..952d0790 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -1,5 +1,5 @@ use super::state::{Block, ChainState, Transaction, UtreexoState}; -use super::utils::{shl, shr}; +use super::utils::Bitshift; const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; @@ -126,10 +126,10 @@ pub fn bits_to_target(bits: u32) -> Result { } else if exponent <= 3 { // For exponents 1, 2, and 3, divide by 256^(3 - exponent) i.e right shift let shift = 8 * (3 - exponent); - target = shr(target, shift); + target = Bitshift::shr(target, shift); } else { let shift = 8 * (exponent - 3); - target = shl(target, shift); + target = Bitshift::shl(target, shift); } // Ensure the target doesn't exceed the maximum allowed value @@ -154,12 +154,12 @@ pub fn target_to_bits(target: u256) -> Result { let mut compact = target; // Count leading zero bytes by finding the first non-zero byte - while size > 1 && shr(compact, (size - 1) * 8) == 0 { + while size > 1 && Bitshift::shr(compact, (size - 1) * 8) == 0 { size -= 1; }; // Extract mantissa (most significant 3 bytes) - let mut mantissa: u32 = shr(compact, (size - 3) * 8).try_into().unwrap(); + let mut mantissa: u32 = Bitshift::shr(compact, (size - 3) * 8).try_into().unwrap(); // Normalize if mantissa > 0x7fffff { @@ -179,7 +179,7 @@ pub fn target_to_bits(target: u256) -> Result { let size_u256: u256 = size.into(); // Combine size and mantissa - let result: u32 = (shl(size_u256, 24) + mantissa.into()).try_into().unwrap(); + let result: u32 = (Bitshift::shl(size_u256, 24_u32) + mantissa.into()).try_into().unwrap(); Result::Ok(result) } From 25b1a26a68693202633a3fe1272b0c238a72a712 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 12:34:19 +0200 Subject: [PATCH 09/23] fix --- src/utils.cairo | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.cairo b/src/utils.cairo index a2de7942..f908f3c5 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -31,7 +31,6 @@ pub impl BitshiftImpl< +PartialOrd, +PartialEq, +BitSize, - +TryInto, +Into > of Bitshift { fn shl(self: T, shift: U) -> T { From d90002bcd0eeb1bf152557b42ac6619d0442aee3 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 12:38:21 +0200 Subject: [PATCH 10/23] merge main --- src/validation.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cairo b/src/validation.cairo index 1d40d1b9..b6ec19cc 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -219,7 +219,7 @@ fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { // Return BTC reward in SATS fn compute_block_reward(block_height: u32) -> u64 { - shr(5000000000, block_height / 210_000).try_into().unwrap() + Bitshift::shr(5000000000_u256, block_height / 210_000).try_into().unwrap() } #[cfg(test)] mod tests { From 0af861fd1c0134de156bddacaaf1d3c6d7783c5c Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 12:40:51 +0200 Subject: [PATCH 11/23] remove some imports --- src/validation.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cairo b/src/validation.cairo index b6ec19cc..37c003a4 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -225,7 +225,7 @@ fn compute_block_reward(block_height: u32) -> u64 { mod tests { use super::{ validate_target, validate_timestamp, validate_proof_of_work, compute_block_reward, - compute_total_work, compute_work_from_target, shr, shl, REWARD_INITIAL, POW_SATS_AMOUNT + compute_total_work, compute_work_from_target, REWARD_INITIAL, POW_SATS_AMOUNT }; use super::{Block, ChainState, UtreexoState}; use super::super::state::{Header, Transaction, TxIn, TxOut}; From 651b563880b459fc902a1cc463b9a1ec8fd3f025 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 12:51:43 +0200 Subject: [PATCH 12/23] solve last bug --- src/utils.cairo | 3 ++- src/validation.cairo | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils.cairo b/src/utils.cairo index f908f3c5..94e60785 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -45,6 +45,7 @@ pub impl BitshiftImpl< if shift > BitSize::::bits().try_into().unwrap() - One::one() { panic_with_felt252('mul Overflow'); } + let two = One::one() + One::one(); self / fast_pow(two, shift) } @@ -73,7 +74,7 @@ pub fn fast_pow< base: T, exp: U ) -> T { if exp == Zero::zero() { - return Zero::zero(); + return One::one(); } let mut res: T = One::one(); diff --git a/src/validation.cairo b/src/validation.cairo index 37c003a4..eb2f646d 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -219,7 +219,7 @@ fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { // Return BTC reward in SATS fn compute_block_reward(block_height: u32) -> u64 { - Bitshift::shr(5000000000_u256, block_height / 210_000).try_into().unwrap() + Bitshift::shr(5000000000_u256, (block_height / 210000_u32)).try_into().unwrap() } #[cfg(test)] mod tests { From 210658f05319d732d560fe9108e392b137a844e9 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 13:00:04 +0200 Subject: [PATCH 13/23] improve generic constraints order + overall nits --- src/utils.cairo | 19 ++++++++----------- src/validation.cairo | 14 ++++++++++---- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/utils.cairo b/src/utils.cairo index 94e60785..e4d69e8c 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -2,7 +2,6 @@ use core::num::traits::{Zero, One, BitSize}; use core::panic_with_felt252; use core::starknet::secp256_trait::Secp256PointTrait; - pub trait Bitshift { fn shl(self: T, shift: U) -> T; fn shr(self: T, shift: U) -> T; @@ -17,17 +16,15 @@ pub impl BitshiftImpl< +One, +Add, +Add, - +Sub, +Sub, +Div, +Mul, - +Rem, +Div, + +Rem, +Copy, +Copy, +Drop, +Drop, - +PartialOrd, +PartialOrd, +PartialEq, +BitSize, @@ -57,19 +54,19 @@ pub impl BitshiftImpl< pub fn fast_pow< T, U, - +Copy, - +Copy, - +Drop, - +Drop, +Zero, - +One, +Zero, + +One, +One, - +PartialEq, +Add, +Mul, +Rem, - +Div + +Div, + +Copy, + +Copy, + +Drop, + +Drop, + +PartialEq, >( base: T, exp: U ) -> T { diff --git a/src/validation.cairo b/src/validation.cairo index eb2f646d..315599db 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -221,14 +221,16 @@ fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { fn compute_block_reward(block_height: u32) -> u64 { Bitshift::shr(5000000000_u256, (block_height / 210000_u32)).try_into().unwrap() } + + #[cfg(test)] mod tests { + use raito::state::{Header, Transaction, TxIn, TxOut}; use super::{ - validate_target, validate_timestamp, validate_proof_of_work, compute_block_reward, - compute_total_work, compute_work_from_target, REWARD_INITIAL, POW_SATS_AMOUNT + Block, ChainState, UtreexoState, REWARD_INITIAL, POW_SATS_AMOUNT, compute_block_reward, + compute_work_from_target, compute_total_work, validate_proof_of_work, validate_target, + validate_timestamp }; - use super::{Block, ChainState, UtreexoState}; - use super::super::state::{Header, Transaction, TxIn, TxOut}; #[test] fn test_validate_target() { @@ -298,6 +300,7 @@ mod tests { let work = compute_work_from_target(target); assert(expected_work == work, 'Failed to compute target'); } + #[test] fn test_compute_work_from_target2() { let expected_work = 0x26d946e509ac00026d; @@ -305,6 +308,7 @@ mod tests { let work = compute_work_from_target(target); assert(expected_work == work, 'Failed to compute target'); } + #[test] fn test_compute_work_from_target3() { let expected_work = 0xe10005c64415f04ef3e387b97db388404db9fdfaab2b1918f6783471d; @@ -312,6 +316,7 @@ mod tests { let work = compute_work_from_target(target); assert(expected_work == work, 'Failed to compute target'); } + #[test] fn test_compute_work_from_target4() { let expected_work = 0x1c040c95a099201bcaf85db4e7f2e21e18707c8d55a887643b95afb2f; @@ -319,6 +324,7 @@ mod tests { let work = compute_work_from_target(target); assert(expected_work == work, 'Failed to compute target'); } + #[test] fn test_compute_work_from_target5() { let expected_work = 0x21809b468faa88dbe34f; From 89ea94897ef067d3984e277daa816f4ad7018f05 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 13:09:13 +0200 Subject: [PATCH 14/23] dont panic but return 0 if shift > Bitsize --- src/utils.cairo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.cairo b/src/utils.cairo index e4d69e8c..5f1ca6d6 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -32,7 +32,7 @@ pub impl BitshiftImpl< > of Bitshift { fn shl(self: T, shift: U) -> T { if shift > BitSize::::bits().into() - One::one() { - panic_with_felt252('mul Overflow'); + return Zero::zero(); } let two = One::one() + One::one(); self * fast_pow(two, shift) @@ -40,7 +40,7 @@ pub impl BitshiftImpl< fn shr(self: T, shift: U) -> T { if shift > BitSize::::bits().try_into().unwrap() - One::one() { - panic_with_felt252('mul Overflow'); + return Zero::zero(); } let two = One::one() + One::one(); From 00b51db742efb506d283bcbfaf065581f345a534 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 13:13:15 +0200 Subject: [PATCH 15/23] remove unused panicwithfelt import --- src/utils.cairo | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.cairo b/src/utils.cairo index 5f1ca6d6..d462e88c 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,5 +1,4 @@ use core::num::traits::{Zero, One, BitSize}; -use core::panic_with_felt252; use core::starknet::secp256_trait::Secp256PointTrait; pub trait Bitshift { From 13511174f0d78cd2779b2301e3e753c74e2a7631 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 13:31:20 +0200 Subject: [PATCH 16/23] remove trait --- src/utils.cairo | 57 +++++++++++++++++++++++++++++--------------- src/validation.cairo | 14 +++++------ 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/utils.cairo b/src/utils.cairo index d462e88c..f50e5c40 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,12 +1,38 @@ use core::num::traits::{Zero, One, BitSize}; use core::starknet::secp256_trait::Secp256PointTrait; -pub trait Bitshift { - fn shl(self: T, shift: U) -> T; - fn shr(self: T, shift: U) -> T; +pub fn shl< + T, + U, + +Zero, + +Zero, + +One, + +One, + +Add, + +Add, + +Sub, + +Mul, + +Div, + +Rem, + +Copy, + +Copy, + +Drop, + +Drop, + +PartialOrd, + +PartialEq, + +BitSize, + +Into +>( + self: T, shift: U, +) -> T { + if shift > BitSize::::bits().into() - One::one() { + return Zero::zero(); + } + let two = One::one() + One::one(); + self * fast_pow(two, shift) } -pub impl BitshiftImpl< +pub fn shr< T, U, +Zero, @@ -28,25 +54,18 @@ pub impl BitshiftImpl< +PartialEq, +BitSize, +Into -> of Bitshift { - fn shl(self: T, shift: U) -> T { - if shift > BitSize::::bits().into() - One::one() { - return Zero::zero(); - } - let two = One::one() + One::one(); - self * fast_pow(two, shift) +>( + self: T, shift: U +) -> T { + if shift > BitSize::::bits().try_into().unwrap() - One::one() { + return Zero::zero(); } - fn shr(self: T, shift: U) -> T { - if shift > BitSize::::bits().try_into().unwrap() - One::one() { - return Zero::zero(); - } - - let two = One::one() + One::one(); - self / fast_pow(two, shift) - } + let two = One::one() + One::one(); + self / fast_pow(two, shift) } + // Fast exponentiation using the square-and-multiply algorithm // Reference: // https://github.com/keep-starknet-strange/alexandria/blob/bcdca70afdf59c9976148e95cebad5cf63d75a7f/packages/math/src/fast_power.cairo#L12 diff --git a/src/validation.cairo b/src/validation.cairo index 315599db..0765b1b5 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -1,5 +1,5 @@ use super::state::{Block, ChainState, Transaction, UtreexoState}; -use super::utils::Bitshift; +use super::utils::{shr, shl}; const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; pub const REWARD_INITIAL: u256 = 50; // 50 BTC in satoshis => 5000000000 SATS @@ -137,10 +137,10 @@ pub fn bits_to_target(bits: u32) -> Result { } else if exponent <= 3 { // For exponents 1, 2, and 3, divide by 256^(3 - exponent) i.e right shift let shift = 8 * (3 - exponent); - target = Bitshift::shr(target, shift); + target = shr(target, shift); } else { let shift = 8 * (exponent - 3); - target = Bitshift::shl(target, shift); + target = shl(target, shift); } // Ensure the target doesn't exceed the maximum allowed value @@ -165,12 +165,12 @@ pub fn target_to_bits(target: u256) -> Result { let mut compact = target; // Count leading zero bytes by finding the first non-zero byte - while size > 1 && Bitshift::shr(compact, (size - 1) * 8) == 0 { + while size > 1 && shr(compact, (size - 1) * 8) == 0 { size -= 1; }; // Extract mantissa (most significant 3 bytes) - let mut mantissa: u32 = Bitshift::shr(compact, (size - 3) * 8).try_into().unwrap(); + let mut mantissa: u32 = shr(compact, (size - 3) * 8).try_into().unwrap(); // Normalize if mantissa > 0x7fffff { @@ -190,7 +190,7 @@ pub fn target_to_bits(target: u256) -> Result { let size_u256: u256 = size.into(); // Combine size and mantissa - let result: u32 = (Bitshift::shl(size_u256, 24_u32) + mantissa.into()).try_into().unwrap(); + let result: u32 = (shl(size_u256, 24_u32) + mantissa.into()).try_into().unwrap(); Result::Ok(result) } @@ -219,7 +219,7 @@ fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> { // Return BTC reward in SATS fn compute_block_reward(block_height: u32) -> u64 { - Bitshift::shr(5000000000_u256, (block_height / 210000_u32)).try_into().unwrap() + shr(5000000000_u256, (block_height / 210000_u32)).try_into().unwrap() } From 8197295693834593f3d5152dca4755bd0f2542a8 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Fri, 9 Aug 2024 13:32:21 +0200 Subject: [PATCH 17/23] keep alphabetic order for imports --- src/validation.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cairo b/src/validation.cairo index 0765b1b5..19f3bf7d 100644 --- a/src/validation.cairo +++ b/src/validation.cairo @@ -1,5 +1,5 @@ use super::state::{Block, ChainState, Transaction, UtreexoState}; -use super::utils::{shr, shl}; +use super::utils::{shl, shr}; const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; pub const REWARD_INITIAL: u256 = 50; // 50 BTC in satoshis => 5000000000 SATS From 178bc9e600b9c2ad3004cd806a975a1da60545a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski=20=40=20StarkWare?= Date: Fri, 9 Aug 2024 14:03:55 +0200 Subject: [PATCH 18/23] fmt --- src/merkle_tree.cairo | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index a770ebdd..d1020477 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -29,18 +29,18 @@ mod tests { #[test] fn test_merkle_root() { let txids = array![ - 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, - 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, - 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, - 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, - 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, - 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, - 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_u256, - 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, - 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, - 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, - 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, - 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 + 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, + 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, + 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, + 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, + 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, + 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, + 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_u256, + 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, + 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, + 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, + 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, + 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 ]; let expected_merkle_root = 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256; From 1d75d64d97c7b5b9aefa315f4a02d8f2ead22912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski=20=40=20StarkWare?= Date: Fri, 9 Aug 2024 14:06:52 +0200 Subject: [PATCH 19/23] fmt --- src/merkle_tree.cairo | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index d1020477..89ede39c 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -28,20 +28,20 @@ mod tests { #[test] fn test_merkle_root() { - let txids = array![ - 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, - 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, - 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, - 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, - 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, - 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, - 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_u256, - 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, - 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, - 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, - 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, - 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 - ]; + let txids = array![ + 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, + 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, + 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, + 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, + 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, + 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, + 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_u256, + 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, + 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, + 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, + 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, + 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 + ]; let expected_merkle_root = 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256; From ac600878e3c9ba356e5e0522a872679758153dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Fri, 9 Aug 2024 14:49:12 +0200 Subject: [PATCH 20/23] fix merkle_tree tests --- src/merkle_tree.cairo | 76 +++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index 89ede39c..fa77d06f 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -2,6 +2,11 @@ use super::utils::double_sha256; pub fn merkle_root(ref txids: Array) -> u256 { let len = txids.len(); + + if len == 1 { + return *txids.at(0); + } + if len % 2 == 1 { txids.append(*txids.at(len - 1)); } else { @@ -24,27 +29,62 @@ pub fn merkle_root(ref txids: Array) -> u256 { #[cfg(test)] mod tests { use super::{merkle_root}; - #[test] - fn test_merkle_root() { - let txids = array![ - 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256, - 0x96b8787b1e3abed802cff132c891c2e511edd200b08baa9eb7d8942d7c5423c6_u256, - 0x65e5a4862b807c83b588e0f4122d4ca2d46691d17a1ec1ebce4485dccc3380d4_u256, - 0x1ee9441ddde02f8ffb910613cd509adbc21282c6e34728599f3ae75e972fb815_u256, - 0xec950fc02f71fc06ed71afa4d2c49fcba04777f353a001b0bba9924c63cfe712_u256, - 0x5d874040a77de7182f7a68bf47c02898f519cb3b58092b79fa2cff614a0f4d50_u256, - 0x0a1c958af3e30ad07f659f44f708f8648452d1427463637b9039e5b721699615_u256, - 0xd94d24d2dcaac111f5f638983122b0e55a91aeb999e0e4d58e0952fa346a1711_u256, - 0xc4709bc9f860e5dff01b5fc7b53fb9deecc622214aba710d495bccc7f860af4a_u256, - 0xd4ed5f5e4334c0a4ccce6f706f3c9139ac0f6d2af3343ad3fae5a02fee8df542_u256, - 0xb5aed07505677c8b1c6703742f4558e993d7984dc03d2121d3712d81ee067351_u256, - 0xf9a14bf211c857f61ff9a1de95fc902faebff67c5d4898da8f48c9d306f1f80f_u256 + #[available_gas(100000000)] + fn test_merkle_root_01() { + let mut txids = array![ + 0xacd9825be8bece7782ec746a80b52f44d6a8af41c63dbab59b03e29558469682_u256, + ]; + + let expected_merkle_root = + 0xacd9825be8bece7782ec746a80b52f44d6a8af41c63dbab59b03e29558469682_u256; + + assert_eq!(merkle_root(ref txids), expected_merkle_root); + } + + #[test] + #[available_gas(100000000)] + fn test_merkle_root_02() { + let mut txids = array![ + 0x8710b2819a369672a2bce3d5270e7ae0ea59be2f7ce7f9078341b389098953e0_u256, + 0x64efde3a3f3531569cdab031bb31cfeb5c2d8cba62ae1ca5b2913b4ef643fd49_u256 ]; - - let expected_merkle_root = 0x50ba87bdd484f07c8c55f76a22982f987c0465fdc345381b4634a70dc0ea0b38_u256; - + + let expected_merkle_root = + 0x20dadaf81170decafec4b025366b75284dbe31dd42c8da5d25ff62fc4bff5d03_u256; + + assert_eq!(merkle_root(ref txids), expected_merkle_root); + } + + #[test] + #[available_gas(100000000)] + fn test_merkle_root_03() { + let mut txids = array![ + 0xd47e03351ee65f73321b684832edc4c840a1fe4bbd04bdb66a8328e5c7796e21_u256, + 0xbf304002ea77842b32dc91f1efe681a5a7909f4200e658e2ef2beb2a821101b9_u256, + 0x397bdf0bf5a8798f5b10bd95c70bb4a3f42ca14a9a837a4a54cd7de525dc0225_u256, + 0xd6ce148117a1cd094cdd5303ae0896cae1b29ad010b6cb0f3d43fa99b5e2c2f7_u256, + 0x7d5ad03ebf001acb47aafdf4915e86b7368ed3183c1e95f47280d81bb4ef91f8_u256, + 0x69cf63b266ebc862bd4d1a01473703c14bdd3a620f93ec323144c7d2c54529a0_u256, + 0x155be8f959b0187d7528a1ff11b3450690047aa96dbbb29a1ae3832b237c8179_u256, + 0x727d5fbed290d645ced8776c9031d7c3438454b5faf1f5dc0200dbe84f8e6035_u256, + 0xc6056c6021081150a86c092f6785955f757024f41472ad4b0cfd9dd39db8b4a2_u256, + 0x83f26f37bb715ec325f25544b6d7ae920fcc073c146c8dd12fbbde31a7ae1d2f_u256, + 0xd39bc02ef2b2c5afdb7807b0162b573648d9264d5e9872dbf26a7d480de301cd_u256, + 0x3dc087cb9e9d66c4d3e2cf29d23949e7b914db4c3f2114d34f34e97a2a44a169_u256, + 0x497d1b0bf7b0c502043fe7201a9696c466f514de3190097ef3b7d0664fc3d0bf_u256, + 0xa43dbef675b637c554987e8a1b98be3faf8850f88fa1bdf59b124c2356135a33_u256, + 0x4f9cf2c386b34b01d48a01ea31b5c795d1e869b42de78410b3ea1adf658f62a2_u256, + 0x46ef4071d3ddfd9443361ef2f4b2d5da7c57eaf59785564782d0d9b95280cb9b_u256, + 0xa48c60d6b27fd5c662d7dcd248b528474fd2598d26d51525deea3d225d7260e0_u256, + 0x5bb6e10378329bf6e78ce3e0f3abae1fb1c4bc40e1ce1b0e1a5f5db8a7fb1897_u256 + ]; + + let expected_merkle_root = + 0xe1455aa624aa92fa8b52766199033d66e4d100b39029e69906ae594397d977af_u256; + assert_eq!(merkle_root(ref txids), expected_merkle_root); } } + From cc290f1503857161f68e49aab051e8201580f58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Fri, 9 Aug 2024 15:48:02 +0200 Subject: [PATCH 21/23] :busts_in_silhouette: Add @olufemi-olumaiyegun as a contributor --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index b873cde0..194f1e24 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -90,6 +90,15 @@ "contributions": [ "code" ] + }, + { + "login": "olufemi-olumaiyegun", + "name": "Olufemi Olumaiyegun", + "avatar_url": "https://avatars.githubusercontent.com/u/53274579?v=4", + "profile": "https://www.heyfemi.com/home", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 5c3c8408..70c9758b 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Harsh Pratap Singh
Harsh Pratap Singh

💻 Xavek
Xavek

💻 + Olufemi Olumaiyegun
Olufemi Olumaiyegun

💻 From a43b171dd4ef048c788bc251068f6b9becd6c875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Fri, 9 Aug 2024 15:49:42 +0200 Subject: [PATCH 22/23] :busts_in_silhouette: Add @MSghais as a contributor --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 194f1e24..6459067f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -99,6 +99,15 @@ "contributions": [ "code" ] + }, + { + "login": "MSghais", + "name": "MSG", + "avatar_url": "https://avatars.githubusercontent.com/u/59928086?v=4", + "profile": "https://github.com/MSghais", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 70c9758b..8feb53fe 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Harsh Pratap Singh
Harsh Pratap Singh

💻 Xavek
Xavek

💻 Olufemi Olumaiyegun
Olufemi Olumaiyegun

💻 + MSG
MSG

💻 From 7484943c5dd04ffb6f392c7df5c96cb6fd145e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Fri, 9 Aug 2024 15:51:42 +0200 Subject: [PATCH 23/23] :busts_in_silhouette: Add @mubarak23 as a contributor --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6459067f..9644c0a0 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -108,6 +108,15 @@ "contributions": [ "code" ] + }, + { + "login": "mubarak23", + "name": "Mubarak Muhammad Aminu", + "avatar_url": "https://avatars.githubusercontent.com/u/7858376?v=4", + "profile": "http://mubarak23.github.io/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 8feb53fe..af17590c 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Xavek
Xavek

💻 Olufemi Olumaiyegun
Olufemi Olumaiyegun

💻 MSG
MSG

💻 + Mubarak Muhammad Aminu
Mubarak Muhammad Aminu

💻