From a8ba89fe2195232e7e860342617ddf5f6c6244c2 Mon Sep 17 00:00:00 2001 From: Stan Bondi Date: Fri, 1 Jul 2022 13:58:54 +0200 Subject: [PATCH] feat(core): validates non-contract utxos have no sidechain features (#4259) Description --- - adds simple validation rule to check that non-contract outputs do not contain sidechain features Motivation and Context --- Outputs that are not flagged with contract `OutputType`s should not contain `SideChainFeatures` How Has This Been Tested? --- Fail case unit test, happy case is tested by other tests --- .../core/src/validation/dan_validators/mod.rs | 38 ++++++++++++++++++- base_layer/core/src/validation/error.rs | 11 +++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/base_layer/core/src/validation/dan_validators/mod.rs b/base_layer/core/src/validation/dan_validators/mod.rs index fbaed04b67..004e86c6e8 100644 --- a/base_layer/core/src/validation/dan_validators/mod.rs +++ b/base_layer/core/src/validation/dan_validators/mod.rs @@ -52,6 +52,8 @@ mod helpers; mod error; pub use error::DanLayerValidationError; +use crate::transactions::transaction_components::TransactionOutput; + #[cfg(test)] mod test_helpers; @@ -80,10 +82,44 @@ impl MempoolTransactionValidation for TxDanLayerValidator< validate_update_proposal_acceptance(&self.db, output)? }, OutputType::ContractAmendment => validate_amendment(&self.db, output)?, - _ => continue, + _ => validate_no_sidechain_features(output)?, } } Ok(()) } } + +fn validate_no_sidechain_features(output: &TransactionOutput) -> Result<(), ValidationError> { + match output.features.sidechain_features { + Some(ref features) => Err(ValidationError::NonContractOutputContainsSidechainFeatures { + output_type: output.features.output_type, + contract_id: features.contract_id, + }), + None => Ok(()), + } +} + +#[cfg(test)] +mod tests { + use tari_common_types::types::FixedHash; + + use super::*; + use crate::transactions::{ + test_helpers::{create_unblinded_coinbase, TestParams}, + transaction_components::SideChainFeatures, + CryptoFactories, + }; + + #[test] + fn it_rejects_standard_output_type_with_sidechain_features() { + let mut utxo = create_unblinded_coinbase(&TestParams::new(), 1); + utxo.features.sidechain_features = Some(SideChainFeatures::builder(FixedHash::default()).finish()); + let output = utxo.as_transaction_output(&CryptoFactories::default()).unwrap(); + let err = validate_no_sidechain_features(&output).unwrap_err(); + assert!(matches!( + err, + ValidationError::NonContractOutputContainsSidechainFeatures { .. } + )) + } +} diff --git a/base_layer/core/src/validation/error.rs b/base_layer/core/src/validation/error.rs index 6ba293a229..1fbe87d21f 100644 --- a/base_layer/core/src/validation/error.rs +++ b/base_layer/core/src/validation/error.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use tari_common_types::types::HashOutput; +use tari_common_types::types::{FixedHash, HashOutput}; use thiserror::Error; use tokio::task; @@ -29,7 +29,7 @@ use crate::{ chain_storage::ChainStorageError, covenants::CovenantError, proof_of_work::{monero_rx::MergeMineError, PowError}, - transactions::transaction_components::TransactionError, + transactions::transaction_components::{OutputType, TransactionError}, validation::dan_validators::DanLayerValidationError, }; @@ -119,6 +119,13 @@ pub enum ValidationError { ErroneousCoinbaseOutput, #[error("Digital Asset Network Error: {0}")] DanLayerError(#[from] DanLayerValidationError), + #[error( + "Output was flagged as a {output_type} but contained sidechain feature data with contract_id {contract_id}" + )] + NonContractOutputContainsSidechainFeatures { + output_type: OutputType, + contract_id: FixedHash, + }, } // ChainStorageError has a ValidationError variant, so to prevent a cyclic dependency we use a string representation in