Skip to content

Commit

Permalink
Merge pull request #1984 from radixdlt/feature/add-nullification-to-r…
Browse files Browse the repository at this point in the history
…eceipts

Feature/add nullification to receipts
  • Loading branch information
dhedey authored Oct 29, 2024
2 parents 10dd7f0 + c02fb1d commit c3416e7
Show file tree
Hide file tree
Showing 68 changed files with 2,105 additions and 475 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ pub struct FungibleResourceRoles {
}

impl FungibleResourceRoles {
pub fn default_with_owner_mint_burn() -> Self {
Self {
mint_roles: mint_roles! {
minter => OWNER;
minter_updater => rule!(deny_all);
},
burn_roles: burn_roles! {
burner => OWNER;
burner_updater => rule!(deny_all);
},
..Default::default()
}
}

pub fn single_locked_rule(access_rule: AccessRule) -> Self {
Self {
mint_roles: mint_roles! {
Expand Down
4 changes: 2 additions & 2 deletions radix-engine-tests/tests/application/execution_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ fn test_execution_trace_for_transaction_v2() {
.yield_to_parent_with_name_lookup(|lookup| (lookup.bucket("bucket2"),))
})
.sign(&private_key2)
.build(),
.build_minimal(),
)
.intent_header(IntentHeaderV2 {
network_id: NetworkDefinition::simulator().id,
Expand All @@ -668,7 +668,7 @@ fn test_execution_trace_for_transaction_v2() {
})
.sign(&private_key1)
.notarize(&private_key1)
.build()
.build_minimal()
.to_raw()
.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion radix-engine-tests/tests/application/metering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ fn system_loan_should_cover_very_minimal_lock_fee_in_scrypto_component() {
true,
);

let receipt = ledger.execute_notarized_transaction(&main_transaction.to_raw().unwrap());
let receipt = ledger.execute_notarized_transaction(main_transaction);

// Assert and print
receipt.expect_commit_success();
Expand Down
4 changes: 2 additions & 2 deletions radix-engine-tests/tests/application/preview_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn prepare_complex_matching_transaction_and_preview_transaction(
builder
}
})
.build_with_names();
.build();

let mut builder = TransactionBuilder::new_v2()
.transaction_header(TransactionHeaderV2 {
Expand Down Expand Up @@ -262,7 +262,7 @@ fn prepare_complex_matching_transaction_and_preview_transaction(
let transaction = builder
.sign(&transaction_account_key)
.notarize(&notary_key)
.build();
.build_minimal();

(transaction, preview_transaction)
}
2 changes: 1 addition & 1 deletion radix-engine-tests/tests/kernel/transaction_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn create_v2_transaction(
})
.sign(&signer)
.notarize(&notary)
.build()
.build_minimal()
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions radix-engine-tests/tests/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mod metadata_identity;
mod metadata_package;
mod metadata_validator;
mod module;
mod nullification;
mod package;
mod package_schema;
mod proxy;
Expand Down
111 changes: 111 additions & 0 deletions radix-engine-tests/tests/system/nullification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use scrypto_test::prelude::*;

#[test]
fn v2_transaction_intent_gets_nullified_and_cannot_be_replayed() {
// This test is similar to test_transaction_replay_protection, but for v1 transactions

// Arrange
let mut ledger = LedgerSimulatorBuilder::new().build();

// Act
let transaction = ledger
.v2_transaction_builder()
.manifest(ManifestBuilder::new_v2().lock_fee_from_faucet().build())
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&transaction);

let commit_result = receipt.expect_commit_success();
assert_matches!(
&commit_result.performed_nullifications[..],
&[Nullification::Intent { intent_hash, .. }] => {
assert_eq!(intent_hash, transaction.transaction_hashes.transaction_intent_hash.into())
}
);

let duplicate_receipt = ledger.execute_notarized_transaction(&transaction);

// Assert
assert_matches!(
duplicate_receipt.expect_rejection(),
&RejectionReason::IntentHashPreviouslyCommitted
);
}

#[test]
fn v2_subintent_only_gets_nullified_on_success() {
// Arrange
let mut ledger = LedgerSimulatorBuilder::new().build();

// Act
let partial = ledger
.v2_partial_transaction_builder()
.manifest(
ManifestBuilder::new_subintent_v2()
.yield_to_parent(())
.build(),
)
.build();

let failing_transaction = ledger
.v2_transaction_builder()
.add_signed_child("child", partial.clone())
.manifest_builder(
|builder| {
builder
.lock_fee_from_faucet()
.yield_to_child("child", ())
.assert_worktop_contains(XRD, 1)
}, // Fail
)
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&failing_transaction);
let commit_result = receipt.expect_commit_failure();
assert_matches!(
&commit_result.performed_nullifications[..],
&[Nullification::Intent { intent_hash, .. }] => {
assert_eq!(intent_hash, failing_transaction.transaction_hashes.transaction_intent_hash.into())
}
);

let successful_transaction = ledger
.v2_transaction_builder()
.add_signed_child("child", partial.clone())
.manifest_builder(|builder| builder.lock_fee_from_faucet().yield_to_child("child", ()))
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&successful_transaction);
let commit_result = receipt.expect_commit_success();
assert_matches!(
&commit_result.performed_nullifications[..],
&[
Nullification::Intent { intent_hash: intent_hash_1, .. },
Nullification::Intent { intent_hash: intent_hash_2, .. },
] => {
let actually_nullified = indexset!(intent_hash_1, intent_hash_2);
let expected_nullified: IndexSet<IntentHash> = indexset!(
successful_transaction.transaction_hashes.transaction_intent_hash.into(),
partial.root_subintent_hash.into(),
);
assert_eq!(actually_nullified, expected_nullified);
}
);

