Wrong masm file shown on certain kinds of errors (missing import, possibly other)
- Ngôn ngữ chính
- Rust
- Star
- 772
- Fork
- 352
- Merge trung bình
- 1 ngày 7 giờ
- Pull request đã merge (30 ngày)
- 84
Mô tả
### 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?
```
Hướng dẫn đóng góp
Hướng nghiên cứu
Lỗi xảy ra trong assembler khi một import bị thiếu khiến tệp không đúng được hiển thị trong thông báo lỗi. Hãy xem mã báo cáo lỗi trong mô-đun assembler, nhiều khả năng nằm trong crate miden-assembly. Tìm nơi tên tệp được phân giải và thay thế. Trường hợp kiểm thử nằm trong phần nội dung của issue: biên dịch một thư viện có import bị thiếu (chẳng hạn active_account) và xem đường dẫn lỗi được tạo ra như thế nào. Bản sửa lỗi phải bảo đảm tên tệp nguồn chính xác được hiển thị.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- rust
- Lĩnh vực
- compilers
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 45/100