Skip to content

Commit

Permalink
fix: feature flag separation for validation (#5137)
Browse files Browse the repository at this point in the history
Description
---
Removes OpenSSL from the WalletFFI lib as its not required or used by it. 
Fixes validation feature flags. 

Motivation and Context
---
Recent refactor added `base_node` feature flag to the walletFFI. This should not be done as it adds in all the base node 
specific crates that not required by the wallet like randomX, lmdb etc. 
This splits the validation traits and implementations between the features `transactions` and `base_node`.

How Has This Been Tested?
---
Manual and unit tests

Fixes: #4974
  • Loading branch information
SWvheerden committed Feb 1, 2023
1 parent d5da7e5 commit 0e83463
Show file tree
Hide file tree
Showing 37 changed files with 180 additions and 415 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 0 additions & 13 deletions base_layer/core/src/blocks/block.rs
Expand Up @@ -61,8 +61,6 @@ pub enum BlockValidationError {
TransactionError(#[from] TransactionError),
#[error("Invalid input in block")]
InvalidInput,
#[error("Contains kernels or inputs that are not yet spendable")]
MaturityError,
#[error("Mismatched {kind} MMR roots")]
MismatchedMmrRoots { kind: &'static str },
#[error("MMR size for {mmr_tree} does not match. Expected: {expected}, received: {actual}")]
Expand All @@ -71,8 +69,6 @@ pub enum BlockValidationError {
expected: u64,
actual: u64,
},
#[error("The block weight ({actual_weight}) is above the maximum ({max_weight})")]
BlockTooLarge { actual_weight: u64, max_weight: u64 },
}

/// A Tari block. Blocks are linked together into a blockchain.
Expand Down Expand Up @@ -131,15 +127,6 @@ impl Block {
Ok(())
}

/// Checks that all STXO rules (maturity etc) and kernel heights are followed
pub fn check_spend_rules(&self) -> Result<(), BlockValidationError> {
self.body.check_utxo_rules(self.header.height)?;
if self.body.max_kernel_timelock() > self.header.height {
return Err(BlockValidationError::MaturityError);
}
Ok(())
}

/// Destroys the block and returns the pieces of the block: header, inputs, outputs and kernels
pub fn dissolve(
self,
Expand Down
Expand Up @@ -711,7 +711,6 @@ mod test {

#[test]
fn test_double_spend_inputs() {
let rules = create_consensus_rules();
let (tx1, _, _) = tx!(MicroTari(5_000), fee: MicroTari(10), inputs: 1, outputs: 1);
const INPUT_AMOUNT: MicroTari = MicroTari(5_000);
let (tx2, inputs, _) = tx!(INPUT_AMOUNT, fee: MicroTari(5), inputs: 1, outputs: 1);
Expand Down Expand Up @@ -749,7 +748,7 @@ mod test {

let factories = CryptoFactories::default();
let mut stx_protocol = stx_builder.build(&factories, None, u64::MAX).unwrap();
stx_protocol.finalize(rules, &factories, None, u64::MAX).unwrap();
stx_protocol.finalize().unwrap();

let tx3 = stx_protocol.get_transaction().unwrap().clone();

Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/src/test_helpers/mod.rs
Expand Up @@ -85,7 +85,7 @@ pub fn create_block(rules: &ConsensusManager, prev_block: &Block, spec: BlockSpe
.with_fees(0.into())
.with_nonce(0.into())
.with_spend_key(block_height.into())
.build_with_reward(rules.clone(), rules.consensus_constants(block_height), reward)
.build_with_reward(rules.consensus_constants(block_height), reward)
.unwrap();

let mut block = header
Expand Down
32 changes: 16 additions & 16 deletions base_layer/core/src/transactions/coinbase_builder.rs
Expand Up @@ -36,7 +36,6 @@ use crate::{
consensus::{
emission::{Emission, EmissionSchedule},
ConsensusConstants,
ConsensusManager,
},
covenants::Covenant,
transactions::{
Expand Down Expand Up @@ -178,13 +177,12 @@ impl CoinbaseBuilder {

pub fn build(
self,
rules: ConsensusManager,
constants: &ConsensusConstants,
emission_schedule: &EmissionSchedule,
) -> Result<(Transaction, UnblindedOutput), CoinbaseBuildError> {
let height = self.block_height.ok_or(CoinbaseBuildError::MissingBlockHeight)?;
let reward = emission_schedule.block_reward(height);
self.build_with_reward(rules, constants, reward)
self.build_with_reward(constants, reward)
}

/// Try and construct a Coinbase Transaction while specifying the block reward. The other parameters (keys, nonces
Expand All @@ -197,7 +195,6 @@ impl CoinbaseBuilder {
#[allow(clippy::erasing_op)] // This is for 0 * uT
pub fn build_with_reward(
self,
rules: ConsensusManager,
constants: &ConsensusConstants,
block_reward: MicroTari,
) -> Result<(Transaction, UnblindedOutput), CoinbaseBuildError> {
Expand Down Expand Up @@ -295,7 +292,7 @@ impl CoinbaseBuilder {
.with_reward(total_reward)
.with_kernel(kernel);
let tx = builder
.build(rules, &self.factories, None, height)
.build()
.map_err(|e| CoinbaseBuildError::BuildError(e.to_string()))?;
Ok((tx, unblinded_output))
}
Expand Down Expand Up @@ -341,7 +338,7 @@ mod test {
let (builder, rules, _) = get_builder();
assert_eq!(
builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule(),)
.build(rules.consensus_constants(0), rules.emission_schedule(),)
.unwrap_err(),
CoinbaseBuildError::MissingBlockHeight
);
Expand All @@ -353,7 +350,7 @@ mod test {
let builder = builder.with_block_height(42);
assert_eq!(
builder
.build(rules.clone(), rules.consensus_constants(42), rules.emission_schedule(),)
.build(rules.consensus_constants(42), rules.emission_schedule(),)
.unwrap_err(),
CoinbaseBuildError::MissingFees
);
Expand All @@ -368,7 +365,7 @@ mod test {
let builder = builder.with_block_height(42).with_fees(fees).with_nonce(p.nonce);
assert_eq!(
builder
.build(rules.clone(), rules.consensus_constants(42), rules.emission_schedule(),)
.build(rules.consensus_constants(42), rules.emission_schedule(),)
.unwrap_err(),
CoinbaseBuildError::MissingSpendKey
);
Expand All @@ -384,7 +381,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key.clone());
let (tx, _unblinded_output) = builder
.build(rules.clone(), rules.consensus_constants(42), rules.emission_schedule())
.build(rules.consensus_constants(42), rules.emission_schedule())
.unwrap();
let utxo = &tx.body.outputs()[0];
let block_reward = rules.emission_schedule().block_reward(42) + 145 * uT;
Expand Down Expand Up @@ -422,7 +419,7 @@ mod test {
.with_spend_key(p.spend_key.clone())
.with_rewind_data(rewind_data.clone());
let (tx, _) = builder
.build(rules.clone(), rules.consensus_constants(42), rules.emission_schedule())
.build(rules.consensus_constants(42), rules.emission_schedule())
.unwrap();
let block_reward = rules.emission_schedule().block_reward(42) + 145 * uT;

Expand All @@ -448,7 +445,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key);
let (mut tx, _) = builder
.build(rules.clone(), rules.consensus_constants(42), rules.emission_schedule())
.build(rules.consensus_constants(42), rules.emission_schedule())
.unwrap();
tx.body.outputs_mut()[0].features.maturity = 1;
assert!(matches!(
Expand All @@ -475,7 +472,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key.clone());
let (mut tx, _) = builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule())
.build(rules.consensus_constants(0), rules.emission_schedule())
.unwrap();
let block_reward = rules.emission_schedule().block_reward(42) + missing_fee;
let builder = CoinbaseBuilder::new(factories.clone());
Expand All @@ -485,7 +482,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key.clone());
let (tx2, _) = builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule())
.build(rules.consensus_constants(0), rules.emission_schedule())
.unwrap();
let mut coinbase2 = tx2.body.outputs()[0].clone();
let mut coinbase_kernel2 = tx2.body.kernels()[0].clone();
Expand All @@ -512,7 +509,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key);
let (tx3, _) = builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule())
.build(rules.consensus_constants(0), rules.emission_schedule())
.unwrap();
assert!(tx3
.body
Expand All @@ -539,7 +536,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key.clone());
let (mut tx, _) = builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule())
.build(rules.consensus_constants(0), rules.emission_schedule())
.unwrap();
let block_reward = rules.emission_schedule().block_reward(42) + missing_fee;
let builder = CoinbaseBuilder::new(factories.clone());
Expand All @@ -549,7 +546,7 @@ mod test {
.with_nonce(p.nonce.clone())
.with_spend_key(p.spend_key);
let (tx2, output) = builder
.build(rules.clone(), rules.consensus_constants(0), rules.emission_schedule())
.build(rules.consensus_constants(0), rules.emission_schedule())
.unwrap();
let mut tx_kernel_test = tx.clone();

Expand All @@ -571,6 +568,7 @@ mod test {

tx.body.add_output(coinbase2);
tx.body.add_kernel(coinbase_kernel2);
tx.body.sort();

// lets add duplciate coinbase kernel
let mut coinbase2 = tx2.body.outputs()[0].clone();
Expand All @@ -579,6 +577,8 @@ mod test {
tx_kernel_test.body.add_output(coinbase2);
tx_kernel_test.body.add_kernel(coinbase_kernel2);

tx_kernel_test.body.sort();

// test catches that coinbase count on the utxo is wrong
assert!(matches!(
tx.body.check_coinbase_output(
Expand Down
7 changes: 2 additions & 5 deletions base_layer/core/src/transactions/test_helpers.rs
Expand Up @@ -624,7 +624,7 @@ pub fn create_sender_transaction_protocol_with(
});

let mut stx_protocol = stx_builder.build(&factories, None, u64::MAX).unwrap();
stx_protocol.finalize(rules, &factories, None, u64::MAX)?;
stx_protocol.finalize()?;

Ok(stx_protocol)
}
Expand All @@ -634,11 +634,8 @@ pub fn create_sender_transaction_protocol_with(
/// This is obviously less efficient, but is offered as a convenience.
/// The output features will be applied to every output
pub fn spend_utxos(schema: TransactionSchema) -> (Transaction, Vec<UnblindedOutput>) {
let rules = ConsensusManager::builder(Network::LocalNet).build();
let (mut stx_protocol, outputs) = create_stx_protocol(schema);
stx_protocol
.finalize(rules, &CryptoFactories::default(), None, u64::MAX)
.unwrap();
stx_protocol.finalize().unwrap();
let txn = stx_protocol.get_transaction().unwrap().clone();
(txn, outputs)
}
Expand Down
Expand Up @@ -356,7 +356,7 @@ fn check_cut_through() {
assert_eq!(tx2.body.outputs().len(), 3);
assert_eq!(tx2.body.kernels().len(), 1);

let tx3 = tx + tx2;
let mut tx3 = tx + tx2;
let mut tx3_cut_through = tx3.clone();
// check that all inputs are as we expect them to be
assert_eq!(tx3.body.inputs().len(), 3);
Expand All @@ -376,6 +376,8 @@ fn check_cut_through() {
tx3_cut_through.body.outputs_mut().retain(|x| !input.is_equal_to(x));
tx3_cut_through.body.inputs_mut().retain(|x| *x != input);
}
tx3.body.sort();
tx3_cut_through.body.sort();

// Validate basis transaction where cut-through has not been applied.
validator.validate(&tx3, None, None, u64::MAX).unwrap();
Expand Down
Expand Up @@ -23,23 +23,12 @@
// Portions of this file were originally copyrighted (c) 2018 The Grin Developers, issued under the Apache License,
// Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0.

use tari_common_types::types::{BlindingFactor, HashOutput};
use tari_common_types::types::BlindingFactor;

use crate::{
consensus::ConsensusManager,
transactions::{
aggregated_body::AggregateBody,
tari_amount::MicroTari,
transaction_components::{
Transaction,
TransactionError,
TransactionInput,
TransactionKernel,
TransactionOutput,
},
CryptoFactories,
},
validation::transaction::TransactionInternalConsistencyValidator,
use crate::transactions::{
aggregated_body::AggregateBody,
tari_amount::MicroTari,
transaction_components::{Transaction, TransactionError, TransactionInput, TransactionKernel, TransactionOutput},
};

//---------------------------------------- Transaction Builder ----------------------------------------------------//
Expand Down Expand Up @@ -104,20 +93,11 @@ impl TransactionBuilder {
}

/// Build the transaction.
pub fn build(
self,
rules: ConsensusManager,
factories: &CryptoFactories,
prev_header: Option<HashOutput>,
height: u64,
) -> Result<Transaction, TransactionError> {
pub fn build(self) -> Result<Transaction, TransactionError> {
if let (Some(script_offset), Some(offset)) = (self.script_offset, self.offset) {
let (i, o, k) = self.body.dissolve();
let tx = Transaction::new(i, o, k, offset, script_offset);
let validator = TransactionInternalConsistencyValidator::new(true, rules, factories.clone());
validator
.validate(&tx, self.reward, prev_header, height)
.map_err(|err| TransactionError::ValidationError(err.to_string()))?;
let mut tx = Transaction::new(i, o, k, offset, script_offset);
tx.body.sort();
Ok(tx)
} else {
Err(TransactionError::ValidationError(
Expand Down
Expand Up @@ -160,6 +160,11 @@ impl TransactionOutput {
&self.proof
}

/// Accessor method for the TariScript contained in an output
pub fn script(&self) -> &TariScript {
&self.script
}

pub fn hash(&self) -> FixedHash {
transaction_components::hash_output(
self.version,
Expand Down

0 comments on commit 0e83463

Please sign in to comment.