0. İnceleme
1. Genel Bakış
Önceki blog yazısında, programın nasıl dağıtılacağını ve programla nasıl etkileşime girileceğini anlattık. Bir programın talimatlarını istemci tarafından çağırmanın yanı sıra, Solana aynı zamanda programların birbirini çapraz program çağrısı (cross-program invocation) adı verilen bir mekanizma aracılığıyla çağırmasına da olanak tanır. Bu yazıda, çapraz program çağrısının nasıl kullanıldığını açıklıyoruz. Test kodu burada mevcuttur.
2. Çapraz Program Çağrısı
Çapraz program çağrısı genellikle invoke fonksiyonu ile gerçekleştirilir. Bu bölümde, bir program içinde lamport transferi yaparak invoke kullanımını açıklıyoruz.
Solana'da, yeni hesaplar oluşturma ve lamport (SOL) transferi yapma konusunda rol oynayan System Program adında bir yerel program bulunmaktadır.
Bu durumda, bir program içinde (örn. Program A) lamport transferi yapmak için, Program A, System Program içindeki transfer() fonksiyonunu çağırır. Aşağıdaki somut örneği inceleyelim.
2.1 Kod İncelemesi

- satırdan 10. satıra kadar gerekli kütüphaneler içe aktarılmaktadır.
invoke()fonksiyonununsolana_program::programkütüphanesinde yer aldığına dikkat edin.

process_instruction fonksiyonunda, 22. satırdan 30. satıra kadar istemci tarafından iletilen üç hesap çıkarılmaktadır. Lamportların from_account'tan to_account'a transfer edileceğine dikkat edin. 33. satırdan 44. satıra kadar invoke() fonksiyonu çağrılmaktadır. İki argüman alır. Birincisi hedef çağrılan talimat, ikincisi ise bir hesaplar kümesidir.
Bu örnekte, hedef talimat lamport transferi için kullanılan transfer() fonksiyonudur. Hesaplar, çağrılan talimat tarafından gereken tüm hesapları içerir. Bu durumda from_account ve to_account.
Dağıtılan program aşağıdaki bağlantıda bulunabilir.
https://explorer.solana.com/address/EPaLuYQ4c11BJAe9ucLbta3xGFb17Zy3cZh3UDPbXRG9?cluster=devnet
2.2 Lamportları Transfer Etme

Belirtildiği gibi, işlemi dağıtılan programa gönderiyoruz. Dağıtılan program, lamportları hedef adrese transfer etmek için System Program'ı çağıracaktır.
Yukarıdaki kod, istemcinin işlemleri nasıl oluşturduğunu göstermektedir. 93. satırdan 101. satıra kadar dağıtılan programın programId'si çıkarılmaktadır. 103. satırdan 109. satıra kadar gönderenin, alıcının ve System Program'ın adresi oluşturulmaktadır. 111. satırdan 117. satıra kadar işlem oluşturulmaktadır. 118. satırda işlem Solana kümesine gönderilmektedir. Bu işlemdeki tek imzalayanın, 112. satırda belirlenen gönderen olduğuna dikkat edin. Gönderenin, kendi hesabından para çeken işlemi yetkilendirmesi (yani imzalaması) gerekirken, alıcının bunu yapmasına gerek yoktur (113. satır).
İşlem aşağıdaki bağlantıda bulunabilir.
https://explorer.solana.com/tx/4cxqnff8SakVcE9y5phmh6utcbBUGaLDPvqMRgSy9aPGdNVH6DCsQyJXCCzRGvW5CpygUi5pqhgBQxczXnWCoqPJ?cluster=devnet
3. Invoke mu Invoke_signed mı?
Solana'da programlar, çalışma zamanında Program Türetilmiş Adresler (PDA) olarak adlandırılan hesaplar oluşturabilir. Bir program tarafından çağrılan hedef talimat, PDA ile imzalanmış hesaplar içeriyorsa, invoke() yerine invoke_signed() kullanılmalıdır. invoke_signed() kullanımını göstermek için başka bir örnek kullanacağız. Şimdi önce sözleşme kodunu inceleyelim.
3.1 Kod İncelemesi
Bu örnekte, bir program içinde (yani Program B) çalışma zamanında bir PDA oluşturuyoruz. Bir PDA oluşturmak için Program B'de System Program çağrılmalıdır.

