Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- [FIX][cli] `notes --send` now rejects a recipient address whose network doesn't match the client's configured network, instead of silently sending to it. ([#2525](https://github.com/0xMiden/rust-sdk/pull/2525)).

### Breaking Changes

* [BREAKING][behavior][rust] Notes fetched from the Note Transport Layer are screened when their tag matches a tracked account's tag, discarding the ones no tracked account can consume ([#2474](https://github.com/0xMiden/rust-sdk/pull/2474)).
Expand Down
26 changes: 25 additions & 1 deletion bin/miden-cli/src/commands/notes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,14 @@ async fn send<AUTH: Keystore + Sync>(
let note: Note = note_record
.try_into()
.map_err(|e| CliError::from(ClientError::NoteRecordConversionError(e)))?;
let (_netid, address) = Address::decode(address).map_err(|e| CliError::Input(e.to_string()))?;
let (address_network_id, address) =
Address::decode(address).map_err(|e| CliError::Input(e.to_string()))?;
let client_network_id = client.network_id().await?;
if address_network_id != client_network_id {
return Err(CliError::Input(format!(
"Address network `{address_network_id}` does not match configured network `{client_network_id}`",
)));
}

match block_hint {
Some(block_hint) => {
Expand Down Expand Up @@ -529,6 +536,7 @@ fn note_summary(
mod tests {
use miden_client::Word;
use miden_client::account::AccountId;
use miden_client::address::{Address, NetworkId};
use miden_client::note::{
Note,
NoteAssets,
Expand Down Expand Up @@ -568,4 +576,20 @@ mod tests {
assert_eq!(summary.sender, sender.to_string());
assert_eq!(summary.tag, tag.to_string());
}

/// `notes --send` must reject an address whose network doesn't match the client's configured
/// network. This checks the underlying decode step that the fix relies on: encoding an address
/// for one network and decoding it must not report a match against a different network.
#[test]
fn decoded_address_network_differs_across_networks() {
let account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_PRIVATE_ACCOUNT_UPDATABLE_CODE).unwrap();
let address = Address::new(account_id);

let encoded_for_testnet = address.encode(NetworkId::Testnet);
let (decoded_network_id, _decoded_address) = Address::decode(&encoded_for_testnet).unwrap();

assert_eq!(decoded_network_id, NetworkId::Testnet);
assert_ne!(decoded_network_id, NetworkId::Mainnet);
}
}