Sichern Sie das Solana-Ökosystem (2) – Aufrufe zwischen Programmen

Beherrschen Sie die Kunst der programmatischen Aufrufe in Solana mit unserem umfassenden Leitfaden und praktischen Beispielen, um Ihre Smart Contract-Entwicklung auf die nächste Stufe zu heben

Sichern Sie das Solana-Ökosystem (2) – Aufrufe zwischen Programmen

0. Überprüfung

1. Überblick

Im vorherigen Blog haben wir vorgestellt, wie Programme bereitgestellt und mit ihnen interagiert wird. Neben dem Aufrufen von Programmanweisungen von der Client-Seite aus ermöglicht Solana Programmen auch, sich über einen Mechanismus namens Cross-Program Invocation gegenseitig aufzurufen. In diesem Beitrag veranschaulichen wir, wie die Cross-Program Invocation verwendet wird. Der Testcode ist hier.

2. Cross Program Invocation

Cross Program Invocation wird normalerweise mit der Funktion invoke implementiert. In diesem Abschnitt veranschaulichen wir die Verwendung von invoke durch die Übertragung von Lamports innerhalb eines Programms.

In Solana gibt es ein natives Programm namens System Program, das eine Rolle bei der Erstellung neuer Konten und der Übertragung von Lamports (SOL) spielt. In diesem Fall ruft Programm A, um Lamports innerhalb eines Programms (z. B. Programm A) zu übertragen, die Funktion transfer() im System Program auf. Gehen wir das konkrete Beispiel unten durch.

2.1 Code-Überprüfung

Zeile 3 bis 10 importieren die erforderlichen Bibliotheken. Beachten Sie, dass sich die Funktion invoke() in der Bibliothek solana_program::program befindet.

In der Funktion process_instruction extrahieren die Zeilen 22 bis 30 die drei vom Client übergebenen Konten. Beachten Sie, dass die Lamports vom from_account zum to_account übertragen werden. Von Zeile 33 bis 44 wird die Funktion invoke() aufgerufen. Sie empfängt zwei Argumente. Das erste ist die aufgerufene Zielanweisung und das zweite ist eine Reihe von Konten. In diesem Beispiel ist die Zielanweisung transfer(), die zum Übertragen von Lamports verwendet wird. Die Konten umfassen alle Konten, die von der aufgerufenen Anweisung benötigt werden. In diesem Fall sind dies from_account und to_account.

Das bereitgestellte Programm finden Sie unter folgendem Link.

https://explorer.solana.com/address/EPaLuYQ4c11BJAe9ucLbta3xGFb17Zy3cZh3UDPbXRG9?cluster=devnet

2.2 Übertragen der Lamports

Wie erwähnt, senden wir die Transaktion an das bereitgestellte Programm. Das bereitgestellte Programm ruft dann das System Program auf, um die Lamports an die Zieladresse zu übertragen. Der obige Code zeigt, wie der Client die Transaktionen erstellt. Zeile 93 bis 101 extrahieren die programId des bereitgestellten Programms. Zeilen 103 bis 109 generieren die Adressen des Absenders, Empfängers und des System Program. Zeilen 111 bis 117 konstruieren die Transaktion. Zeile 118, die Transaktion wird an den Solana-Cluster gesendet. Beachten Sie, dass der einzige Unterzeichner dieser Transaktion der Absender ist, der in Zeile 112 festgelegt ist. Der Absender muss die Transaktion autorisieren (d. h. unterzeichnen), die Geld von seinem Konto abbucht, und der Empfänger muss dies nicht tun (Zeile 113).

Die Transaktion finden Sie unter folgendem Link.

https://explorer.solana.com/tx/4cxqnff8SakVcE9y5phmh6utcbBUGaLDPvqMRgSy9aPGdNVH6DCsQyJXCCzRGvW5CpygUi5pqhgBQxczXnWCoqPJ?cluster=devnet

3. Invoke oder Invoke_signed

In Solana können Programme zur Laufzeit Konten generieren, die als Program Derived Addresses (PDA) bezeichnet werden. Wenn die von einem Programm aufgerufene Zielanweisung unterzeichnete Konten mit PDA enthält, sollte invoke_signed() anstelle von invoke() verwendet werden. Wir verwenden ein weiteres Beispiel, um die Verwendung von invoke_signed() zu demonstrieren. Lassen Sie uns zunächst den Vertragscode durchgehen.