- satırdan 10. satıra kadar gerekli kütüphaneler içe aktarılacaktır. Bu sefer
invoke_signed()fonksiyonunun içe aktarıldığına dikkat edin (6. satır).

Bölüm 2'deki örneğe benzer şekilde, gerekli hesapları çıkarıyoruz (22. satır - 27. satır): System Program ve PDA. Ardından PDA'nın adresini ve bu PDA'yı ed25519 eğrisinin dışına itmek için kullanılan tohumu oluşturmak üzere find_program_address() fonksiyonunu kullanıyoruz (29. satır - 30. satır). Bu, adresin ilişkili özel anahtarının olmadığını garanti etmek içindir. Bu örnekte, istemci ve program PDA'yı oluşturmak için aynı tohumu (yani 'You pass butter') kullanmaktadır. Bu nedenle açık anahtar aynı olmalıdır ve bu durum 31. satırdan 34. satıra kadar kontrol edilmektedir. Bunun ardından, invoke_signer çağrılarak 37. satırdan 47. satıra kadar allocate() talimatı verilmektedir. invoke() fonksiyonundan farklı olarak, PDA'yı oluşturmak için kullanılan tohumlar ve find_program_address() fonksiyonu tarafından kullanılan bump tohumu olmak üzere bir argüman daha alır.
Bir hesap oluşturmak/tahsis etmek için hesabın kendisinin imza sağlaması gerekir ve bu örnekte imzalayan PDA'dır. PDA'yı imzalamak için invoke_signed kullanılır. Özellikle, Solana tohumları ve çağıranın (yani Program B'nin) programId'sini kullanarak PDA'yı yeniden oluşturacak ve bunu verilen hesaplarla (ikinci argüman) eşleştirecektir. Eşit olurlarsa, PDA imzalanacaktır.
Dağıtılan program aşağıdan kontrol edilebilir.
https://explorer.solana.com/address/4h3RXGsouTRvUWNG1Dqq2tuuASTXFebHC3wFzv3tSFCK?cluster=devnet
3.2 PDA Oluşturma
İkinci örnek için istemci betiğini inceleyelim.

- satırda,
findProgramAddress()fonksiyonu aracılığıyla PDA ve bump tohumunu çıkarıyoruz. - satırdan 120. satıra kadar işlem oluşturulacak ve gönderilecektir. PDA'nın (
isSigner) özelliğinin burada 'false' (113. satır) olduğuna dikkat edin; zira istemci tarafından imzalanamaz. Çalışma zamanında Program B, PDA'yı imzalayacak veSystem Programprogramındakiallocatetalimatını çağıracaktır.
Aşağıdaki işlemde tahsis edilen PDA'yı bulabilirsiniz.
https://explorer.solana.com/tx/5fzdfzbD4281pY1HJm37f1fxSEMGmWtQmbmFPzEiP9v6hWF8GRRZmfcMDvPJugTrs3npnCsaWUGvw15URyBhx3LS?cluster=devnet
3.3 Invoke() Kullanabilir miyiz?
invoke'un burada kullanılamayacağını göstermek için, allocation talimatını çağırmak üzere başka bir program (yani Program C) kullanıyoruz.
Yaptığımız tek değişiklik, invoke_signed() fonksiyonunu invoke() fonksiyonuyla değiştirmektir. Hesabın oluşturulamadığını fark ettik.

Hata, çapraz program çağrısının başarıyla yürütülmesi için bir imzalayana ihtiyaç duyduğunu göstermektedir. Yani invoke_signed() fonksiyonu gereklidir.
4. Sonuç
Bu makalede, invoke() fonksiyonu aracılığıyla çapraz program çağrısının nasıl uygulanacağını anlattık. Ayrıca invoke() ve invoke_signed() arasındaki farkları açıklamak için farklı örnekler kullandık. Takipte kalın, bu seriye ait daha fazla makale yayınlanacaktır.
Bu serideki diğer makaleleri okuyun:
- Solana Ekosistemini Güvence Altına Alma (1) — Merhaba Solana
- Solana Ekosistemini Güvence Altına Alma (3) — Program Yükseltme
- Solana Ekosistemini Güvence Altına Alma (4) — Hesap Doğrulama
- Solana Ekosistemini Güvence Altına Alma (5) — Çoklu İmza
- Solana Ekosistemini Güvence Altına Alma (6) — Çoklu İmza2
- Solana Ekosistemini Güvence Altına Alma (7) — Tür Karışıklığı



