From 3b30fdb99af14a43eb0e9762861f5fabc2481cca Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Tue, 2 Aug 2022 12:19:26 +0200 Subject: [PATCH] fix: burned output check (#4374) Description --- fixes the burned output check. Adds in a unit test to ensure its correct How Has This Been Tested? --- Unit and integration --- base_layer/core/src/validation/helpers.rs | 56 ++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/base_layer/core/src/validation/helpers.rs b/base_layer/core/src/validation/helpers.rs index ac9c2dada6..b1eca6ea4d 100644 --- a/base_layer/core/src/validation/helpers.rs +++ b/base_layer/core/src/validation/helpers.rs @@ -280,7 +280,7 @@ pub fn check_total_burned(body: &AggregateBody) -> Result<(), ValidationError> { } } for kernel in body.kernels() { - if kernel.is_burned() && burned_outputs.remove(kernel.get_burn_commitment()?) { + if kernel.is_burned() && !burned_outputs.remove(kernel.get_burn_commitment()?) { return Err(ValidationError::InvalidBurnError( "Burned kernel does not match burned output".to_string(), )); @@ -1039,4 +1039,58 @@ mod test { unpack_enum!(TransactionError::InvalidCoinbase = err); } } + + use crate::{covenants::Covenant, transactions::transaction_components::KernelFeatures}; + + #[test] + fn check_burned_succeeds_for_valid_outputs() { + let mut kernel1 = test_helpers::create_test_kernel(0.into(), 0); + let mut kernel2 = test_helpers::create_test_kernel(0.into(), 0); + + let (output1, _, _) = test_helpers::create_utxo( + 100.into(), + &CryptoFactories::default(), + &OutputFeatures::create_burn_output(), + &TariScript::default(), + &Covenant::default(), + 0.into(), + ); + let (output2, _, _) = test_helpers::create_utxo( + 101.into(), + &CryptoFactories::default(), + &OutputFeatures::create_burn_output(), + &TariScript::default(), + &Covenant::default(), + 0.into(), + ); + let (output3, _, _) = test_helpers::create_utxo( + 102.into(), + &CryptoFactories::default(), + &OutputFeatures::create_burn_output(), + &TariScript::default(), + &Covenant::default(), + 0.into(), + ); + + kernel1.features = KernelFeatures::create_burn(); + kernel1.burn_commitment = Some(output1.commitment.clone()); + kernel2.features = KernelFeatures::create_burn(); + kernel2.burn_commitment = Some(output2.commitment.clone()); + let kernel3 = kernel1.clone(); + + let mut body = AggregateBody::new(Vec::new(), vec![output1.clone(), output2.clone()], vec![ + kernel1.clone(), + kernel2.clone(), + ]); + assert!(check_total_burned(&body).is_ok()); + // lets add an extra kernel + body.add_kernels(&mut vec![kernel3]); + assert!(check_total_burned(&body).is_err()); + // lets add a kernel commitment mismatch + body.add_outputs(&mut vec![output3.clone()]); + assert!(check_total_burned(&body).is_err()); + // Lets try one with a commitment with no kernel + let body2 = AggregateBody::new(Vec::new(), vec![output1, output2, output3], vec![kernel1, kernel2]); + assert!(check_total_burned(&body2).is_err()); + } }