Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add opcode versions #4836

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions base_layer/core/src/consensus/consensus_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::{

use chrono::{DateTime, Duration, Utc};
use tari_common::configuration::Network;
use tari_script::script;
use tari_script::{script, OpcodeVersion};
use tari_utilities::epoch_time::EpochTime;

use crate::{
Expand Down Expand Up @@ -101,6 +101,7 @@ pub struct ConsensusConstants {
pub struct OutputVersionRange {
pub outputs: RangeInclusive<TransactionOutputVersion>,
pub features: RangeInclusive<OutputFeaturesVersion>,
pub opcode: RangeInclusive<OpcodeVersion>,
}

/// All V0 for Inputs, Outputs + Features, Kernels
Expand All @@ -114,6 +115,7 @@ fn version_zero() -> (
let output_version_range = OutputVersionRange {
outputs: TransactionOutputVersion::V0..=TransactionOutputVersion::V0,
features: OutputFeaturesVersion::V0..=OutputFeaturesVersion::V0,
opcode: OpcodeVersion::V0..=OpcodeVersion::V0,
};

(input_version_range, output_version_range, kernel_version_range)
Expand Down Expand Up @@ -505,6 +507,11 @@ impl ConsensusConstants {
target_time: 200,
});
let (input_version_range, output_version_range, kernel_version_range) = version_zero();
let output_version_2_range = OutputVersionRange {
outputs: TransactionOutputVersion::V0..=TransactionOutputVersion::V0,
features: OutputFeaturesVersion::V0..=OutputFeaturesVersion::V0,
opcode: OpcodeVersion::V0..=OpcodeVersion::V1,
};
vec![
ConsensusConstants {
effective_from_height: 0,
Expand Down Expand Up @@ -541,12 +548,34 @@ impl ConsensusConstants {
emission_decay: &ESMERALDA_DECAY_PARAMS,
emission_tail: 800 * T,
max_randomx_seed_height: 3000,
proof_of_work: algos.clone(),
faucet_value: (10 * 4000) * T,
transaction_weight: TransactionWeight::v1(),
max_script_byte_size: 2048,
input_version_range: input_version_range.clone(),
output_version_range,
kernel_version_range: kernel_version_range.clone(),
permitted_output_types: Self::current_permitted_output_types(),
},
ConsensusConstants {
effective_from_height: 25000,
coinbase_lock_height: 6,
blockchain_version: 1,
valid_blockchain_version_range: 0..=1,
future_time_limit: 540,
difficulty_block_window: 90,
max_block_transaction_weight: 127_795,
median_timestamp_count: 11,
emission_initial: 18_462_816_327 * uT,
emission_decay: &ESMERALDA_DECAY_PARAMS,
emission_tail: 800 * T,
max_randomx_seed_height: 3000,
proof_of_work: algos,
faucet_value: (10 * 4000) * T,
transaction_weight: TransactionWeight::v1(),
max_script_byte_size: 2048,
input_version_range,
output_version_range,
output_version_range: output_version_2_range,
kernel_version_range,
permitted_output_types: Self::current_permitted_output_types(),
},
Expand Down
3 changes: 3 additions & 0 deletions base_layer/core/src/validation/block_validators/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::{
check_permitted_output_types,
check_sorting_and_duplicates,
check_total_burned,
validate_versions,
},
OrphanValidation,
ValidationError,
Expand Down Expand Up @@ -88,6 +89,8 @@ impl OrphanValidation for OrphanBlockValidator {
trace!(target: LOG_TARGET, "Validating {}", block_id);

let constants = self.rules.consensus_constants(height);
validate_versions(&block.body, constants)?;
trace!(target: LOG_TARGET, "SV - Block body versions are ok for {} ", &block_id);
check_block_weight(block, constants)?;
trace!(target: LOG_TARGET, "SV - Block weight is ok for {} ", &block_id);

Expand Down
72 changes: 72 additions & 0 deletions base_layer/core/src/validation/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,78 @@ pub fn check_permitted_output_types(
Ok(())
}

pub fn validate_versions(
body: &AggregateBody,
consensus_constants: &ConsensusConstants,
) -> Result<(), ValidationError> {
// validate input version
for input in body.inputs() {
if !consensus_constants.input_version_range().contains(&input.version) {
let msg = format!(
"Transaction input contains a version not allowed by consensus ({:?})",
input.version
);
return Err(ValidationError::ConsensusError(msg));
}
}

// validate output version and output features version
for output in body.outputs() {
let valid_output_version = consensus_constants
.output_version_range()
.outputs
.contains(&output.version);

let valid_features_version = consensus_constants
.output_version_range()
.features
.contains(&output.features.version);
if !valid_output_version {
let msg = format!(
"Transaction output version is not allowed by consensus ({:?})",
output.version
);
return Err(ValidationError::ConsensusError(msg));
}

if !valid_features_version {
let msg = format!(
"Transaction output features version is not allowed by consensus ({:?})",
output.features.version
);
return Err(ValidationError::ConsensusError(msg));
}
for opcode in output.script.as_slice() {
if !consensus_constants
.output_version_range()
.opcode
.contains(&opcode.get_version())
{
let msg = format!(
"Transaction output script opcode is not allowed by consensus ({})",
opcode
);
return Err(ValidationError::ConsensusError(msg));
}
}

check_permitted_output_types(consensus_constants, output)?;
}

// validate kernel version
for kernel in body.kernels() {
if !consensus_constants.kernel_version_range().contains(&kernel.version) {
let msg = format!(
"Transaction kernel version is not allowed by consensus ({:?})",
kernel.version
);
return Err(ValidationError::ConsensusError(msg));
}
}

Ok(())
}

#[cfg(test)]
mod test {
use tari_test_utils::unpack_enum;
Expand Down
66 changes: 2 additions & 64 deletions base_layer/core/src/validation/transaction_validators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ use tari_utilities::hex::Hex;

use crate::{
chain_storage::{BlockchainBackend, BlockchainDatabase},
consensus::ConsensusConstants,
transactions::{transaction_components::Transaction, CryptoFactories},
validation::{
helpers::{check_inputs_are_utxos, check_outputs, check_permitted_output_types, check_total_burned},
helpers::{check_inputs_are_utxos, check_outputs, check_total_burned, validate_versions},
MempoolTransactionValidation,
ValidationError,
},
Expand Down Expand Up @@ -98,67 +97,6 @@ impl<B: BlockchainBackend> TxConsensusValidator<B> {
Self { db }
}

fn validate_versions(
&self,
tx: &Transaction,
consensus_constants: &ConsensusConstants,
) -> Result<(), ValidationError> {
// validate input version
for input in tx.body().inputs() {
if !consensus_constants.input_version_range().contains(&input.version) {
let msg = format!(
"Transaction input contains a version not allowed by consensus ({:?})",
input.version
);
return Err(ValidationError::ConsensusError(msg));
}
}

// validate output version and output features version
for output in tx.body().outputs() {
let valid_output_version = consensus_constants
.output_version_range()
.outputs
.contains(&output.version);

let valid_features_version = consensus_constants
.output_version_range()
.features
.contains(&output.features.version);

if !valid_output_version {
let msg = format!(
"Transaction output version is not allowed by consensus ({:?})",
output.version
);
return Err(ValidationError::ConsensusError(msg));
}

if !valid_features_version {
let msg = format!(
"Transaction output features version is not allowed by consensus ({:?})",
output.features.version
);
return Err(ValidationError::ConsensusError(msg));
}

check_permitted_output_types(consensus_constants, output)?;
}

// validate kernel version
for kernel in tx.body().kernels() {
if !consensus_constants.kernel_version_range().contains(&kernel.version) {
let msg = format!(
"Transaction kernel version is not allowed by consensus ({:?})",
kernel.version
);
return Err(ValidationError::ConsensusError(msg));
}
}

Ok(())
}

fn validate_excess_sig_not_in_db(&self, tx: &Transaction) -> Result<(), ValidationError> {
for kernel in tx.body.kernels() {
if let Some((db_kernel, header_hash)) = self.db.fetch_kernel_by_excess_sig(kernel.excess_sig.to_owned())? {
Expand Down Expand Up @@ -191,7 +129,7 @@ impl<B: BlockchainBackend> MempoolTransactionValidation for TxConsensusValidator

self.validate_excess_sig_not_in_db(tx)?;

self.validate_versions(tx, consensus_constants)
validate_versions(tx.body(), consensus_constants)
}
}

Expand Down
6 changes: 2 additions & 4 deletions base_layer/core/tests/helpers/block_malleability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,11 @@ fn check_block_changes_are_detected(field: MerkleMountainRangeField, block_mod_f

let (_, output) = blockchain.add_block(blocks.new_block("A1").child_of("GB").difficulty(1));

// we need to use input version V2 to include the "version" into the input hash
// and also the output version V2 to include the "sender_offset_public_key" into the output hash
let (txs, _) = schema_to_transaction(&[txn_schema!(
from: vec![output],
to: vec![50 * T],
input_version: TransactionInputVersion::V1,
output_version: TransactionOutputVersion::V1
input_version: TransactionInputVersion::V0,
output_version: TransactionOutputVersion::V0
)]);
blockchain.add_block(
blocks
Expand Down
2 changes: 1 addition & 1 deletion infrastructure/tari_script/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mod serde;
mod stack;

pub use error::ScriptError;
pub use op_codes::{slice_to_boxed_hash, slice_to_hash, HashValue, Message, Opcode, ScalarValue};
pub use op_codes::{slice_to_boxed_hash, slice_to_hash, HashValue, Message, Opcode, OpcodeVersion, ScalarValue};
pub use script::TariScript;
pub use script_commitment::{ScriptCommitment, ScriptCommitmentError, ScriptCommitmentFactory};
pub use script_context::ScriptContext;
Expand Down
Loading