Skip to content

Commit

Permalink
Allow increasing an account's nonce without changing its state (#796)
Browse files Browse the repository at this point in the history
* refactor: remove nonce increase restriction

* test: add nonce update with empty delta test

* refactor: update tx script, update comment
  • Loading branch information
Fumuran authored Jul 18, 2024
1 parent 19df86c commit dd5b7b9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [BREAKING] Renamed public accessors of the `Block` struct to match the updated fields (#791).
- [BREAKING] Changed the `TransactionArgs` to use `AdviceInputs` (#793).
- Setters in `memory` module don't drop the setting `Word` anymore (#795).
- [BREAKING] Increase of nonce does not require changes in account state any more (#789).

## 0.4.0 (2024-07-03)

Expand Down
60 changes: 60 additions & 0 deletions miden-tx/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,66 @@ fn executed_transaction_account_delta() {
);
}

#[test]
fn test_empty_delta_nonce_update() {
let tx_context = TransactionContextBuilder::with_standard_account(
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN,
ONE,
)
.build();

let mut executor: TransactionExecutor<_, ()> =
TransactionExecutor::new(tx_context.clone(), None);
let account_id = tx_context.tx_inputs().account().id();
executor.load_account(account_id).unwrap();

let tx_script = format!(
"\
begin
push.1
call.{ACCOUNT_INCR_NONCE_MAST_ROOT}
# => [0, 1]
drop drop
# => []
end
"
);
let tx_script_code = ProgramAst::parse(&tx_script).unwrap();
let tx_script = executor.compile_tx_script(tx_script_code, vec![], vec![]).unwrap();
let tx_args = TransactionArgs::new(
Some(tx_script),
None,
tx_context.tx_args().advice_inputs().clone().map,
);

let block_ref = tx_context.tx_inputs().block_header().block_num();
let note_ids = tx_context
.tx_inputs()
.input_notes()
.iter()
.map(|note| note.id())
.collect::<Vec<_>>();

// expected delta
// --------------------------------------------------------------------------------------------
// execute the transaction and get the witness
let executed_transaction =
executor.execute_transaction(account_id, block_ref, &note_ids, tx_args).unwrap();

// nonce delta
// --------------------------------------------------------------------------------------------
assert_eq!(executed_transaction.account_delta().nonce(), Some(Felt::new(2)));

// storage delta
// --------------------------------------------------------------------------------------------
// We expect one updated item and one updated map
assert_eq!(executed_transaction.account_delta().storage().updated_items.len(), 0);

assert_eq!(executed_transaction.account_delta().storage().updated_maps.len(), 0);
}

#[test]
fn executed_transaction_output_notes() {
let tx_context = TransactionContextBuilder::with_standard_account(
Expand Down
10 changes: 2 additions & 8 deletions objects/src/accounts/delta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ impl AccountDelta {
/// # Errors
/// Returns an error if:
/// - Storage or vault deltas are invalid.
/// - Storage and vault deltas are empty, and the nonce was updated.
/// - Storage or vault deltas are not empty, but nonce was not updated.
pub fn new(
storage: AccountStorageDelta,
Expand All @@ -52,7 +51,7 @@ impl AccountDelta {
storage.validate()?;
vault.validate()?;

// nonce must be updated if and only if either account storage or vault were updated
// nonce must be updated if either account storage or vault were updated
validate_nonce(nonce, &storage, &vault)?;

Ok(Self { storage, vault, nonce })
Expand Down Expand Up @@ -169,7 +168,6 @@ impl Deserializable for AccountUpdateDetails {
/// # Errors
/// Returns an error if:
/// - Storage or vault were updated, but the nonce was either not updated or set to 0.
/// - Storage and vault were not updated, but the nonce was updated.
fn validate_nonce(
nonce: Option<Felt>,
storage: &AccountStorageDelta,
Expand All @@ -190,10 +188,6 @@ fn validate_nonce(
))
},
}
} else if nonce.is_some() {
return Err(AccountDeltaError::InconsistentNonceUpdate(
"nonce updated for empty delta".to_string(),
));
}

Ok(())
Expand Down Expand Up @@ -222,7 +216,7 @@ mod tests {
};

assert!(AccountDelta::new(storage_delta.clone(), vault_delta.clone(), None).is_ok());
assert!(AccountDelta::new(storage_delta.clone(), vault_delta.clone(), Some(ONE)).is_err());
assert!(AccountDelta::new(storage_delta.clone(), vault_delta.clone(), Some(ONE)).is_ok());

// non-empty delta
let storage_delta = AccountStorageDelta {
Expand Down
1 change: 0 additions & 1 deletion objects/src/accounts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,6 @@ mod tests {
}

#[test]
#[should_panic]
fn empty_account_delta_with_incremented_nonce() {
// build account
let init_nonce = Felt::new(1);
Expand Down

0 comments on commit dd5b7b9

Please sign in to comment.