Wrong masm file shown on certain kinds of errors (missing import, possibly other)
- 主要語言
- Rust
- 星號
- 772
- 分支
- 352
- 平均合併
- 1 天 12 小時
- 30 天內合併 PR
- 93
描述
### Packages versions
miden-assembly: 0.20.6
### Bug description
Issue: When compiling library code with missing imports, MASM file name and contents will be replaced with `account_id.masm` and it's contents respectively.
Example: Code missing `miden::protocol::active_account` import while calling `exec.active_account::get_item` will yield:
```
Error: Failed to compile lp_local library: x undefined symbol reference
,-[/Users/mieszkomanijak/Documents/repos/miden/c-prod_pools/target/release/build/miden-protocol-f93a66620a2cffdd/out/asm/shared_modules/account_id.masm:68:11]
67 | #! Inputs: [acct_id_prefix]
68 | #! Outputs: [is_non_fungible_faucet]
: ^^^^^^^^^^^^|^^^^^^^^^^^
: `-- this symbol path could not be resolved
69 | #!
`----
help: maybe you are missing an import?
```
### How can this be reproduced?
Offending code from `asm/accounts/lp_local.masm` trying to call `exec.active_account::get_item` in l 88
```
use miden::core::math::u64
use miden::protocol::native_account
#use miden::protocol::active_account
use miden::core::sys
use zoro::math
use zoro::storage_utils
const MINIMUM_LIQUIDITY = 100
### MEMORY LOCATIONS
const DYNAMIC_PROC_ADDR = 4
const USER_ACCOUNT_ID_WORD = 20
const USER_ACCOUNT_ID_PREFIX = 20
const USER_ACCOUNT_ID_SUFFIX = 21
### ERROR CODES
const ERR_ZERO_ADDRESS = "Zero address"
### STORAGE SLOTS
const USER_DEPOSITS_MAPPING_SLOT = word("zoro::lp_local::user_deposits_mapping")
const RESERVE_SLOT = word("zoro::lp_local::reserve")
const TOTAL_SUPPLY_SLOT = word("zoro::lp_local::total_supply")
#################
#! Computes the LP amount out for a deposit of amount_0 and amount_1.
#! For initial deposit (the total supply is 0), it subracts the minimum liquidity.
#! Inputs: [total_supply, amount_0, amount_1, reserve_0, reserve_1]
#! Outputs: [lp_amount_out]
@locals(5)
pub proc get_lp_amount_out(total_supply: felt, amount_0: felt, amount_1: felt, reserve_0: felt, reserve_1: felt) -> felt
# loc.0: total_supply
# loc.1: amount_0
# loc.2: amount_1
# loc.3: reserve_0
# loc.4: reserve_1
loc_store.0 loc_store.1 loc_store.2 loc_store.3 loc_store.4
# => []
### if total_supply == 0
loc_load.0 eq.0
if.true
### initial deposit: - MINIMUM_LIQUIDITY
loc_load.1 loc_load.2 mul exec.math::sqrt
# => [lp_amount]
push.MINIMUM_LIQUIDITY exec.math::safe_sub
# => [lp_amount_out]
### return lp_amount_out
else
### subsequent deposits: min(lp_amount_0, lp_amount_1)
### lp_amount_0 = amount_0 * total_supply / reserve_0
loc_load.1 u32split loc_load.0 u32split exec.u64::wrapping_mul loc_load.3 u32split exec.u64::div
# => [lp_amount_0_high, lp_amount_0_low]
loc_load.2 u32split loc_load.0 u32split exec.u64::wrapping_mul loc_load.4 u32split exec.u64::div
# => [lp_amount_1_high, lp_amount_1_low, lp_amount_0_high, lp_amount_0_low]
exec.u64::min
# => [lp_amount_out_high, lp_amount_out_low]
exec.math::safe_cast_u64_into_felt
# => [lp_amount_out]
### return lp_amount_out
end
exec.sys::truncate_stack
end
proc assert_non_zero_address#(suffix: felt, prefix: felt)
neq.0 swap.1 neq.0
# => [is_suffix_non_zero, is_prefix_non_zero]
or assert.err=ERR_ZERO_ADDRESS
end
proc get_current_user_deposit_key#() -> Word
mem_load.USER_ACCOUNT_ID_SUFFIX mem_load.USER_ACCOUNT_ID_PREFIX
exec.assert_non_zero_address
mem_load.USER_ACCOUNT_ID_SUFFIX mem_load.USER_ACCOUNT_ID_PREFIX
# => [USER_DEPOSIT_KEY]
exec.get_user_deposit_key
exec.sys::truncate_stack
end
proc get_user_deposit_key#(prefix: felt, suffix: felt) -> Word
push.0.0 movup.3 movup.2
# => [prefix, suffix, 0 , 0 ] == [KEY]
end
pub proc total_supply#() -> felt
push.TOTAL_SUPPLY_SLOT[0..2] exec.active_account::get_item
end
pub proc get_reserve#() -> (felt, felt)
push.RESERVE_SLOT[0..2] exec.active_account::get_item
end
proc set_reserve#(reserve_0: felt, reserve_1: felt)
### amount validation vs vault
push.RESERVE_SLOT[0..2] exec.native_account::set_item
dropw
end
@locals(2)
proc add_to_reserve#(amount_0: felt, amount_1: felt)
# loc.0: amount_0
# loc.1: amount_1
loc_store.0 loc_store.1
# => []
exec.get_reserve
# => [reserve_0, reserve_1]
loc_load.0 exec.math::safe_add
# => [new_reserve_0, reserve_1]
swap
loc_load.1 exec.math::safe_add
# => [new_reserve_1, new_reserve_0]
swap
# => [new_reserve_0, new_reserve_1]
exec.set_reserve
end
@locals(2)
proc sub_from_reserve#(amount_0: felt, amount_1: felt)
# loc.0: amount_0
# loc.1: amount_1
loc_store.0 loc_store.1
# => []
exec.get_reserve
# => [reserve_0, reserve_1]
loc_load.0 exec.math::safe_sub
# => [new_reserve_0, reserve_1]
swap
loc_load.1 exec.math::safe_sub
# => [new_reserve_1, new_reserve_0]
swap
# => [new_reserve_0, new_reserve_1]
exec.set_reserve
end
@locals(3)
proc mint#(amount: felt, beneficiary_prefix: felt, beneficiary_suffix: felt)
# loc.0: amount
# loc.1: beneficiary_prefix
# loc.2: beneficiary_suffix
loc_store.0 loc_store.1 loc_store.2
# => []
### add to mapping USER_DEPOSITS_MAPPING_SLOT
loc_load.0
loc_load.2 loc_load.1 exec.get_user_deposit_key
# => [USER_DEPOSIT_KEY, amount]
push.USER_DEPOSITS_MAPPING_SLOT[0..2]
# => [slot_id_prefix, slot_id_suffix, USER_DEPOSIT_KEY, amount]
exec.storage_utils::add_to_map_item
drop
### updating total supply
loc_load.0 push.TOTAL_SUPPLY_SLOT[0..2] exec.storage_utils::add_to_storage_item
drop
end
#! add new deposit: receive asset, update deposit mapping
#!
#! Inputs: [ASSET0, ASSET1, user_id_prefix, user_id_suffix]
#! Outputs: [share_amount_out]
#!
@locals(9)
pub proc deposit
# loc.0: ASSET0
# loc.4: ASSET1
# loc.5: lp_amount_out
loc_storew_be.0 dropw loc_storew_be.4 dropw mem_store.USER_ACCOUNT_ID_PREFIX mem_store.USER_ACCOUNT_ID_SUFFIX
### get_lp_amount_out (total_supply: felt, amount_0: felt, amount_1: felt, reserve_0: felt, reserve_1: felt)
exec.get_reserve
# => [reserve_0, reserve_1]
loc_load.7 loc_load.3
# => [amount_0, amount_1, reserve_0, reserve_1]
exec.total_supply
# => [total_supply, amount_0, amount_1, reserve_0, reserve_1]
exec.get_lp_amount_out
# => [lp_amount_out]
loc_store.5
### check if initial deposit
exec.total_supply eq.0
if.true
### burn minimum liquidity
push.0.0 push.MINIMUM_LIQUIDITY
exec.mint
end
### mint to user
loc_load.5
mem_load.USER_ACCOUNT_ID_SUFFIX mem_load.USER_ACCOUNT_ID_PREFIX
# => [user_id_prefix, user_id_suffix, lp_amount_out]
exec.mint
### receive assets
### reserve needs to be updated
#padw padw padw loc_loadw_be.0 exec.receive_asset
#padw padw padw loc_loadw_be.4 exec.receive_asset
padw loc_loadw_be.0 exec.native_account::add_asset dropw
padw loc_loadw_be.4 exec.native_account::add_asset dropw
## make sure asset order correct
loc_load.7 loc_load.3
# => [amount_0, amount_1]
exec.add_to_reserve
end
```
Compiled with
```
pub fn get_lp_local_library() -> Result {
let math_library = get_math_library()?;
let storage_utils_library = get_storage_utils_library()?;
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let path: PathBuf = [manifest_dir, "asm", "accounts", "lp_local.masm"]
.iter()
.collect();
let source = fs::read_to_string(&path)?;
let assembler = TransactionKernel::assembler()
.with_warnings_as_errors(true)
.with_static_library(math_library)
.map_err(|e| anyhow!("Failed to add math library to assembler: {e:?}"))?
.with_static_library(storage_utils_library)
.map_err(|e| anyhow!("Failed to add storage_utils library to assembler: {e:?}"))?;
create_library(assembler, "zoro::lp_local", &source)
.map_err(|e| anyhow!("Failed to compile lp_local library: {e:?}"))
}
pub fn get_math_library() -> Result {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let path: PathBuf = [manifest_dir, "asm", "accounts", "math.masm"]
.iter()
.collect();
let source = fs::read_to_string(&path)?;
let assembler = TransactionKernel::assembler().with_warnings_as_errors(true);
create_library(assembler, "zoro::math", &source)
.map_err(|e| anyhow!("Failed to compile math library: {e:?}"))
}
pub fn get_storage_utils_library() -> Result {
let math_library = get_math_library()?;
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let path: PathBuf = [manifest_dir, "asm", "accounts", "storage_utils.masm"]
.iter()
.collect();
let source = fs::read_to_string(&path)?;
let assembler = TransactionKernel::assembler()
.with_warnings_as_errors(true)
.with_static_library(math_library)
.unwrap_or_else(|e| panic!("Failed to add math library to assembler: {e:?}"));
create_library(assembler, "zoro::storage_utils", &source)
.map_err(|e| anyhow!("Failed to compile storage_utils library: {e:?}"))
}
pub fn create_library(
assembler: Assembler,
library_path: &str,
source_code: &str,
) -> Result> {
let source_manager = Arc::new(DefaultSourceManager::default());
// println!("parsing library: {:?}", library_path);
let module = Module::parser(ModuleKind::Library).parse_str(
AssemblyPath::new(library_path),
source_code,
source_manager.clone(),
)?;
// println!("Module: {:?}", module);
let library = assembler.clone().assemble_library([module])?;
Ok(library)
}
```
### Relevant log output
```shell
Error: Failed to compile lp_local library: x undefined symbol reference
,-[/Users/mieszkomanijak/Documents/repos/miden/c-prod_pools/target/release/build/miden-protocol-f93a66620a2cffdd/out/asm/shared_modules/account_id.masm:68:11]
67 | #! Inputs: [acct_id_prefix]
68 | #! Outputs: [is_non_fungible_faucet]
: ^^^^^^^^^^^^|^^^^^^^^^^^
: `-- this symbol path could not be resolved
69 | #!
`----
help: maybe you are missing an import?
```
貢獻指南
評估
這個 Issue 還沒有評估資料。