Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions ledger/block/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ workspace = true
[dependencies.snarkvm-ledger-puzzle]
workspace = true

[dependencies.snarkvm-synthesizer-error]
workspace = true

[dependencies.snarkvm-synthesizer-program]
workspace = true

Expand Down
93 changes: 60 additions & 33 deletions ledger/block/src/transactions/confirmed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod bytes;
mod serialize;
mod string;

use crate::{Transaction, rejected::Rejected};
use crate::{Transaction, rejected::Rejected, rejected_reason::RejectedReason};
use console::{network::prelude::*, program::FINALIZE_ID_DEPTH, types::Field};
use snarkvm_synthesizer_program::FinalizeOperation;

Expand Down Expand Up @@ -220,6 +220,16 @@ impl<N: Network> ConfirmedTransaction<N> {
pub fn contains_unconfirmed_transaction_id(&self, unconfirmed_transaction_id: &N::TransactionID) -> bool {
self.to_unconfirmed_transaction_id().is_ok_and(|id| &id == unconfirmed_transaction_id)
}

/// Returns the rejected reason, if the confirmed transaction is rejected.
pub fn rejected_reason(&self) -> Option<RejectedReason> {
match self {
Self::AcceptedDeploy(..) | Self::AcceptedExecute(..) => None,
Self::RejectedDeploy(_, _, rejected, _) | Self::RejectedExecute(_, _, rejected, _) => {
rejected.rejected_reason()
}
}
}
}

impl<N: Network> ConfirmedTransaction<N> {
Expand Down Expand Up @@ -409,6 +419,7 @@ pub mod test_helpers {
version: u8,
edition: u16,
is_fee_private: bool,
has_rejected_reason: bool,
rng: &mut TestRng,
) -> ConfirmedTransaction<CurrentNetwork> {
// Sample a fee transaction.
Expand All @@ -418,7 +429,13 @@ pub mod test_helpers {
};

// Extract the rejected deployment.
let rejected = crate::rejected::test_helpers::sample_rejected_deployment(version, edition, is_fee_private, rng);
let rejected = crate::rejected::test_helpers::sample_rejected_deployment(
version,
edition,
is_fee_private,
has_rejected_reason,
rng,
);

// Return the confirmed transaction.
ConfirmedTransaction::rejected_deploy(index, fee_transaction, rejected, vec![]).unwrap()
Expand All @@ -428,6 +445,7 @@ pub mod test_helpers {
pub(crate) fn sample_rejected_execute(
index: u32,
is_fee_private: bool,
has_rejected_reason: bool,
rng: &mut TestRng,
) -> ConfirmedTransaction<CurrentNetwork> {
// Sample a fee transaction.
Expand All @@ -437,7 +455,8 @@ pub mod test_helpers {
};

// Extract the rejected execution.
let rejected = crate::rejected::test_helpers::sample_rejected_execution(is_fee_private, rng);
let rejected =
crate::rejected::test_helpers::sample_rejected_execution(is_fee_private, has_rejected_reason, rng);

// Return the confirmed transaction.
ConfirmedTransaction::rejected_execute(index, fee_transaction, rejected, vec![]).unwrap()
Expand All @@ -454,24 +473,28 @@ pub mod test_helpers {
sample_accepted_deploy(0, 2, Uniform::rand(rng), true, rng),
sample_accepted_execute(1, true, rng),
sample_accepted_execute(1, false, rng),
sample_rejected_deploy(2, 1, Uniform::rand(rng), true, rng),
sample_rejected_deploy(2, 1, Uniform::rand(rng), true, rng),
sample_rejected_deploy(2, 2, Uniform::rand(rng), true, rng),
sample_rejected_deploy(2, 2, Uniform::rand(rng), true, rng),
sample_rejected_execute(3, true, rng),
sample_rejected_execute(3, false, rng),
sample_rejected_deploy(2, 1, Uniform::rand(rng), true, true, rng),
sample_rejected_deploy(2, 1, Uniform::rand(rng), true, false, rng),
sample_rejected_deploy(2, 2, Uniform::rand(rng), true, true, rng),
sample_rejected_deploy(2, 2, Uniform::rand(rng), true, false, rng),
sample_rejected_execute(3, true, true, rng),
sample_rejected_execute(3, true, false, rng),
sample_rejected_execute(3, false, true, rng),
sample_rejected_execute(3, false, false, rng),
sample_accepted_execute(Uniform::rand(rng), true, rng),
sample_accepted_execute(Uniform::rand(rng), false, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, rng),
sample_rejected_execute(Uniform::rand(rng), true, rng),
sample_rejected_execute(Uniform::rand(rng), false, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, true, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, false, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, true, rng),
sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, false, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, true, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, false, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, true, rng),
sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, false, rng),
sample_rejected_execute(Uniform::rand(rng), true, true, rng),
sample_rejected_execute(Uniform::rand(rng), true, false, rng),
sample_rejected_execute(Uniform::rand(rng), false, true, rng),
sample_rejected_execute(Uniform::rand(rng), false, false, rng),
]
}
}
Expand Down Expand Up @@ -549,22 +572,22 @@ mod test {

// Ensure that the unconfirmed transaction ID of a rejected deployment is not equivalent to its confirmed transaction ID.
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, false, rng);
check_contains_unconfirmed_transaction_id(rejected_deploy);
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, false, rng);
check_contains_unconfirmed_transaction_id(rejected_deploy);
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, false, rng);
check_contains_unconfirmed_transaction_id(rejected_deploy);
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, false, rng);
check_contains_unconfirmed_transaction_id(rejected_deploy);

