Podsumowanie
Kontrole w czasie wykonywania po każdej instrukcji: tylko właściciel może obciążać konto lamportami lub modyfikować dane, dane mogą rosnąć maksymalnie o 10 KiB na instrukcję, zmiana właściciela wymaga danych wyzerowanych, a flaga wykonywalności jest nieodwracalna.
Środowisko uruchomieniowe Solana egzekwuje te zasady po wykonaniu każdej
instrukcji za pomocą metod
BorrowedInstructionAccount.
Każda zasada jest sprawdzana w momencie modyfikacji, a transakcja jest
wycofywana, jeśli którakolwiek kontrola się nie powiedzie.
Zasady dotyczące lamportów
| Zasada | Egzekwowanie | Błąd |
|---|---|---|
| Tylko właściciel może obciążać konto lamportami | set_lamports(): sprawdza is_owned_by_current_program(), gdy lamports < current | ExternalAccountLamportSpend |
| Konta tylko do odczytu nie mogą mieć zmienianych lamportów | set_lamports(): sprawdza is_writable() | ReadonlyLamportChange |
| Każdy program może dodać lamporty do zapisywalnego konta | set_lamports(): kontrola właściciela dotyczy tylko sytuacji, gdy nowy bilans jest mniejszy niż obecny; kontrola zapisywalności nadal obowiązuje | ReadonlyLamportChange |
| Bilans lamportów musi się zgadzać w ramach instrukcji | TransactionContext::pop(): weryfikuje get_lamports_delta() == 0 | UnbalancedInstruction |
Zasady dotyczące danych
| Zasada | Egzekwowanie | Błąd |
|---|---|---|
| Tylko właściciel może modyfikować dane | can_data_be_changed(): sprawdza is_owned_by_current_program() | ExternalAccountDataModified |
| Konta tylko do odczytu nie mogą mieć modyfikowanych danych | can_data_be_changed(): sprawdza is_writable() | ReadonlyDataModified |
| Tylko właściciel może zmieniać rozmiar danych | can_data_be_resized(): sprawdza is_owned_by_current_program(), gdy new_len != old_len | AccountDataSizeChanged |
| Maksymalny rozmiar danych: 10 MiB | TransactionAccounts::can_data_be_resized(): sprawdza new_len <= MAX_ACCOUNT_DATA_LEN | InvalidRealloc |
| Maksymalny przyrost na instrukcję: 10 KiB | Deserializacja w deserialize_parameters_aligned(): sprawdza post_len - pre_len <= MAX_PERMITTED_DATA_INCREASE | InvalidRealloc |
| Maksymalny przyrost na transakcję: 20 MiB | TransactionAccounts::can_data_be_resized(): sprawdza sumarycznie resize_delta <= MAX_ACCOUNT_DATA_GROWTH_PER_TRANSACTION | MaxAccountsDataAllocationsExceeded |
Zasady właściciela
| Zasada | Egzekwowanie | Błąd |
|---|---|---|
| Tylko obecny właściciel może zmienić właściciela | set_owner(): sprawdza is_owned_by_current_program() | ModifiedProgramId |
| Konto musi być zapisywalne | set_owner(): sprawdza is_writable() | ModifiedProgramId |
| Dane muszą być wyzerowane | set_owner(): sprawdza is_zeroed(data) | ModifiedProgramId |
Zasady flagi wykonywalności
| Zasada | Egzekwowanie | Błąd |
|---|---|---|
| Konto musi być zwolnione z rent | set_executable(): sprawdza rent.is_exempt(lamports, data_len) | ExecutableAccountNotRentExempt |
| Tylko właściciel może ustawić flagę | set_executable(): sprawdza is_owned_by_current_program() | ExecutableModified |
| Konto musi być zapisywalne | set_executable(): sprawdza is_writable() | ExecutableModified |
Przejścia stanów rent
Konta istnieją w jednym z trzech
RentState
stanów: Uninitialized (0 lamportów), RentPaying (powyżej 0, ale
poniżej minimum zwolnienia z rent), oraz RentExempt (na poziomie minimum
lub powyżej). Niedozwolone przejścia powodują
TransactionError::InsufficientFundsForRent.
Środowisko wykonawcze egzekwuje te zasady przez
transition_allowed():
- Każde konto może przejść do
Uninitialized(zamknięcie) lubRentExempt. - Żadne konto nie może wejść w
RentPayingzUninitializedaniRentExempt. Wszystkie nowe konta muszą być zwolnione z rent.
Zasady pożyczania konta
Podczas wykonywania instrukcji środowisko wykonawcze egzekwuje semantykę
pojedynczego zapisu na kontach. Program może uzyskać albo jedno mutowalne
odwołanie, albo wiele niemutowalnych odwołań do konta, ale nie oba jednocześnie.
Jeśli program spróbuje pożyczyć konto, które jest już mutowalnie pożyczone (lub
mutowalnie pożyczyć konto, które jest już niemutowalnie pożyczone), instrukcja
zakończy się niepowodzeniem z AccountBorrowFailed przez
try_borrow()
oraz
try_borrow_mut().
Jeśli instrukcja zakończy się, gdy pożyczka nadal trwa, środowisko wykonawcze
zwraca AccountBorrowOutstanding w
TransactionContext::pop().
Is this page helpful?