修改规则

概要

每条指令执行后进行运行时检查:只有所有者可以扣除 lamports 或修改数据,数据每条指令最多可增长 10 KiB,变更所有者需保证数据为全零初始化,可执行标志一旦设置不可逆。

Solana 运行时会在每条指令执行后,通过 BorrowedInstructionAccount 方法强制执行这些规则。每条规则都会在发生修改时进行检查,如果有任何检查未通过,交易将被回滚。

Lamports 规则

规则强制执行方式错误代码
只有所有者可以扣除 lamportsset_lamports():检查 is_owned_by_current_program()lamports < currentExternalAccountLamportSpend
只读账户不能更改 lamportsset_lamports():检查 is_writable()ReadonlyLamportChange
任何程序都可以向可写账户增加 lamportsset_lamports():只有当新余额小于当前余额时才检查所有权;可写性检查始终适用ReadonlyLamportChange
每条指令 lamports 必须平衡TransactionContext::pop():验证 get_lamports_delta() == 0UnbalancedInstruction

数据规则

规则强制执行方式错误代码
只有所有者可以修改数据can_data_be_changed():检查 is_owned_by_current_program()ExternalAccountDataModified
只读账户不能修改数据can_data_be_changed():检查 is_writable()ReadonlyDataModified
只有所有者可以调整数据大小can_data_be_resized():当 new_len != old_len 时检查 is_owned_by_current_program()AccountDataSizeChanged
最大数据大小:10 MiBTransactionAccounts::can_data_be_resized():检查 new_len <= MAX_ACCOUNT_DATA_LENInvalidRealloc
每条指令最大增长:10 KiBdeserialize_parameters_aligned() 反序列化时检查 post_len - pre_len <= MAX_PERMITTED_DATA_INCREASEInvalidRealloc
每笔交易最大增长:20 MiBTransactionAccounts::can_data_be_resized():检查累计 resize_delta <= MAX_ACCOUNT_DATA_GROWTH_PER_TRANSACTIONMaxAccountsDataAllocationsExceeded

所有者规则

规则执行方式错误码
只有当前所有者可以重新分配所有权set_owner():检查 is_owned_by_current_program()ModifiedProgramId
账户必须可写set_owner():检查 is_writable()ModifiedProgramId
数据必须为零初始化set_owner():检查 is_zeroed(data)ModifiedProgramId

可执行标志规则

规则执行方式错误码
账户必须 rent 免除set_executable():检查 rent.is_exempt(lamports, data_len)ExecutableAccountNotRentExempt
只有所有者可以设置该标志set_executable():检查 is_owned_by_current_program()ExecutableModified
账户必须可写set_executable():检查 is_writable()ExecutableModified

rent 状态转换

账户存在于三种 RentState 状态之一:Uninitialized(0 lamports)、RentPaying(大于 0 但低于 rent 免除最低值)、以及 RentExempt(等于或高于最低值)。不允许的状态转换会产生 TransactionError::InsufficientFundsForRent

运行时通过 transition_allowed() 强制执行这些规则:

  • 任何账户都可以转换为 Uninitialized(关闭)或 RentExempt
  • 任何账户都不能从 UninitializedRentExempt 进入 RentPaying。所有新账户必须为 rent 免除。

账户借用规则

在指令执行期间,运行时会对账户强制实施单写者借用语义。一个程序可以获得一个可变引用或多个不可变引用,但不能同时获得两者。如果程序尝试借用已被可变借用的账户(或对已被不可变借用的账户进行可变借用),该指令会因 AccountBorrowFailed 而失败,相关代码见 try_borrow()try_borrow_mut()。如果指令在借用尚未释放时完成,运行时会在 TransactionContext::pop() 返回 AccountBorrowOutstanding

Is this page helpful?

Table of Contents

Edit Page

管理者

©️ 2026 Solana 基金会版权所有
取得联系