// Ensure that the unconfirmed transaction ID of a rejected execute is not equivalent to its confirmed transaction ID.
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), true, rng);
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), true, false, rng);
check_contains_unconfirmed_transaction_id(rejected_execution);
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), false, rng);
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), false, false, rng);
check_contains_unconfirmed_transaction_id(rejected_execution);
}

Expand Down Expand Up @@ -594,22 +617,22 @@ mod test {

// Ensure that the unconfirmed transaction ID of a rejected deployment is not equivalent to its confirmed transaction ID.
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), true, false, rng);
assert_ne!(rejected_deploy.to_unconfirmed_transaction_id().unwrap(), rejected_deploy.id());
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 1, Uniform::rand(rng), false, false, rng);
assert_ne!(rejected_deploy.to_unconfirmed_transaction_id().unwrap(), rejected_deploy.id());
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), true, false, rng);
assert_ne!(rejected_deploy.to_unconfirmed_transaction_id().unwrap(), rejected_deploy.id());
let rejected_deploy =
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, rng);
test_helpers::sample_rejected_deploy(Uniform::rand(rng), 2, Uniform::rand(rng), false, false, rng);
assert_ne!(rejected_deploy.to_unconfirmed_transaction_id().unwrap(), rejected_deploy.id());

// Ensure that the unconfirmed transaction ID of a rejected execute is not equivalent to its confirmed transaction ID.
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), true, rng);
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), true, false, rng);
assert_ne!(rejected_execution.to_unconfirmed_transaction_id().unwrap(), rejected_execution.id());
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), false, rng);
let rejected_execution = test_helpers::sample_rejected_execute(Uniform::rand(rng), false, false, rng);
assert_ne!(rejected_execution.to_unconfirmed_transaction_id().unwrap(), rejected_execution.id());
}

