mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-08 06:35:52 +01:00
feat: add targeted split
This commit is contained in:
@@ -21,6 +21,48 @@ impl Amount {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Split into parts that are powers of two by target
|
||||
pub fn split_targeted(&self, target: &SplitTarget) -> Vec<Self> {
|
||||
let mut parts = vec![];
|
||||
let mut parts_total = Amount::ZERO;
|
||||
|
||||
match target {
|
||||
&SplitTarget::Value(amount) => {
|
||||
if self.le(&amount) {
|
||||
return self.split();
|
||||
}
|
||||
|
||||
// The powers of two that are need to create target value
|
||||
let parts_of_value = amount.split();
|
||||
|
||||
while parts_total.lt(self) {
|
||||
for part in parts_of_value.iter().copied() {
|
||||
if (part + parts_total).le(self) {
|
||||
parts.push(part);
|
||||
} else {
|
||||
let amount_left = *self - parts_total;
|
||||
parts.extend(amount_left.split());
|
||||
}
|
||||
|
||||
parts_total = parts.clone().iter().copied().sum::<Amount>();
|
||||
|
||||
if parts_total.eq(self) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parts.sort();
|
||||
parts
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum SplitTarget {
|
||||
Value(Amount),
|
||||
}
|
||||
|
||||
impl Default for Amount {
|
||||
@@ -102,4 +144,45 @@ mod tests {
|
||||
.collect();
|
||||
assert_eq!(Amount::from(255).split(), amounts);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_target_amount() {
|
||||
let amount = Amount(65);
|
||||
|
||||
let split = amount.split_targeted(&SplitTarget::Value(Amount(32)));
|
||||
assert_eq!(vec![Amount(1), Amount(32), Amount(32)], split);
|
||||
|
||||
let amount = Amount(150);
|
||||
|
||||
let split = amount.split_targeted(&SplitTarget::Value(Amount::from(50)));
|
||||
assert_eq!(
|
||||
vec![
|
||||
Amount(2),
|
||||
Amount(2),
|
||||
Amount(2),
|
||||
Amount(16),
|
||||
Amount(16),
|
||||
Amount(16),
|
||||
Amount(32),
|
||||
Amount(32),
|
||||
Amount(32)
|
||||
],
|
||||
split
|
||||
);
|
||||
|
||||
let amount = Amount::from(63);
|
||||
|
||||
let split = amount.split_targeted(&SplitTarget::Value(Amount::from(32)));
|
||||
assert_eq!(
|
||||
vec![
|
||||
Amount(1),
|
||||
Amount(2),
|
||||
Amount(4),
|
||||
Amount(8),
|
||||
Amount(16),
|
||||
Amount(32)
|
||||
],
|
||||
split
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
use bitcoin::hashes::Hash;
|
||||
use bitcoin::secp256k1::rand::{self, RngCore};
|
||||
use bitcoin::secp256k1::{All, Secp256k1};
|
||||
use bitcoin::secp256k1::{rand, All, Secp256k1};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use instant::SystemTime;
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -24,15 +21,7 @@ pub static SECP256K1: Lazy<Secp256k1<All>> = Lazy::new(|| {
|
||||
ctx
|
||||
});
|
||||
|
||||
pub fn random_hash() -> Vec<u8> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut random_bytes: [u8; 32] = [0u8; Sha256::LEN];
|
||||
rng.fill_bytes(&mut random_bytes);
|
||||
|
||||
let hash = Sha256::hash(&random_bytes);
|
||||
hash.to_byte_array().to_vec()
|
||||
}
|
||||
|
||||
/// Seconds since unix epoch
|
||||
pub fn unix_time() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
||||
Reference in New Issue
Block a user