Özet
Her CPI, temel olarak ~1.000 CU artı serileştirme maliyetlerine mal olur. Hesap verisi, çağrılan programın yürütülmesinden önce ve sonra senkronize edilir. PDA imzalama, çağıran programın program ID'sini kullanır. Dönüş verisi 1.024 bayt ile sınırlıdır.
CPI maliyet modeli
CPI maliyetleri, aynı işlem hesaplama bütçesinden (paylaşılan sayaç) çekilir.
Her invoke / invoke_signed çağrısı için tam maliyet formülü:
total_cpi_cost = invocation_cost+ instruction_data_cost+ account_meta_cost (SIMD-0339 only)+ account_info_cost (SIMD-0339 only)+ per_account_data_cost (for each non-executable account)+ callee_execution_cost
Maliyet dağılımı
| Maliyet bileşeni | Formül | Kaynak |
|---|---|---|
| Çağrı (sabit) | invoke_units = 1.000 CU (SIMD-0339 ile 946) | CPI girişinde ücretlendirilir |
| Instruction data serileştirme | instruction_data_len / cpi_bytes_per_unit | cpi_bytes_per_unit = 250. translate_instruction içinde ücretlendirilir. |
| Hesap meta serileştirme (SIMD-0339) | (num_account_metas * 34) / cpi_bytes_per_unit | Her AccountMeta 34 bayttır (32 pubkey + 1 is_signer + 1 is_writable). translate_instruction içinde ücretlendirilir. |
| Hesap bilgisi çevirisi (SIMD-0339) | (num_account_infos * 80) / cpi_bytes_per_unit | ACCOUNT_INFO_BYTE_SIZE = 80 bayt (32 key + 32 owner + 8 lamports + 8 data_len). translate_account_infos içinde ücretlendirilir. |
| Hesap başına veri | account_data_len / cpi_bytes_per_unit | CallerAccount::from_account_info içinde hesap başına ve çalıştırılabilir hesaplar için ücretlendirilir. |
| Çağrılan programın yürütülmesi | Çağrılan programın tükettiği CU miktarı | Çağrılan programın yürütülmesi sırasında paylaşılan sayaçtan düşülür. |
Örnek maliyet hesaplaması
100 bayt instruction data, 5 hesap meta, 5 hesap bilgisi (her biri 1.000 bayt veri içeren) ve SIMD-0339 aktif olan bir CPI:
invocation_cost = 946instruction_data_cost = 100 / 250 = 0 (integer division)account_meta_cost = (5 * 34) / 250 = 0account_info_cost = (5 * 80) / 250 = 1per_account_data_cost = 5 * (1000 / 250) = 20total (before callee) = 967 CUs
Hesap verisi senkronizasyonu
Hesap durumu, bir CPI sırasında çağıran ve çağrılan arasında iki noktada senkronize edilir. Bu, her iki tarafın da hesap verisinin tutarlı bir görünümünü görmesini sağlar.
CPI öncesi senkronizasyon (çağırandan çağrılana)
Çağrılan çalıştırılmadan önce,
update_callee_account
çağıranın devam eden değişikliklerini çağrılanın hesap görünümüne kopyalar:
| Alan | Yön | Ne zaman |
|---|---|---|
| Lamports | Çağıran -> Çağrılan | Değer, çağrılanın mevcut görünümünden farklıysa |
| Veri uzunluğu | Çağıran -> Çağrılan | Çağıran hesabı yeniden boyutlandırdıysa. original_data_len + MAX_PERMITTED_DATA_INCREASE (10 KiB) değerini aşmamalıdır. |
| Veri içeriği | Çağıran -> Çağrılan | Hesabın verisi değiştirilebilir durumdaysa (can_data_be_changed geçerse) |
| Sahip | Çağıran -> Çağrılan | En son ayarlanır, böylece veri/lamport değişikliklerine eski sahip altında izin verilir |
CPI sonrası senkronizasyon (çağrılandan çağırana)
Çağrılan geri döndükten sonra,
update_caller_account
çağrılanın değişikliklerini çağıranın görünümüne geri kopyalar. Bu yalnızca
yazılabilir olarak işaretlenmiş hesaplar için çalışır:
| Alan | Yön | Ne zaman |
|---|---|---|
| Lamports | Çağrılan -> Çağıran | Her zaman geri kopyalanır |
| Sahip | Çağrılan -> Çağıran | Her zaman geri kopyalanır |
| Veri uzunluğu | Çağrılan -> Çağıran | Değiştiyse. VM veri dilimi işaretçisi ve serileştirilmiş uzunluk alanı güncellenir. Hesap küçültüldüyse, serbest bırakılan bellek sıfırlanır. Yeni uzunluk original_data_len + MAX_PERMITTED_DATA_INCREASE değerini aşarsa, InvalidRealloc döndürür. |
| Veri içeriği | Çağrılan -> Çağıran | Çağrılanın veri tamponundan çağıranın serileştirilmiş veri bölgesine kopyalanır |
Realloc sınırları
Hesap verileri, CPI sırasında mevcut üst düzey talimatın başlangıcındaki hesap
veri uzunluğunun
MAX_PERMITTED_DATA_INCREASE
= 10.240 bayt (10 KiB) ötesine kadar yeniden boyutlandırılabilir. Bu sınır hem
update_callee_account
(CPI öncesi) hem de
update_caller_account
(CPI sonrası) içinde uygulanır. Bu sınırın aşılması InvalidRealloc
döndürür.
PDA imzalama
invoke_signed çağrıldığında, çalışma zamanı sağlanan seed'lerden ve
çağıranın program ID'sinden PDA adreslerini türetir. Bu işlem
translate_signers_rust
içinde gerçekleşir:
- İmzalayan seed dizisi doğrulanır: en fazla
MAX_SIGNERS(16) imzalayan seed seti. - Her seed seti doğrulanır: set başına en fazla
MAX_SEEDS(16) seed, her seed en fazlaMAX_SEED_LEN(32) bayt. Pubkey::create_program_addressseed'ler ve çağıranın program ID'si (çağrılanın değil) ile çağrılır.- Eğer seed'ler geçerli bir PDA üretmezse (yani, ortaya çıkan nokta ed25519
eğrisi üzerindeyse), CPI
BadSeedsile başarısız olur. - Türetilen PDA pubkey'leri toplanır ve geçerli imzalayanlar olarak
prepare_next_instruction'e aktarılır. Yetki kontrolü sırasında, bir çağrılan hesap imzalayan olarak işaretlenmişse ve pubkey'i bu türetilmiş PDA'lardan biriyle eşleşiyorsa, imzalayan kontrolü geçer.
PDA, çağıranın program ID'si kullanılarak türetilir, çağrılanın değil. Bu, yalnızca PDA'ya sahip olan programın (türetmek için ID'si kullanılan programın) onun adına imzalayabileceği anlamına gelir. Bir program, diğer programlardan türetilen PDA'lar için imzalayamaz.
Dönüş verisi
Programlar, dönüş verisi mekanizmasını kullanarak çağıranlara veri geri gönderebilir. Bu işlem iki syscall kullanır:
sol_set_return_data: Mevcut talimat içinMAX_RETURN_DATA(1.024) bayta kadar dönüş verisi ayarlar. Maliyetdata_len / cpi_bytes_per_unit + syscall_base_costCU'dur.sol_get_return_data: En son yürütülen talimat tarafından ayarlanan dönüş verisini okur. Veriyi, onu ayarlayan program ID'si ile birlikte döndürür. Maliyet(data_len + 32) / cpi_bytes_per_unit + syscall_base_costCU'dur (program ID'si için 32 bayt).
Dönüş verisi işlem başına saklanır ve sol_set_return_data çağrısı yapan her
talimat tarafından üzerine yazılır. Her program çağrısının başlangıcında,
çalışma zamanı
dönüş verisini sıfırlar
ve boş hale getirir. Bir CPI döndükten sonra, çağıran taraf, çağrılanın (veya
çağrılanın çağırdığı herhangi bir programın) en son ayarladığı dönüş verisini
okuyabilir.
Dönüş verisi 1.024 bayt ile sınırlıdır. Çağrı zincirinde sol_set_return_data
çağrısı yapan son program, çağıranın ne göreceğini belirler. Eğer çağrılan
taraf, dönüş verisi ayarlayan başka CPI'lar yaparsa, çağrılanın kendi dönüş
verisi üzerine yazılır.
Is this page helpful?