Expand Down Expand Up @@ -643,6 +666,7 @@ mod test {
let rejected = Rejected::new_deployment(
*deployment_transaction.owner().unwrap(),
deployment_transaction.deployment().unwrap().clone(),
None,
);
let fee = Transaction::from_fee(deployment_transaction.fee_transition().unwrap()).unwrap();
let rejected_deploy = ConfirmedTransaction::rejected_deploy(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand All @@ -654,6 +678,7 @@ mod test {
let rejected = Rejected::new_deployment(
*deployment_transaction.owner().unwrap(),
deployment_transaction.deployment().unwrap().clone(),
None,
);
let fee = Transaction::from_fee(deployment_transaction.fee_transition().unwrap()).unwrap();
let rejected_deploy = ConfirmedTransaction::rejected_deploy(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand All @@ -665,6 +690,7 @@ mod test {
let rejected = Rejected::new_deployment(
*deployment_transaction.owner().unwrap(),
deployment_transaction.deployment().unwrap().clone(),
None,
);
let fee = Transaction::from_fee(deployment_transaction.fee_transition().unwrap()).unwrap();
let rejected_deploy = ConfirmedTransaction::rejected_deploy(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand All @@ -676,6 +702,7 @@ mod test {
let rejected = Rejected::new_deployment(
*deployment_transaction.owner().unwrap(),
deployment_transaction.deployment().unwrap().clone(),
None,
);
let fee = Transaction::from_fee(deployment_transaction.fee_transition().unwrap()).unwrap();
let rejected_deploy = ConfirmedTransaction::rejected_deploy(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand All @@ -685,7 +712,7 @@ mod test {
// Ensure that the unconfirmed transaction of a rejected execute is not equivalent to its confirmed transaction.
let execution_transaction =
crate::transaction::test_helpers::sample_execution_transaction_with_fee(true, rng, 0);
let rejected = Rejected::new_execution(execution_transaction.execution().unwrap().clone());
let rejected = Rejected::new_execution(execution_transaction.execution().unwrap().clone(), None);
let fee = Transaction::from_fee(execution_transaction.fee_transition().unwrap()).unwrap();
let rejected_execute =
ConfirmedTransaction::rejected_execute(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand All @@ -694,7 +721,7 @@ mod test {

let execution_transaction =
crate::transaction::test_helpers::sample_execution_transaction_with_fee(false, rng, 0);
let rejected = Rejected::new_execution(execution_transaction.execution().unwrap().clone());
let rejected = Rejected::new_execution(execution_transaction.execution().unwrap().clone(), None);
let fee = Transaction::from_fee(execution_transaction.fee_transition().unwrap()).unwrap();
let rejected_execute =
ConfirmedTransaction::rejected_execute(Uniform::rand(rng), fee, rejected, vec![]).unwrap();
Expand Down
4 changes: 4 additions & 0 deletions ledger/block/src/transactions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub use confirmed::*;
pub mod rejected;
pub use rejected::*;

pub mod rejected_reason;
pub use rejected_reason::*;

mod bytes;
mod merkle;
mod serialize;
Expand All @@ -41,6 +44,7 @@ use console::{
};
use snarkvm_ledger_committee::Committee;
use snarkvm_ledger_narwhal_batch_header::BatchHeader;
use snarkvm_synthesizer_error::IndexedFinalizeError;
use snarkvm_synthesizer_program::FinalizeOperation;

use indexmap::IndexMap;
Expand Down
46 changes: 41 additions & 5 deletions ledger/block/src/transactions/rejected/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,33 @@ impl<N: Network> FromBytes for Rejected<N> {
// Read the deployment.
let deployment = Deployment::read_le(&mut reader)?;
// Return the rejected deployment.
Ok(Self::new_deployment(program_owner, deployment))
Ok(Self::new_deployment(program_owner, deployment, None))
}
1 => {
// Read the execution.
let execution = Execution::read_le(&mut reader)?;
// Return the rejected execution.
Ok(Self::new_execution(execution))
Ok(Self::new_execution(execution, None))
}
2.. => Err(error(format!("Failed to decode rejected transaction variant {variant}"))),
2 => {
// Read the program owner.
let program_owner = ProgramOwner::read_le(&mut reader)?;
// Read the deployment.
let deployment = Deployment::read_le(&mut reader)?;
// Read the rejected reason.
let rejected_reason = RejectedReason::read_le(&mut reader)?;
// Return the rejected deployment.
Ok(Self::new_deployment(program_owner, deployment, Some(rejected_reason)))
}
3 => {
// Read the execution.
let execution = Execution::read_le(&mut reader)?;
// Read the rejected reason.
let rejected_reason = RejectedReason::read_le(&mut reader)?;
// Return the rejected execution.
Ok(Self::new_execution(execution, Some(rejected_reason)))
}
4.. => Err(error(format!("Failed to decode rejected transaction variant {variant}"))),
}
}
}
Expand All @@ -43,20 +61,38 @@ impl<N: Network> ToBytes for Rejected<N> {
/// Writes the rejected transaction to a buffer.
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
match self {
Self::Deployment(program_owner, deployment) => {
Self::Deployment(program_owner, deployment, None) => {
// Write the variant.
0u8.write_le(&mut writer)?;
// Write the program owner.
program_owner.write_le(&mut writer)?;
// Write the deployment.
deployment.write_le(&mut writer)
}
Self::Execution(execution) => {
Self::Execution(execution, None) => {
// Write the variant.
1u8.write_le(&mut writer)?;
// Write the execution.
execution.write_le(&mut writer)
}
Self::Deployment(program_owner, deployment, Some(rejected_reason)) => {
// Write the variant.
2u8.write_le(&mut writer)?;
// Write the program owner.
program_owner.write_le(&mut writer)?;
// Write the deployment.
deployment.write_le(&mut writer)?;
// Write the rejected reason.
rejected_reason.write_le(&mut writer)
}
Self::Execution(execution, Some(rejected_reason)) => {
// Write the variant.
3u8.write_le(&mut writer)?;
// Write the execution.
execution.write_le(&mut writer)?;
// Write the rejected reason.
rejected_reason.write_le(&mut writer)
}
}
}
}
Expand Down
Loading