如何解决Solana交易时出现的Transaction simulation failed指令处理错误
问题根因
错误触发点为代码第67行的unwrap()调用:调用迭代器的position()方法查找groom为a的记录时返回了None,直接调用unwrap()触发panic导致交易失败。
具体原因及修复方案
1. 反序列化错误分支逻辑缺失
原有代码中反序列化账户数据的match分支里,非InvalidData的错误场景仅打印了日志,既没有返回合法的Vec<LoveRecord>,也没有抛出错误终止程序,会导致existing_data_messages变量值异常,后续查找记录必然失败。
修复代码:
let mut existing_data_messages = match <Vec<LoveRecord>>::try_from_slice(&account.data.borrow()) { Ok(data) => data, Err(err) => { if err.kind() == InvalidData { msg!("InvalidData so initializing account data"); get_init_love_records() } else { msg!("Unknown error decoding account data {:?}", err); return Err(ProgramError::InvalidAccountData); } } };
2. 占位记录匹配逻辑风险
初始化的10条记录均为groom="a",第一次写入会把匹配到的第一条记录替换为传入的值,第二次调用时就找不到groom="a的占位记录,直接触发panic。
修复方案:
将unwrap()改为错误抛出,避免panic,同时可根据业务返回明确的无可用占位记录提示:
let index = existing_data_messages.iter().position(|p| p.groom == String::from(DUMMY_TX_ID)) .ok_or(ProgramError::InvalidAccountData)?;
3. 账户空间不足风险
String类型的序列化长度是可变的,初始化的10条短字符串记录序列化后长度固定,若后续传入的groom或created_on长度超过初始值,序列化后的updated_data长度会超过账户分配的空间,执行copy_from_slice会触发越界错误。
修复方案:
- 创建账户时预分配足够空间,按照业务最大可能的字段长度计算10条记录的总大小,初始化账户时直接分配对应容量
- 或者将可变长度的
String替换为固定长度数组存储内容,例如[u8; 64],避免序列化长度波动
4. 可变借用冲突问题
原有代码反序列化时使用了&account.data.borrow_mut(),只读反序列化不需要可变借用,容易和后续写入操作的借用产生冲突,改为只读的borrow()即可(参考第一条修复代码的写法)。
内容的提问来源于stack exchange,提问作者Akshay S P
相关产品推荐
相关产品推荐

