Правила модификации

Кратко

Проверки во время выполнения после каждой инструкции: только владелец может списывать лампорты или изменять данные, данные могут увеличиваться максимум на 10 КиБ за инструкцию, смена владельца требует нулевой инициализации данных, а флаг исполняемости необратим.

Среда выполнения Solana применяет эти правила после выполнения каждой инструкции с помощью BorrowedInstructionAccount методов. Каждое правило проверяется в момент изменения, и транзакция откатывается, если какая-либо проверка не пройдена.

Правила для лампортов

ПравилоПрименениеОшибка
Только владелец может списывать лампортыset_lamports(): проверяет is_owned_by_current_program() при lamports < currentExternalAccountLamportSpend
В режиме только для чтения лампорты не изменяютсяset_lamports(): проверяет is_writable()ReadonlyLamportChange
Любая программа может зачислять лампорты на writable аккаунтset_lamports(): проверка владельца применяется только если новый баланс меньше текущего; writable-проверка всё равно применяетсяReadonlyLamportChange
Баланс лампортов должен сходиться в инструкции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(): проверяет is_owned_by_current_program() при new_len != old_lenAccountDataSizeChanged
Максимальный размер данных: 10 МиБTransactionAccounts::can_data_be_resized(): проверяет new_len <= MAX_ACCOUNT_DATA_LENInvalidRealloc
Максимальный рост за инструкцию: 10 КиБДесериализация в deserialize_parameters_aligned(): проверяет post_len - pre_len <= MAX_PERMITTED_DATA_INCREASEInvalidRealloc
Максимальный рост за транзакцию: 20 МиБTransactionAccounts::can_data_be_resized(): проверяет совокупный resize_delta <= MAX_ACCOUNT_DATA_GROWTH_PER_TRANSACTIONMaxAccountsDataAllocationsExceeded

Правила для владельца

ПравилоПрименениеОшибка
Только текущий владелец может переназначить владельцаset_owner(): проверяет is_owned_by_current_program()ModifiedProgramId
Аккаунт должен быть доступен для записиset_owner(): проверяет is_writable()INLINE_CODE_PLACEHOLDER_06ed73c4723a857е_END
Данные должны быть инициализированы нулямиset_owner(): проверяет is_zeroed(data)ModifiedProgramId

Правила для флага исполняемости

ПравилоПрименениеОшибка
Аккаунт должен быть освобождён от rentset_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 лампортов), RentPaying (больше 0, но меньше минимального значения для освобождения от rent), и RentExempt (равно или больше минимума). Запрещённые переходы вызывают TransactionError::InsufficientFundsForRent.

Выполнение этих правил обеспечивается рантаймом через transition_allowed():

  • Любой аккаунт может перейти в Uninitialized (закрытие) или RentExempt.
  • Ни один аккаунт не может попасть в RentPaying из Uninitialized или RentExempt. Все новые аккаунты должны быть освобождены от rent.

Правила заимствования аккаунта

Во время выполнения инструкции рантайм обеспечивает семантику единственного писателя для заимствования аккаунтов. Программа может получить либо одну изменяемую ссылку, либо несколько неизменяемых ссылок на аккаунт, но не одновременно. Если программа пытается заимствовать аккаунт, который уже изменяемо заимствован (или изменить заимствование аккаунта, который уже неизменяемо заимствован), инструкция завершится с ошибкой AccountBorrowFailed через try_borrow() и try_borrow_mut(). Если инструкция завершается, пока заимствование всё ещё активно, рантайм возвращает AccountBorrowOutstanding в TransactionContext::pop().

Is this page helpful?

Управляется

© 2026 Solana Foundation.
Все права защищены.
Связаться с нами