Skip to content

Commit 7125156

Browse files
committed
Cleanup
1 parent 9d94734 commit 7125156

File tree

5 files changed

+74
-67
lines changed

5 files changed

+74
-67
lines changed

ledger/block/src/transaction/merkle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl<N: Network> Transaction<N> {
119119
// Prepare the header for the hash.
120120
let header = match deployment.program_checksum() {
121121
None => deployment.program().id().to_bits_le(),
122-
// Note that the checksum must be recomputed since the one stored in the deployment may have been modified.
122+
// Note that the checksum is verified in `VM::check_transaction`.
123123
Some(program_checksum) => program_checksum.to_bits_le(),
124124
};
125125
// Prepare the leaves.

ledger/block/src/transactions/confirmed/mod.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ impl<N: Network> ConfirmedTransaction<N> {
5151
}
5252
};
5353

54-
// Count the number of `InitializeMapping` and `UpdateKeyValue` finalize operations.
55-
let (num_initialize_mappings, num_update_key_values) =
56-
finalize_operations.iter().try_fold((0, 0), |(init, update), operation| match operation {
57-
FinalizeOperation::InitializeMapping(..) => Ok((init + 1, update)),
58-
FinalizeOperation::UpdateKeyValue(..) => Ok((init, update + 1)),
54+
// Count the number of `InitializeMapping` and `*KeyValue` finalize operations.
55+
let (num_initialize_mappings, num_key_values) =
56+
finalize_operations.iter().try_fold((0, 0), |(init, key_value), operation| match operation {
57+
FinalizeOperation::InitializeMapping(..) => Ok((init + 1, key_value)),
58+
FinalizeOperation::InsertKeyValue(..) // At the time of writing, `InsertKeyValue` is only used in tests. However, it is added for completeness, as it is a valid operation.
59+
| FinalizeOperation::RemoveKeyValue(..)
60+
| FinalizeOperation::UpdateKeyValue(..) => Ok((init, key_value + 1)),
5961
op => {
6062
bail!("Transaction '{}' (deploy) contains an invalid finalize operation ({op})", transaction.id())
6163
}
@@ -64,30 +66,29 @@ impl<N: Network> ConfirmedTransaction<N> {
6466
// Perform safety checks on the finalize operations.
6567
{
6668
// Ensure the number of finalize operations matches the number of 'InitializeMapping' and 'UpdateKeyValue' finalize operations.
67-
if num_initialize_mappings + num_update_key_values != finalize_operations.len() {
69+
if num_initialize_mappings + num_key_values != finalize_operations.len() {
6870
bail!(
6971
"Transaction '{}' (deploy) must contain '{}' operations",
7072
transaction.id(),
7173
finalize_operations.len()
7274
);
7375
}
7476
// Ensure the number of program mappings upper bounds the number of 'InitializeMapping' finalize operations.
75-
if num_initialize_mappings > program.mappings().len() {
76-
bail!(
77-
"Transaction '{}' (deploy) must contain at most '{}' 'InitializeMapping' operations (found '{num_initialize_mappings}')",
78-
transaction.id(),
79-
program.mappings().len(),
80-
)
81-
}
82-
// Ensure the number of fee finalize operations lower bounds the number of 'UpdateKeyValue' finalize operations.
83-
// The lower bound is due to the fact that constructors can issue 'UpdateKeyValue' operations as part of the deployment.
84-
if num_update_key_values < fee.num_finalize_operations() {
85-
bail!(
86-
"Transaction '{}' (deploy) must contain at least {} 'UpdateKeyValue' operations (found '{num_update_key_values}')",
87-
transaction.id(),
88-
fee.num_finalize_operations()
89-
);
90-
}
77+
// The upper bound is due to the fact that some mappings may have been initialized in earlier deployments or updates.
78+
ensure!(
79+
num_initialize_mappings <= program.mappings().len(),
80+
"Transaction '{}' (deploy) must contain at most '{}' 'InitializeMapping' operations (found '{num_initialize_mappings}')",
81+
transaction.id(),
82+
program.mappings().len(),
83+
);
84+
// Ensure the number of fee finalize operations lower bounds the number of '*KeyValue' finalize operations.
85+
// The lower bound is due to the fact that constructors can issue '*KeyValue' operations as part of the deployment.
86+
ensure!(
87+
fee.num_finalize_operations() <= num_key_values,
88+
"Transaction '{}' (deploy) must contain at least {} 'UpdateKeyValue' operations (found '{num_key_values}')",
89+
transaction.id(),
90+
fee.num_finalize_operations()
91+
);
9192
}
9293

9394
// Return the accepted deploy transaction.

synthesizer/process/src/stack/deploy.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl<N: Network> Stack<N> {
5151
finish!(timer);
5252

5353
// Return the deployment.
54+
// Note that the checksum is **intentionally** left as `None`. It should be added in `VM::deploy`.
5455
Deployment::new(*self.program_edition, self.program.clone(), verifying_keys, None)
5556
}
5657

@@ -74,6 +75,13 @@ impl<N: Network> Stack<N> {
7475
*self.program_edition == deployment.edition(),
7576
"The stack edition does not match the deployment edition"
7677
);
78+
// If the deployment contains a checksum, ensure it matches the one computed by the stack.
79+
if let Some(program_checksum) = deployment.program_checksum() {
80+
ensure!(
81+
*program_checksum == self.program_checksum,
82+
"The deployment checksum does not match the stack checksum"
83+
);
84+
}
7785

7886
// Check Verifying Keys //
7987

synthesizer/process/src/stack/helpers/check_update.rs

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use super::*;
1818
impl<N: Network> Stack<N> {
1919
/// Checks that the new program definition is a valid update.
2020
#[inline]
21-
pub(crate) fn check_update_is_valid(process: &Process<N>, program: &Program<N>) -> Result<()> {
21+
pub(crate) fn check_update_is_valid(process: &Process<N>, new_program: &Program<N>) -> Result<()> {
2222
// Get the new program ID.
23-
let program_id = program.id();
23+
let program_id = new_program.id();
2424
// Get the old program.
2525
let stack = process.get_stack(program_id)?;
2626
let old_program = stack.program();
@@ -30,79 +30,76 @@ impl<N: Network> Stack<N> {
3030
"Cannot update '{program_id}' because it does not have a constructor"
3131
);
3232
// Ensure the program ID matches.
33-
ensure!(old_program.id() == program.id(), "Cannot update '{program_id}' with different program ID");
33+
ensure!(old_program.id() == new_program.id(), "Cannot update '{program_id}' with different program ID");
3434
// Ensure that all of the structs in the old program exist in the new program.
35-
for (struct_id, struct_type) in old_program.structs() {
36-
let new_struct_type = program.get_struct(struct_id)?;
35+
for (old_struct_id, old_struct_type) in old_program.structs() {
36+
let new_struct_type = new_program.get_struct(old_struct_id)?;
3737
ensure!(
38-
struct_type == new_struct_type,
39-
"Cannot update '{program_id}' because the struct '{struct_id}' does not match"
38+
old_struct_type == new_struct_type,
39+
"Cannot update '{program_id}' because the struct '{old_struct_id}' does not match"
4040
);
4141
}
4242
// Ensure that all of the records in the old program exist in the new program.
43-
for (record_id, record_type) in old_program.records() {
44-
let new_record_type = program.get_record(record_id)?;
43+
for (old_record_id, old_record_type) in old_program.records() {
44+
let new_record_type = new_program.get_record(old_record_id)?;
4545
ensure!(
46-
record_type == new_record_type,
47-
"Cannot update '{program_id}' because the record '{record_id}' does not match"
46+
old_record_type == new_record_type,
47+
"Cannot update '{program_id}' because the record '{old_record_id}' does not match"
4848
);
4949
}
5050
// Ensure that all of the mappings in the old program exist in the new program.
51-
for (mapping_id, mapping_type) in old_program.mappings() {
52-
let new_mapping_type = program.get_mapping(mapping_id)?;
51+
for (old_mapping_id, old_mapping_type) in old_program.mappings() {
52+
let new_mapping_type = new_program.get_mapping(old_mapping_id)?;
5353
ensure!(
54-
*mapping_type == new_mapping_type,
55-
"Cannot update '{program_id}' because the mapping '{mapping_id}' does not match"
54+
*old_mapping_type == new_mapping_type,
55+
"Cannot update '{program_id}' because the mapping '{old_mapping_id}' does not match"
5656
);
5757
}
5858
// Ensure that all of the imports in the old program exist in the new program.
59-
for import in old_program.imports().keys() {
60-
if !program.contains_import(import) {
61-
bail!("Cannot update '{program_id}' because it is missing the original import '{import}'");
59+
for old_import in old_program.imports().keys() {
60+
if !new_program.contains_import(old_import) {
61+
bail!("Cannot update '{program_id}' because it is missing the original import '{old_import}'");
6262
}
6363
}
6464
// Ensure that the constructors in both programs are exactly the same.
6565
ensure!(
66-
old_program.constructor() == program.constructor(),
66+
old_program.constructor() == new_program.constructor(),
6767
"Cannot update '{program_id}' because the constructor does not match"
6868
);
6969
// Ensure that the old program closures exist in the new program, with the exact same definition
70-
for closure in old_program.closures().values() {
71-
let closure_name = closure.name();
72-
let new_closure = program.get_closure(closure_name)?;
70+
for old_closure in old_program.closures().values() {
71+
let old_closure_name = old_closure.name();
72+
let new_closure = new_program.get_closure(old_closure_name)?;
7373
ensure!(
74-
closure == &new_closure,
75-
"Cannot update '{program_id}' because the closure '{closure_name}' does not exactly match"
74+
old_closure == &new_closure,
75+
"Cannot update '{program_id}' because the closure '{old_closure_name}' does not match"
7676
);
7777
}
7878
// Ensure that the old program functions exist in the new program, with the same input and output types.
7979
// If the function has an associated `finalize` block, then ensure that the finalize block exists in the new program.
80-
for function in old_program.functions().values() {
81-
let function_name = function.name();
82-
if !program.contains_function(function.name()) {
83-
bail!("Cannot update '{program_id}' because it is missing the function '{function_name}'");
84-
}
85-
let new_function = program.get_function(function.name())?;
80+
for old_function in old_program.functions().values() {
81+
let old_function_name = old_function.name();
82+
let new_function = new_program.get_function_ref(old_function_name)?;
8683
ensure!(
87-
function.input_types() == new_function.input_types(),
88-
"Cannot update '{program_id}' because the inputs to the function '{function_name}' do not match"
84+
old_function.input_types() == new_function.input_types(),
85+
"Cannot update '{program_id}' because the inputs to the function '{old_function_name}' do not match"
8986
);
9087
ensure!(
91-
function.output_types() == new_function.output_types(),
92-
"Cannot update '{program_id}' because the outputs of the function '{function_name}' do not match"
88+
old_function.output_types() == new_function.output_types(),
89+
"Cannot update '{program_id}' because the outputs of the function '{old_function_name}' do not match"
9390
);
94-
match (function.finalize_logic(), new_function.finalize_logic()) {
91+
match (old_function.finalize_logic(), new_function.finalize_logic()) {
9592
(None, None) => {} // Do nothing
9693
(None, Some(_)) => bail!(
97-
"Cannot update '{program_id}' because the function '{function_name}' should not have a finalize block"
94+
"Cannot update '{program_id}' because the function '{old_function_name}' should not have a finalize block"
9895
),
9996
(Some(_), None) => bail!(
100-
"Cannot update '{program_id}' because the function '{function_name}' should have a finalize block"
97+
"Cannot update '{program_id}' because the function '{old_function_name}' should have a finalize block"
10198
),
102-
(Some(finalize), Some(new_finalize)) => {
99+
(Some(old_finalize), Some(new_finalize)) => {
103100
ensure!(
104-
finalize.input_types() == new_finalize.input_types(),
105-
"Cannot update '{program_id}' because the finalize inputs to the function '{function_name}' do not match"
101+
old_finalize.input_types() == new_finalize.input_types(),
102+
"Cannot update '{program_id}' because the finalize inputs to the function '{old_function_name}' do not match"
106103
);
107104
}
108105
}

synthesizer/src/vm/verify.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
285285
N::TRANSACTION_SPEND_LIMIT
286286
);
287287
// Ensure the fee is sufficient to cover the cost.
288-
ensure!(
289-
cost <= *fee.base_amount()?,
290-
"Transaction '{id}' has an insufficient base fee (execution) - requires {cost} microcredits"
291-
);
288+
if *fee.base_amount()? < cost {
289+
bail!(
290+
"Transaction '{id}' has an insufficient base fee (execution) - requires {cost} microcredits"
291+
)
292+
}
292293
} else {
293294
// Ensure the base fee amount is zero.
294295
ensure!(*fee.base_amount()? == 0, "Transaction '{id}' has a non-zero base fee (execution)");

0 commit comments

Comments
 (0)