Skip to content

Transaction script compilation support#625

Merged
bitwalker merged 24 commits intonextfrom
greenhat/i622-tx-script-compilation
Aug 15, 2025
Merged

Transaction script compilation support#625
bitwalker merged 24 commits intonextfrom
greenhat/i622-tx-script-compilation

Conversation

@greenhat
Copy link
Copy Markdown
Contributor

@greenhat greenhat commented Jul 31, 2025

Close #618
Close #621
Close #622

Corresponding templates repo PR - 0xMiden/rust-templates#18

This PR introduces transaction script compilation support.

Key Changes

  • Added the cargo miden new --tx-script option to generate a tx script project;
  • Added project-kind under [package.metadata.miden] in Cargo.toml to identify project kind (account, note script, tx script);
  • Renamed both note script and tx script entrypoint function to be run;
  • Added the arg: Word parameter to both note and tx scripts entrypoint functions;
  • Added missing tx kernel bindings and changed existing ones where MASM signature changed;
  • Finished the test_basic_wallet_p2id_local test against the local node instance with the scenario Faucet -> Alice -> Bob asset movement.
  • Added basic-wallet-tx-script to cargo miden example command;

See basic-walled-tx-script at

struct BasicWalletTxScript;
// Input layout constants
const TAG_INDEX: usize = 0;
const AUX_INDEX: usize = 1;
const NOTE_TYPE_INDEX: usize = 2;
const EXECUTION_HINT_INDEX: usize = 3;
const RECIPIENT_START: usize = 4;
const RECIPIENT_END: usize = 8;
const ASSET_START: usize = 8;
const ASSET_END: usize = 12;
impl Guest for BasicWalletTxScript {
fn run(arg: Word) {
let num_felts = adv_push_mapvaln(arg.clone());
let num_felts_u64 = num_felts.as_u64();
assert_eq(Felt::from_u32((num_felts_u64 % 4) as u32), felt!(0));
let num_words = Felt::from_u64_unchecked(num_felts_u64 / 4);
let commitment = arg;
let input = adv_load_preimage(num_words, commitment);
let tag = input[TAG_INDEX];
let aux = input[AUX_INDEX];
let note_type = input[NOTE_TYPE_INDEX];
let execution_hint = input[EXECUTION_HINT_INDEX];
let recipient: [Felt; 4] = input[RECIPIENT_START..RECIPIENT_END].try_into().unwrap();
let note_idx = miden::tx::create_note(
tag.into(),
aux,
note_type.into(),
execution_hint,
recipient.into(),
);
let asset: [Felt; 4] = input[ASSET_START..ASSET_END].try_into().unwrap();
basic_wallet::move_asset_to_note(asset.into(), note_idx);
}
}

And the offchain code that calls it at

let tx_script_program = tx_script_package.unwrap_program();
let tx_script = TransactionScript::from_parts(
tx_script_program.mast_forest().clone(),
tx_script_program.entrypoint(),
);
// Prepare note recipient
let program_hash = tx_script_program.hash();
let serial_num = RpoRandomCoin::new(program_hash.into()).draw_word();
let inputs = NoteInputs::new(vec![
recipient_account_id.prefix().as_felt(),
recipient_account_id.suffix(),
])
.unwrap();
let note_recipient = NoteRecipient::new(serial_num, p2id_note.script().clone(), inputs);
// Prepare commitment data
let mut input: Vec<Felt> = vec![
config.tag.into(),
config.aux,
config.note_type.into(),
config.execution_hint.into(),
];
let recipient_digest: [Felt; 4] = note_recipient.digest().into();
input.extend(recipient_digest);
let asset_arr: [Felt; 4] = asset.into();
input.extend(asset_arr);
let mut commitment: [Felt; 4] = miden_core::crypto::hash::Rpo256::hash_elements(&input).into();
assert_eq!(input.len() % 4, 0, "input needs to be word-aligned");
// Prepare advice map
let mut advice_map = std::collections::BTreeMap::new();
advice_map.insert(commitment.into(), input.clone());
let recipients = vec![note_recipient.clone()];
// NOTE: passed on the stack reversed
commitment.reverse();
let tx_request = TransactionRequestBuilder::new()
.custom_script(tx_script)
.script_arg(commitment)
.expected_output_recipients(recipients)
.extend_advice_map(advice_map)
.build()
.unwrap();

The updated basic-wallet Rust code is at

#[component]
struct MyAccount;
impl basic_wallet::Guest for MyAccount {
fn receive_asset(asset: Asset) {
miden::account::add_asset(asset);
}
/// Moves an asset from the account to a note.
///
/// This function removes the specified asset from the account and adds it to
/// the note identified by the given index.
///
/// # Arguments
/// * `asset` - The asset to move from the account to the note
/// * `note_idx` - The index of the note to receive the asset
fn move_asset_to_note(asset: Asset, note_idx: NoteIdx) {
let asset = miden::account::remove_asset(asset);
miden::tx::add_asset_to_note(asset, note_idx);
}
}

@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch 2 times, most recently from 523e9d0 to a368353 Compare August 1, 2025 14:13
@greenhat greenhat changed the base branch from greenhat/i544-run-basic-wallet-testnet to greenhat/i626-advice-map-sdk August 1, 2025 14:13
@greenhat greenhat force-pushed the greenhat/i626-advice-map-sdk branch from b230f2d to 4815892 Compare August 6, 2025 03:51
@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch from 3ee8160 to e6a7e82 Compare August 6, 2025 05:41
@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch from e6a7e82 to 851770a Compare August 7, 2025 13:51
@greenhat greenhat changed the base branch from greenhat/i626-advice-map-sdk to greenhat/data-segments-word-align August 7, 2025 13:52
@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch 3 times, most recently from d350d3a to 56b69d6 Compare August 8, 2025 09:03
Copy link
Copy Markdown
Collaborator

@bitwalker bitwalker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is still in draft status, but figured I'd take a pass through early. No notes, aside from one about how we name the entrypoint for note and transaction scripts, but it isn't necessarily a blocker, just something that sticks out to me now.

@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch from aa73a28 to e6807e5 Compare August 11, 2025 11:19
Base automatically changed from greenhat/data-segments-word-align to next August 11, 2025 13:09
@greenhat greenhat force-pushed the greenhat/i622-tx-script-compilation branch from 5872ba2 to fb81ad5 Compare August 11, 2025 14:02
@greenhat greenhat marked this pull request as ready for review August 11, 2025 14:24
@greenhat
Copy link
Copy Markdown
Contributor Author

@bitwalker It's ready for review.

@bitwalker bitwalker merged commit c614530 into next Aug 15, 2025
12 checks passed
@bitwalker bitwalker deleted the greenhat/i622-tx-script-compilation branch August 15, 2025 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants