diff --git a/goat/src/transactions/base.rs b/goat/src/transactions/base.rs index e4ecb828..56dfb619 100644 --- a/goat/src/transactions/base.rs +++ b/goat/src/transactions/base.rs @@ -53,6 +53,36 @@ pub const fn disprove_input_amount() -> u64 { pub const fn pubin_disprove_input_amount() -> u64 { MIN_RELAY_FEE_PUBIN_DISPROVE + P2A_AMOUNT } +pub const fn watchtower_challenge_timeout_input_amount() -> u64 { + MIN_RELAY_FEE_WATCHTOWER_CHALLENGE_TIMEOUT + P2A_AMOUNT +} +pub const fn operator_challenge_nack_input_amount() -> u64 { + MIN_RELAY_FEE_OPERATOR_CHALLENGE_NACK + P2A_AMOUNT +} +pub const fn operator_commit_timeout_input_amount() -> u64 { + MIN_RELAY_FEE_OPERATOR_COMMIT_TIMEOUT + P2A_AMOUNT +} +pub const fn watchtower_challenge_connector_output_amount() -> u64 { + max( + DUST_AMOUNT, + watchtower_challenge_timeout_input_amount().saturating_sub(ack_connector_output_amount()), + ) +} +pub const fn ack_connector_output_amount() -> u64 { + DUST_AMOUNT +} +pub const fn connector_e_output_amount() -> u64 { + DUST_AMOUNT +} +pub const fn connector_f_output_amount() -> u64 { + max( + DUST_AMOUNT, + max( + operator_challenge_nack_input_amount().saturating_sub(ack_connector_output_amount()), + operator_commit_timeout_input_amount().saturating_sub(connector_e_output_amount()), + ), + ) +} pub const fn connector_d_assert_output_amount() -> u64 { let disprove_connector_d_amount = if disprove_input_amount() > verifier_assert_prover_output_amount() { @@ -77,7 +107,10 @@ pub const fn max_assert_cost(num_verifier: usize) -> u64 { } pub const fn max_watchtower_challenge_cost(num_watchtowers: usize) -> u64 { min_relay_fee_watchtower_challenge_init(num_watchtowers) - + (num_watchtowers as u64 * 2 + 2) * DUST_AMOUNT + + num_watchtowers as u64 + * (watchtower_challenge_connector_output_amount() + ack_connector_output_amount()) + + connector_e_output_amount() + + connector_f_output_amount() + P2A_AMOUNT } pub const fn max_pegout_cost(num_watchtowers: usize, num_verifier: usize) -> u64 { @@ -85,6 +118,7 @@ pub const fn max_pegout_cost(num_watchtowers: usize, num_verifier: usize) -> u64 + max_watchtower_challenge_cost(num_watchtowers) + MIN_RELAY_FEE_KICKOFF + DUST_AMOUNT * 2 + + P2A_AMOUNT } #[derive(Serialize, Deserialize, Eq, PartialEq, Clone)] diff --git a/goat/src/transactions/kickoff.rs b/goat/src/transactions/kickoff.rs index 72cf6b65..c8b06661 100644 --- a/goat/src/transactions/kickoff.rs +++ b/goat/src/transactions/kickoff.rs @@ -14,7 +14,7 @@ use crate::{ scripts::p2a_output, transactions::{ base::{ - max_assert_cost, max_watchtower_challenge_cost, output_topology, tx_output_input, + max_pegout_cost, max_watchtower_challenge_cost, output_topology, tx_output_input, BaseTransaction, Input, DUST_AMOUNT, MIN_RELAY_FEE_KICKOFF, }, pre_signed::{pre_sign_taproot_input_default, PreSignedTransaction}, @@ -61,14 +61,7 @@ impl KickoffTransaction { let input_0_leaf = 0; let _input_0 = kickoff_connector.generate_taproot_leaf_tx_in(input_0_leaf, input_0); - if input_0.amount - < Amount::from_sat( - MIN_RELAY_FEE_KICKOFF - + 4 * DUST_AMOUNT - + max_watchtower_challenge_cost(watchtower_num) - + max_assert_cost(verifier_num), - ) - { + if input_0.amount < Amount::from_sat(max_pegout_cost(watchtower_num, verifier_num)) { return Err(Error::Transaction(InsufficientInputAmount)); } let total_output_amount = input_0.amount - Amount::from_sat(MIN_RELAY_FEE_KICKOFF); diff --git a/goat/src/transactions/prekickoff.rs b/goat/src/transactions/prekickoff.rs index 0d462306..5f0a5dea 100644 --- a/goat/src/transactions/prekickoff.rs +++ b/goat/src/transactions/prekickoff.rs @@ -127,7 +127,10 @@ impl PrekickoffTransaction { if total_input_amount < Amount::from_sat( - fee_amount + 3 * DUST_AMOUNT + max_pegout_cost(watchtower_num, verifier_num), + fee_amount + + 2 * DUST_AMOUNT + + P2A_AMOUNT + + max_pegout_cost(watchtower_num, verifier_num), ) { return Err(Error::Transaction(InsufficientInputAmount)); diff --git a/goat/src/transactions/take1.rs b/goat/src/transactions/take1.rs index d76704e6..76600edf 100644 --- a/goat/src/transactions/take1.rs +++ b/goat/src/transactions/take1.rs @@ -85,7 +85,7 @@ impl Take1Transaction { let total_input_amount = input_0.amount + input_1.amount + input_2.amount + input_3.amount + input_4.amount; - if total_input_amount < (Amount::from_sat(MIN_RELAY_FEE_TAKE_1 + 2 * DUST_AMOUNT)) { + if total_input_amount < Amount::from_sat(MIN_RELAY_FEE_TAKE_1 + DUST_AMOUNT + P2A_AMOUNT) { return Err(Error::Transaction(InsufficientInputAmount)); } diff --git a/goat/src/transactions/take2.rs b/goat/src/transactions/take2.rs index d8c872d1..d80b9d57 100644 --- a/goat/src/transactions/take2.rs +++ b/goat/src/transactions/take2.rs @@ -78,7 +78,7 @@ impl Take2Transaction { let total_input_amount = input_0.amount + input_1.amount + input_2.amount + input_3.amount; - if total_input_amount < (Amount::from_sat(MIN_RELAY_FEE_TAKE_2 + 2 * DUST_AMOUNT)) { + if total_input_amount < Amount::from_sat(MIN_RELAY_FEE_TAKE_2 + DUST_AMOUNT + P2A_AMOUNT) { return Err(Error::Transaction(InsufficientInputAmount)); } diff --git a/goat/src/transactions/watchtower_challenge.rs b/goat/src/transactions/watchtower_challenge.rs index fcbc4220..7d69179b 100644 --- a/goat/src/transactions/watchtower_challenge.rs +++ b/goat/src/transactions/watchtower_challenge.rs @@ -211,13 +211,13 @@ impl WatchtowerChallengeInitTransaction { .zip(ack_connectors.iter()) { let challenge_output = TxOut { - value: Amount::from_sat(DUST_AMOUNT), + value: Amount::from_sat(watchtower_challenge_connector_output_amount()), script_pubkey: watchtower_challenge_connector .generate_taproot_address() .script_pubkey(), }; let ack_output = TxOut { - value: Amount::from_sat(DUST_AMOUNT), + value: Amount::from_sat(ack_connector_output_amount()), script_pubkey: ack_connector.generate_taproot_address().script_pubkey(), }; total_output_amount = total_output_amount - challenge_output.value - ack_output.value; @@ -226,7 +226,7 @@ impl WatchtowerChallengeInitTransaction { } let connector_e_output = TxOut { - value: Amount::from_sat(DUST_AMOUNT), + value: Amount::from_sat(connector_e_output_amount()), script_pubkey: connector_e.generate_taproot_address().script_pubkey(), }; let anchor_output = p2a_output();