From 148fdb8d0a45ce929f14c8c0f22e8506142758c4 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 12 Aug 2021 11:28:00 +1000 Subject: [PATCH] Ensure the size of our locking script never changes --- swap/Cargo.toml | 1 + swap/src/bitcoin/lock.rs | 22 ++++++++++++++-------- swap/src/lib.rs | 3 +++ swap/src/proptest.rs | 17 +++++++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 swap/src/proptest.rs diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 92eeb2b8..727f8e65 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -80,6 +80,7 @@ get-port = "3" hyper = "0.14" monero-harness = { path = "../monero-harness" } port_check = "0.1" +proptest = "1" serde_cbor = "0.11" spectral = "0.6" tempfile = "3" diff --git a/swap/src/bitcoin/lock.rs b/swap/src/bitcoin/lock.rs index b1b2be0e..2f82ff77 100644 --- a/swap/src/bitcoin/lock.rs +++ b/swap/src/bitcoin/lock.rs @@ -7,11 +7,11 @@ use ::bitcoin::{OutPoint, TxIn, TxOut, Txid}; use anyhow::{bail, Result}; use bdk::database::BatchDatabase; use bitcoin::Script; -use ecdsa_fun::fun::Point; use miniscript::{Descriptor, DescriptorTrait}; -use rand::thread_rng; use serde::{Deserialize, Serialize}; +const SCRIPT_SIZE: usize = 34; + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TxLock { inner: PartiallySignedTransaction, @@ -112,12 +112,7 @@ impl TxLock { /// Calculate the size of the script used by this transaction. pub fn script_size() -> usize { - build_shared_output_descriptor( - Point::random(&mut thread_rng()), - Point::random(&mut thread_rng()), - ) - .script_pubkey() - .len() + SCRIPT_SIZE } pub fn script_pubkey(&self) -> Script { @@ -245,6 +240,17 @@ mod tests { result.expect_err("PSBT to be invalid"); } + proptest::proptest! { + #[test] + fn estimated_tx_lock_script_size_never_changes(a in crate::proptest::ecdsa_fun::point(), b in crate::proptest::ecdsa_fun::point()) { + proptest::prop_assume!(a != b); + + let computed_size = build_shared_output_descriptor(a, b).script_pubkey().len(); + + assert_eq!(computed_size, SCRIPT_SIZE); + } + } + /// Helper function that represents Bob's action of constructing the PSBT. /// /// Extracting this allows us to keep the tests concise. diff --git a/swap/src/lib.rs b/swap/src/lib.rs index 64c8ffe9..1b050ae2 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -32,3 +32,6 @@ pub mod tor; pub mod tracing_ext; mod monero_ext; + +#[cfg(test)] +mod proptest; diff --git a/swap/src/proptest.rs b/swap/src/proptest.rs new file mode 100644 index 00000000..0c7ee7b3 --- /dev/null +++ b/swap/src/proptest.rs @@ -0,0 +1,17 @@ +use proptest::prelude::*; + +pub mod ecdsa_fun { + use super::*; + use ::ecdsa_fun::fun::marker::{Mark, NonZero, Normal}; + use ::ecdsa_fun::fun::{Point, Scalar, G}; + + pub fn point() -> impl Strategy { + scalar().prop_map(|mut scalar| Point::from_scalar_mul(&G, &mut scalar).mark::()) + } + + pub fn scalar() -> impl Strategy { + prop::array::uniform32(0..255u8).prop_filter_map("generated the 0 element", |bytes| { + Scalar::from_bytes_mod_order(bytes).mark::() + }) + } +}