Skip to content

Commit

Permalink
remove blockchainstorage from internal_tx_validation
Browse files Browse the repository at this point in the history
remove base_node from wallet_ffi
  • Loading branch information
SWvheerden committed Jan 30, 2023
1 parent 6b125af commit e245adc
Show file tree
Hide file tree
Showing 24 changed files with 145 additions and 102 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
Original file line number Diff line number Diff line change
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
2 changes: 1 addition & 1 deletion base_layer/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub mod covenants;
#[cfg(feature = "base_node")]
pub mod iterators;
pub mod proof_of_work;
#[cfg(feature = "base_node")]
#[cfg(any(feature = "base_node", feature = "transactions"))]
pub mod validation;

#[cfg(any(test, feature = "base_node"))]
Expand Down
3 changes: 3 additions & 0 deletions base_layer/core/src/transactions/coinbase_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,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 +580,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ impl TransactionBuilder {
) -> 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 mut tx = Transaction::new(i, o, k, offset, script_offset);
tx.body.sort();
let validator = TransactionInternalConsistencyValidator::new(true, rules, factories.clone());
validator
.validate(&tx, self.reward, prev_header, height)
Expand Down
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,7 @@ impl SenderTransactionProtocol {
.validate()
.and_then(|_| Self::build_transaction(info, rules.clone(), factories));
match result {
Ok(mut transaction) => {
transaction.body.sort();
Ok(transaction) => {
let validator = TransactionInternalConsistencyValidator::new(true, rules, factories.clone());
let result = validator
.validate(&transaction, None, prev_header, height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ use tari_script::ScriptContext;
use tari_utilities::hex::Hex;

use crate::{
blocks::BlockValidationError,
consensus::{ConsensusConstants, ConsensusManager},
transactions::{
aggregated_body::AggregateBody,
Expand All @@ -59,6 +58,8 @@ use crate::{
validation::{
helpers::{
check_permitted_output_types,
check_tari_script_byte_size,
is_all_unique_and_sorted,
validate_input_version,
validate_kernel_version,
validate_output_version,
Expand Down Expand Up @@ -108,9 +109,18 @@ impl AggregateBodyInternalConsistencyValidator {
) -> Result<(), ValidationError> {
let total_reward = total_reward.unwrap_or(MicroTari::zero());

// old internal validatior
// old internal validator
verify_kernel_signatures(body)?;

check_script_size(
body,
self.consensus_manager
.consensus_constants(height)
.get_max_script_byte_size(),
)?;

check_sorting_and_duplicates(body)?;

let total_offset = self.factories.commitment.commit_value(tx_offset, total_reward.0);
validate_kernel_sum(body, total_offset, &self.factories.commitment)?;

Expand Down Expand Up @@ -157,6 +167,38 @@ fn verify_kernel_signatures(body: &AggregateBody) -> Result<(), ValidationError>
Ok(())
}

/// Verify that the TariScript is not larger than the max size
fn check_script_size(body: &AggregateBody, max_script_size: usize) -> Result<(), ValidationError> {
for output in body.outputs() {
check_tari_script_byte_size(output.script(), max_script_size).map_err(|e| {
warn!(
target: LOG_TARGET,
"output ({}) script size exceeded max size {:?}.", output, e
);
e
})?;
}
Ok(())
}

// This function checks for duplicate inputs and outputs. There should be no duplicate inputs or outputs in a aggregated
// body
fn check_sorting_and_duplicates(body: &AggregateBody) -> Result<(), ValidationError> {
if !is_all_unique_and_sorted(body.inputs()) {
return Err(ValidationError::UnsortedOrDuplicateInput);
}

if !is_all_unique_and_sorted(body.outputs()) {
return Err(ValidationError::UnsortedOrDuplicateOutput);
}

if !is_all_unique_and_sorted(body.kernels()) {
return Err(ValidationError::UnsortedOrDuplicateKernel);
}

Ok(())
}

/// Confirm that the (sum of the outputs) - (sum of inputs) = Kernel excess
///
/// The offset_and_reward commitment includes the offset & the total coinbase reward (block reward + fees for
Expand Down Expand Up @@ -289,18 +331,17 @@ fn check_weight(

Ok(())
} else {
Err(BlockValidationError::BlockTooLarge {
Err(ValidationError::BlockTooLarge {
actual_weight: block_weight,
max_weight,
}
.into())
})
}
}

/// Checks that all transactions (given by their kernels) are spendable at the given height
fn check_kernel_lock_height(height: u64, kernels: &[TransactionKernel]) -> Result<(), BlockValidationError> {
fn check_kernel_lock_height(height: u64, kernels: &[TransactionKernel]) -> Result<(), ValidationError> {
if kernels.iter().any(|k| k.lock_height > height) {
return Err(BlockValidationError::MaturityError);
return Err(ValidationError::MaturityError);
}
Ok(())
}
Expand Down Expand Up @@ -424,7 +465,7 @@ mod test {
kernel.lock_height = 2;
assert!(matches!(
check_kernel_lock_height(1, &[kernel.clone()]),
Err(BlockValidationError::MaturityError)
Err(ValidationError::MaturityError)
));

check_kernel_lock_height(2, &[kernel.clone()]).unwrap();
Expand Down
3 changes: 2 additions & 1 deletion base_layer/core/src/validation/aggregate_body/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

mod aggregate_body_internal_validator;
pub use aggregate_body_internal_validator::AggregateBodyInternalConsistencyValidator;

#[cfg(feature = "base_node")]
mod aggregate_body_chain_validator;
#[cfg(feature = "base_node")]
pub use aggregate_body_chain_validator::AggregateBodyChainLinkedValidator;
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use crate::{
transactions::{aggregated_body::AggregateBody, CryptoFactories},
validation::{
aggregate_body::AggregateBodyInternalConsistencyValidator,
helpers::is_all_unique_and_sorted,
InternalConsistencyValidator,
ValidationError,
},
Expand Down Expand Up @@ -89,7 +88,7 @@ fn validate_block_specific_checks(
warn!(target: LOG_TARGET, "Attempt to validate genesis block");
return Err(ValidationError::ValidatingGenesis);
}
check_sorting_and_duplicates(&block.body)?;

check_coinbase_output(block, consensus_manager, factories)?;
check_output_features(&block.body, constants)?;

Expand Down Expand Up @@ -149,20 +148,3 @@ fn check_coinbase_output(
)
.map_err(ValidationError::from)
}

// This function checks for duplicate inputs and outputs. There should be no duplicate inputs or outputs in a block
fn check_sorting_and_duplicates(body: &AggregateBody) -> Result<(), ValidationError> {
if !is_all_unique_and_sorted(body.inputs()) {
return Err(ValidationError::UnsortedOrDuplicateInput);
}

if !is_all_unique_and_sorted(body.outputs()) {
return Err(ValidationError::UnsortedOrDuplicateOutput);
}

if !is_all_unique_and_sorted(body.kernels()) {
return Err(ValidationError::UnsortedOrDuplicateKernel);
}

Ok(())
}
2 changes: 1 addition & 1 deletion base_layer/core/src/validation/block_body/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ async fn it_limits_the_script_byte_size() {
.add_consensus_constants(
ConsensusConstantsBuilder::new(Network::LocalNet)
.with_coinbase_lockheight(0)
.with_max_script_byte_size(0)
.with_max_script_byte_size(2)
.build(),
)
.build();
Expand Down
12 changes: 11 additions & 1 deletion base_layer/core/src/validation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ use tari_crypto::errors::RangeProofError;
use thiserror::Error;
use tokio::task;

#[cfg(feature = "base_node")]
use crate::{
blocks::{BlockHeaderValidationError, BlockValidationError},
chain_storage::ChainStorageError,
covenants::CovenantError,
proof_of_work::{monero_rx::MergeMineError, PowError},
};
use crate::{
covenants::CovenantError,
transactions::{
tari_amount::MicroTari,
transaction_components::{OutputType, TransactionError},
Expand All @@ -39,11 +42,15 @@ use crate::{
#[derive(Debug, Error)]
pub enum ValidationError {
#[error("Block header validation failed: {0}")]
#[cfg(feature = "base_node")]
BlockHeaderError(#[from] BlockHeaderValidationError),
#[error("Block validation error: {0}")]
#[cfg(feature = "base_node")]
BlockError(#[from] BlockValidationError),
#[error("Contains kernels or inputs that are not yet spendable")]
MaturityError,
#[error("The block weight ({actual_weight}) is above the maximum ({max_weight})")]
BlockTooLarge { actual_weight: u64, max_weight: u64 },
#[error("Contains {} unknown inputs", .0.len())]
UnknownInputs(Vec<HashOutput>),
#[error("Contains an unknown input")]
Expand Down Expand Up @@ -78,6 +85,7 @@ pub enum ValidationError {
#[error("Final state validation failed: The UTXO set did not balance with the expected emission at height {0}")]
ChainBalanceValidationFailed(u64),
#[error("Proof of work error: {0}")]
#[cfg(feature = "base_node")]
ProofOfWorkError(#[from] PowError),
#[error("Attempted to validate genesis block")]
ValidatingGenesis,
Expand All @@ -90,6 +98,7 @@ pub enum ValidationError {
#[error("Duplicate or unsorted kernel found in block body")]
UnsortedOrDuplicateKernel,
#[error("Error in merge mine data:{0}")]
#[cfg(feature = "base_node")]
MergeMineError(#[from] MergeMineError),
#[error("Contains an input with an invalid mined-height in body")]
InvalidMinedHeight,
Expand Down Expand Up @@ -151,6 +160,7 @@ pub enum ValidationError {

// ChainStorageError has a ValidationError variant, so to prevent a cyclic dependency we use a string representation in
// for storage errors that cause validation failures.
#[cfg(feature = "base_node")]
impl From<ChainStorageError> for ValidationError {
fn from(err: ChainStorageError) -> Self {
Self::FatalStorageError(err.to_string())
Expand Down
Loading

0 comments on commit e245adc

Please sign in to comment.