3.1 Code-Überprüfung

In diesem Beispiel erstellen wir zur Laufzeit eine PDA innerhalb eines Programms (d. h. Programm B). Um eine PDA zu erstellen, sollte das System Program in Programm B aufgerufen werden.

Zeile 3 bis 10 importieren die erforderlichen Bibliotheken. Beachten Sie, dass invoke_signed() dieses Mal importiert wird (Zeile 6).

Ähnlich wie im Beispiel in Abschnitt 2 extrahieren wir die erforderlichen Konten (Zeile 22 - Zeile 27), die System Program und PDA sind. Wir verwenden dann die Funktion find_program_address(), um die Adresse der PDA und den Seed zu generieren, der verwendet wird, um diese PDA von der ed25519-Kurve zu verschieben (Zeile 29 - Zeile 30). Dies dient dazu, sicherzustellen, dass die Adresse keinen zugehörigen privaten Schlüssel hat. In diesem Beispiel verwenden der Client und das Programm denselben Seed (d. h. 'You pass butter'), um die PDA zu generieren. Daher sollte die öffentliche Schlüssel gleich sein, was von Zeile 31 bis 34 überprüft wird. Danach rufen wir invoke_signer auf, um die Anweisung allocate() von Zeile 37 bis 47 auszugeben. Anders als bei der Funktion invoke() nimmt sie ein zusätzliches Argument entgegen, nämlich die Seeds, die zur Erstellung der PDA verwendet werden, sowie den Bump-Seed, der von der Funktion find_program_address() verwendet wird.

Um ein Konto zu erstellen/zuzuweisen, muss das Konto selbst eine Signatur bereitstellen, und in diesem Beispiel ist die PDA der Unterzeichner. Um die PDA zu signieren, wird invoke_signed verwendet. Insbesondere verwendet Solana die Seeds und die programId des Aufrufers (d. h. Programm B), um die PDA neu zu erstellen und sie mit den angegebenen Konten (dem zweiten Argument) abzugleichen. Wenn sie gleich sind, wird die PDA signiert.

Das bereitgestellte Programm kann unten überprüft werden.

https://explorer.solana.com/address/4h3RXGsouTRvUWNG1Dqq2tuuASTXFebHC3wFzv3tSFCK?cluster=devnet

3.2 PDA erstellen

Lassen Sie uns das Client-Skript für das zweite Beispiel durchgehen.

In Zeile 104 extrahieren wir die PDA und den Bump-Seed über die Funktion findProgramAddress(). Von Zeile 112 bis 120 wird die Transaktion erstellt und gesendet. Beachten Sie, dass die Eigenschaft (isSigner) der PDA hier 'false' ist (Zeile 113), da sie nicht vom Client signiert werden kann. Zur Laufzeit wird Programm B die PDA signieren und die allocate-Anweisung im Programm System Program aufrufen.

Sie können die zugewiesene PDA in der folgenden Transaktion finden.

https://explorer.solana.com/tx/5fzdfzbD4281pY1HJm37f1fxSEMGmWtQmbmFPzEiP9v6hWF8GRRZmfcMDvPJugTrs3npnCsaWUGvw15URyBhx3LS?cluster=devnet

3.3 Können wir Invoke() verwenden?

Um zu demonstrieren, dass invoke hier nicht verwendet werden kann. Wir verwenden ein anderes Programm (d. h. Programm C), um die allocation-Anweisung aufzurufen.

Die einzige Änderung, die wir vorgenommen haben, ist die Umwandlung der Funktion invoke_signed() in die Funktion invoke(). Wir haben festgestellt, dass das Konto nicht erstellt werden konnte.

Der Fehler zeigt, dass die Cross-Program Invocation einen Unterzeichner benötigt, um erfolgreich ausgeführt zu werden. Das heißt, die Funktion invoke_signed() wird benötigt.

4. Fazit

In diesem Artikel haben wir vorgestellt, wie die Cross-Program Invocation über die Funktion invoke() implementiert wird. Wir haben auch verschiedene Beispiele verwendet, um die Unterschiede zwischen invoke() und invoke_signed() zu veranschaulichen. Bleiben Sie dran, weitere Artikel dieser Reihe werden veröffentlicht.

Lesen Sie weitere Artikel dieser Reihe:

Sign up for the latest updates