miden-testing 0.15.1

Miden protocol testing tools
Documentation
//! Tests for the `miden::standards::attachments::network_account_target` module.

use miden_protocol::Felt;
use miden_protocol::account::AccountType;
use miden_protocol::note::NoteAttachment;
use miden_protocol::testing::account_id::AccountIdBuilder;
use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};

use crate::executor::CodeExecutor;

#[tokio::test]
async fn network_account_target_into_target_id() -> anyhow::Result<()> {
    let target_id = AccountIdBuilder::new()
        .account_type(AccountType::Public)
        .build_with_rng(&mut rand::rng());
    let exec_hint = NoteExecutionHint::Always;

    let attachment = NoteAttachment::from(NetworkAccountTarget::new(target_id, exec_hint)?);

    let source = format!(
        r#"
        use miden::standards::attachments::network_account_target
        use miden::protocol::note

        begin
            push.{attachment_scheme}
            # => [attachment_scheme]
            exec.network_account_target::is_network_account_target
            # => [is_valid]
            assert.err="expected scheme to be a valid network account target"

            push.{attachment_word}
            # => [NOTE_ATTACHMENT]
            exec.network_account_target::into_target_id
            # => [account_id_suffix, account_id_prefix]
            # cleanup stack
            movup.2 drop movup.2 drop
        end
        "#,
        attachment_scheme = attachment.attachment_scheme().as_u16(),
        attachment_word = attachment.content().as_words()[0],
    );

    let exec_output = CodeExecutor::with_default_host().run(&source).await?;

    assert_eq!(exec_output.stack[0], target_id.suffix());
    assert_eq!(exec_output.stack[1], target_id.prefix().as_felt());

    Ok(())
}

#[tokio::test]
async fn network_account_target_new_attachment() -> anyhow::Result<()> {
    let target_id = AccountIdBuilder::new()
        .account_type(AccountType::Public)
        .build_with_rng(&mut rand::rng());
    let exec_hint = NoteExecutionHint::Always;

    let attachment = NoteAttachment::from(NetworkAccountTarget::new(target_id, exec_hint)?);
    let raw_attachment_word = attachment.content().as_words()[0];

    let source = format!(
        r#"
        use miden::standards::attachments::network_account_target

        begin
            push.{exec_hint}
            push.{target_id_prefix}
            push.{target_id_suffix}
            # => [target_id_suffix, target_id_prefix, exec_hint]
            exec.network_account_target::new
            # => [attachment_scheme, NOTE_ATTACHMENT, pad(16)]

            # cleanup stack
            swapdw dropw dropw
        end
        "#,
        target_id_prefix = target_id.prefix().as_felt(),
        target_id_suffix = target_id.suffix(),
        exec_hint = Felt::from(exec_hint),
    );

    let exec_output = CodeExecutor::with_default_host().run(&source).await?;

    assert_eq!(
        exec_output.stack[0],
        Felt::from(NetworkAccountTarget::ATTACHMENT_SCHEME.as_u16())
    );

    let word = exec_output.stack.get_word(1).unwrap();
    assert_eq!(word, raw_attachment_word);

    Ok(())
}

#[tokio::test]
async fn network_account_target_attachment_round_trip() -> anyhow::Result<()> {
    let target_id = AccountIdBuilder::new()
        .account_type(AccountType::Public)
        .build_with_rng(&mut rand::rng());
    let exec_hint = NoteExecutionHint::Always;

    let source = format!(
        r#"
        use miden::standards::attachments::network_account_target

        const ERR_NOT_NETWORK_ACCOUNT_TARGET = "attachment is not a valid network account target"

        begin
            push.{exec_hint}
            push.{target_id_prefix}
            push.{target_id_suffix}
            # => [target_id_suffix, target_id_prefix, exec_hint]
            exec.network_account_target::new
            # => [attachment_scheme, NOTE_ATTACHMENT]
            exec.network_account_target::is_network_account_target
            # => [is_valid, NOTE_ATTACHMENT]
            assert.err=ERR_NOT_NETWORK_ACCOUNT_TARGET
            # => [NOTE_ATTACHMENT]
            exec.network_account_target::into_target_id
            # => [target_id_suffix, target_id_prefix]
            # cleanup stack
            movup.2 drop movup.2 drop
        end
        "#,
        target_id_prefix = target_id.prefix().as_felt(),
        target_id_suffix = target_id.suffix(),
        exec_hint = Felt::from(exec_hint),
    );

    let exec_output = CodeExecutor::with_default_host().run(&source).await?;

    assert_eq!(exec_output.stack[0], target_id.suffix());
    assert_eq!(exec_output.stack[1], target_id.prefix().as_felt());

    Ok(())
}