Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Factor out note scripts #880

Merged
merged 4 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 0.6.0 (TBD)

- Made note scripts public (#880).
- Implemented serialization for `TransactionWitness`, `ChainMmr`, `TransactionInputs` and `TransactionArgs` (#888).
- [BREAKING] Renamed the `TransactionProver` struct to `LocalTransactionProver` and added the `TransactionProver` trait (#865).
- Implemented `Display`, `TryFrom<&str>` and `FromStr` for `AccountStorageMode` (#861).
Expand Down
58 changes: 6 additions & 52 deletions miden-lib/src/notes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use miden_objects::{
crypto::rand::FeltRng,
notes::{
Note, NoteAssets, NoteDetails, NoteExecutionHint, NoteExecutionMode, NoteInputs,
NoteMetadata, NoteRecipient, NoteScript, NoteTag, NoteType,
NoteMetadata, NoteRecipient, NoteTag, NoteType,
},
utils::Deserializable,
vm::Program,
Felt, NoteError, Word,
};
use utils::build_swap_tag;

pub mod scripts;
pub mod utils;

// STANDARDIZED SCRIPTS
Expand All @@ -36,10 +36,7 @@ pub fn create_p2id_note<R: FeltRng>(
aux: Felt,
rng: &mut R,
) -> Result<Note, NoteError> {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/P2ID.masb"));
let program =
Program::read_from_bytes(bytes).map_err(NoteError::NoteScriptDeserializationError)?;
let note_script = NoteScript::new(program);
let note_script = scripts::p2id();

let inputs = NoteInputs::new(vec![target.into()])?;
let tag = NoteTag::from_account_id(target, NoteExecutionMode::Local)?;
Expand Down Expand Up @@ -72,10 +69,7 @@ pub fn create_p2idr_note<R: FeltRng>(
recall_height: u32,
rng: &mut R,
) -> Result<Note, NoteError> {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/P2IDR.masb"));
let program =
Program::read_from_bytes(bytes).map_err(NoteError::NoteScriptDeserializationError)?;
let note_script = NoteScript::new(program);
let note_script = scripts::p2idr();

let inputs = NoteInputs::new(vec![target.into(), recall_height.into()])?;
let tag = NoteTag::from_account_id(target, NoteExecutionMode::Local)?;
Expand Down Expand Up @@ -104,10 +98,7 @@ pub fn create_swap_note<R: FeltRng>(
aux: Felt,
rng: &mut R,
) -> Result<(Note, NoteDetails), NoteError> {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/SWAP.masb"));
let program =
Program::read_from_bytes(bytes).map_err(NoteError::NoteScriptDeserializationError)?;
let note_script = NoteScript::new(program);
let note_script = scripts::swap();

let payback_serial_num = rng.draw_word();
let payback_recipient = utils::build_p2id_recipient(sender, payback_serial_num)?;
Expand Down Expand Up @@ -145,40 +136,3 @@ pub fn create_swap_note<R: FeltRng>(

Ok((note, payback_note))
}

// HELPER FUNCTIONS
// ================================================================================================

/// Returns a note tag for a swap note with the specified parameters.
///
/// Use case ID for the returned tag is set to 0.
///
/// Tag payload is constructed by taking asset tags (8 bits of faucet ID) and concatenating them
/// together as offered_asset_tag + requested_asset tag.
///
/// Network execution hint for the returned tag is set to `Local`.
pub fn build_swap_tag(
note_type: NoteType,
offered_asset: &Asset,
requested_asset: &Asset,
) -> Result<NoteTag, NoteError> {
const SWAP_USE_CASE_ID: u16 = 0;

// get bits 4..12 from faucet IDs of both assets, these bits will form the tag payload; the
// reason we skip the 4 most significant bits is that these encode metadata of underlying
// faucets and are likely to be the same for many different faucets.

let offered_asset_id: u64 = offered_asset.faucet_id().into();
let offered_asset_tag = (offered_asset_id >> 52) as u8;

let requested_asset_id: u64 = requested_asset.faucet_id().into();
let requested_asset_tag = (requested_asset_id >> 52) as u8;

let payload = ((offered_asset_tag as u16) << 8) | (requested_asset_tag as u16);

let execution = NoteExecutionMode::Local;
match note_type {
NoteType::Public => NoteTag::for_public_use_case(SWAP_USE_CASE_ID, payload, execution),
_ => NoteTag::for_local_use_case(SWAP_USE_CASE_ID, payload),
}
}
25 changes: 25 additions & 0 deletions miden-lib/src/notes/scripts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use miden_objects::{notes::NoteScript, utils::Deserializable, vm::Program};

/// Returns a P2ID (Pay-to-ID) note script.
pub fn p2id() -> NoteScript {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/P2ID.masb"));
let program = Program::read_from_bytes(bytes).expect("Shipped P2ID script is well-formed");

NoteScript::new(program)
}

/// Returns a P2IDR (Pay-to-ID with recall) note script.
pub fn p2idr() -> NoteScript {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/P2IDR.masb"));
let program = Program::read_from_bytes(bytes).expect("Shipped P2IDR script is well-formed");

NoteScript::new(program)
}

/// Returns a SWAP (Pay-to-ID with recall) note script.
pub fn swap() -> NoteScript {
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/SWAP.masb"));
let program = Program::read_from_bytes(bytes).expect("Shipped SWAP script is well-formed");

NoteScript::new(program)
}
37 changes: 36 additions & 1 deletion miden-lib/src/notes/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use miden_objects::{
accounts::AccountId,
notes::{NoteInputs, NoteRecipient, NoteScript},
assets::Asset,
notes::{NoteExecutionMode, NoteInputs, NoteRecipient, NoteScript, NoteTag, NoteType},
utils::Deserializable,
vm::Program,
NoteError, Word,
Expand All @@ -22,3 +23,37 @@ pub fn build_p2id_recipient(

Ok(NoteRecipient::new(serial_num, note_script, note_inputs))
}

/// Returns a note tag for a swap note with the specified parameters.
///
/// Use case ID for the returned tag is set to 0.
///
/// Tag payload is constructed by taking asset tags (8 bits of faucet ID) and concatenating them
/// together as offered_asset_tag + requested_asset tag.
///
/// Network execution hint for the returned tag is set to `Local`.
pub fn build_swap_tag(
note_type: NoteType,
offered_asset: &Asset,
requested_asset: &Asset,
) -> Result<NoteTag, NoteError> {
const SWAP_USE_CASE_ID: u16 = 0;

// get bits 4..12 from faucet IDs of both assets, these bits will form the tag payload; the
// reason we skip the 4 most significant bits is that these encode metadata of underlying
// faucets and are likely to be the same for many different faucets.

let offered_asset_id: u64 = offered_asset.faucet_id().into();
let offered_asset_tag = (offered_asset_id >> 52) as u8;

let requested_asset_id: u64 = requested_asset.faucet_id().into();
let requested_asset_tag = (requested_asset_id >> 52) as u8;

let payload = ((offered_asset_tag as u16) << 8) | (requested_asset_tag as u16);

let execution = NoteExecutionMode::Local;
match note_type {
NoteType::Public => NoteTag::for_public_use_case(SWAP_USE_CASE_ID, payload, execution),
_ => NoteTag::for_local_use_case(SWAP_USE_CASE_ID, payload),
}
}
Loading