let another_valid_transaction = ledger
.v2_transaction_builder()
.add_signed_child("child", partial.clone())
.manifest_builder(|builder| builder.lock_fee_from_faucet().yield_to_child("child", ()))
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(another_valid_transaction);

assert_matches!(
receipt.expect_rejection(),
&RejectionReason::IntentHashPreviouslyCommitted
);
}
18 changes: 9 additions & 9 deletions radix-engine-tests/tests/system/subintent_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn subintents_support_depth_of_four() {
let depth_four_child = ledger
.v2_partial_transaction_builder()
.manifest_builder(|builder| builder.yield_to_parent(()))
.build_with_names();
.build();

let depth_three_child = ledger
.v2_partial_transaction_builder()
Expand All @@ -21,7 +21,7 @@ fn subintents_support_depth_of_four() {
.yield_to_child("depth_four_child", ())
.yield_to_parent(())
})
.build_with_names();
.build();

let depth_two_child = ledger
.v2_partial_transaction_builder()
Expand All @@ -31,7 +31,7 @@ fn subintents_support_depth_of_four() {
.yield_to_child("depth_three_child", ())
.yield_to_parent(())
})
.build_with_names();
.build();

// Root transaction intent is depth 1
let transaction = ledger
Expand All @@ -47,7 +47,7 @@ fn subintents_support_depth_of_four() {
.build();

ledger
.execute_notarized_transaction(&transaction.to_raw().unwrap())
.execute_notarized_transaction(transaction)
.expect_commit_success();
}

Expand All @@ -61,7 +61,7 @@ fn subintents_do_not_support_depth_of_five() {
let depth_five_child = ledger
.v2_partial_transaction_builder()
.manifest_builder(|builder| builder.yield_to_parent(()))
.build_with_names();
.build();

let depth_four_child = ledger
.v2_partial_transaction_builder()
Expand All @@ -71,7 +71,7 @@ fn subintents_do_not_support_depth_of_five() {
.yield_to_child("depth_five_child", ())
.yield_to_parent(())
})
.build_with_names();
.build();

let depth_three_child = ledger
.v2_partial_transaction_builder()
Expand All @@ -81,7 +81,7 @@ fn subintents_do_not_support_depth_of_five() {
.yield_to_child("depth_four_child", ())
.yield_to_parent(())
})
.build_with_names();
.build();

let depth_two_child = ledger
.v2_partial_transaction_builder()
Expand All @@ -91,7 +91,7 @@ fn subintents_do_not_support_depth_of_five() {
.yield_to_child("depth_three_child", ())
.yield_to_parent(())
})
.build_with_names();
.build();

let transaction = ledger
.v2_transaction_builder()
Expand All @@ -103,7 +103,7 @@ fn subintents_do_not_support_depth_of_five() {
})
.sign(&account_key)
.notarize(&ledger.default_notary())
.build_no_validate();
.build_minimal_no_validate();

let validation_error = transaction
.prepare_and_validate(ledger.transaction_validator())
Expand Down
14 changes: 8 additions & 6 deletions radix-engine-tests/tests/system/threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn can_transfer_locked_bucket_between_threads() {
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&transaction.to_raw().unwrap());
let receipt = ledger.execute_notarized_transaction(transaction);
receipt.expect_commit_success();
}

Expand Down Expand Up @@ -100,7 +100,7 @@ fn can_pass_global_and_direct_access_references() {
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&transaction.to_raw().unwrap());
let receipt = ledger.execute_notarized_transaction(transaction);
receipt.expect_commit_success();
}

Expand Down Expand Up @@ -136,7 +136,7 @@ fn can_not_pass_address_reservation() {
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&transaction.to_raw().unwrap());
let receipt = ledger.execute_notarized_transaction(transaction);
receipt.expect_specific_failure(|e| {
matches!(e, RuntimeError::SystemError(SystemError::NotAnObject))
});
Expand Down Expand Up @@ -177,7 +177,7 @@ fn can_pass_named_address() {
.notarize(&ledger.default_notary())
.build();

let receipt = ledger.execute_notarized_transaction(&transaction.to_raw().unwrap());
let receipt = ledger.execute_notarized_transaction(transaction);
receipt.expect_commit_success();
}

Expand All @@ -196,7 +196,7 @@ fn can_not_pass_proof_between_threads() {
.manifest_builder(|builder| builder.yield_to_parent(()))
.build(),
)
.manifest_builder_no_validate(|builder| {
.manifest_builder(|builder| {
builder
.lock_fee(account1, 3)
.create_proof_from_account_of_amount(account1, XRD, 10)
Expand All @@ -209,7 +209,9 @@ fn can_not_pass_proof_between_threads() {

// Which fails with a validation error
assert_matches!(
transaction.prepare_and_validate(ledger.transaction_validator()),
transaction
.transaction
.prepare_and_validate(ledger.transaction_validator()),
Err(TransactionValidationError::IntentValidationError(
_,
IntentValidationError::ManifestValidationError(
Expand Down
Loading

0 comments on commit c3416e7

Please sign in to comment.