solana documentaiton-developing-Deployed programs

Overview

Developers can write and deploy their own programs to the Solana blockchain.
開発者は、独自のプログラムを書いてソラナブロックチェーンにデプロイすることができます。

The Helloworld example is a good starting place to see how a program is written, built, deployed, and interacted with on-chain.
Helloworldの例は、プログラムがどのように書かれ、構築され、デプロイされ、オンチェーンでやり取りされるかを見るための良い出発点となります。

Berkley Packet Filter (BPF)

Solana on-chain programs are compiled via the LLVM compiler infrastructure to an Executable and Linkable Format (ELF) containing a variation of the Berkley Packet Filter (BPF) bytecode.
ソラナオンチェーンプログラムは、LLVMコンパイラインフラストラクチャを介して、コンパイルされ、BPFバイトコードのバリエーションを含むELFに変換されます。

Because Solana uses the LLVM compiler infrastructure, a program may be written in any programming language that can target the LLVM's BPF backend. Solana currently supports writing programs in Rust and C/C++.
ソラナはLLVMコンパイラインフラストラクチャを使用しているため、LLVMのBPFバックエンドをターゲットとすることができる任意のプログラミング言語でプログラムを書くことができます。ソラナは現在、RustとC/C++でのプログラムの記述をサポートしています。

BPF provides an efficient instruction set that can be executed in a interpreted virtual machine or as efficient just-in-time compiled native instructions.
BPFは効率的な命令セットを提供し、"interpreted"型仮想マシンで実行したり、効率的な"just-in-time"コンパイルされたネイティブ命令として実行することが出来ます。

Memory map(メモリーマップ)

The virtual address memory map used by Solana BPF programs is fixed and laid out as follows
ソラナBPFプログラムで使用する仮想アドレスメモリマップは固定されており、以下のようにレイアウトされています。

・Program code starts at 0x100000000
・Stack data starts at 0x200000000
・Heap data starts at 0x300000000
・Program input parameters start at 0x400000000

The above virtual addresses are start addresses but programs are given access to a subset of the memory map. The program will panic if it attempts to read or write to a virtual address that it was not granted access to, and an AccessViolation error will be returned that contains the address and size of the attempted violation.
上記の仮想アドレスはスタートアドレスですが、プログラムはメモリマップのサブセットへのアクセスを許可れています。アクセスが許可れていない仮想アドレスに読み書きしようとすると、プログラムはパニックに陥り、違反しようとしたアドレスとサイズを含む"AccessViolation"エラーが返されます。

Stack(スタック)

BPF uses stack frames instead of a variable stack pointer. Each stack frame is 4KB in size.
BPFは可変スタックポインタの代わりにスタックフレームを使用します。各スタックフレームのサイズは4KBです。

If a program violates that stack frame size, the compiler will report the overrun as a warning.
プログラムがこのスタックフレームのサイズに違反した場合、コンパイラはオーバーランを警告として報告します。

For example: Error: Function(例:エラー機能) _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables

The message identifies which symbol is exceeding its stack frame but the name might be mangled if it is a Rust or C++ symbol. To demangle a Rust symbol use rustfilt. The above warning came from a Rust program, so the demangled symbol name is:
このメッセージは、どのシンボルがスタックフレームを超えているかを識別しますが、それがRustやC++シンボルである場合、名前が混乱する可能性があります。Rustシンボルを解体するには"rustfilt"を使用してください。上記の警告はRustプログラム由来なので解体されたシンボル名は以下の通りになります。

$ rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E
curve25519_dalek::edwards::EdwardsBasepointTable::create

To demangle a C++ symbol use c++filt from binutils.
C++シンボルを分割するには、"binutils"の"c++filt"を使用してください。

The reason a warning is reported rather than an error is because some dependent crates may include functionality that violates the stack frame restrictions even if the program doesn't use that functionality. If the program violates the stack size at runtime, an AccessViolation error will be reported.
エラーでなく警告が報告されるのは、プログラムがその機能を使用していなくても、依存性のあるクレートにスタックフレームの制限に違反する機能が含まれている可能性があるためです。プログラムが実行時にスタックさずに違反した場合、"AccessViolation"エラーが報告されます。

BPF stack frames occupy a virtual address range starting at 0x200000000.
BPFスタックフレームは、0x200000000から始まる仮想アドレス範囲を占有します。

Call Depth(コールデプス)

Programs are constrained to run quickly, and to facilitate this, the program's call stack is limited to a max depth of 64 frames.
プログラムは素早く実行するように制約されており、これを容易にするために、プログラムのコールスタックは最大64フレームの深さに制限されています。

※Heap(ヒープ)

Programs have access to a runtime heap either directly in C or via the Rust alloc APIs. To facilitate fast allocations, a simple 32KB bump heap is utilized. The heap does not support free or realloc so use it wisely.
プログラムは、C言語で直接、または"Rust alloc API"を介してランタイムヒープにアクセスできます。高速な割り当てを容易にするために、単純な32KBのバンプヒープが利用されています。このヒープはフリーや再割り当てをサポートしていないため、うまく活用してください。

Internally, programs have access to the 32KB memory region starting at virtual address 0x300000000 and may implement a custom heap based on the the program's specific needs.
内部的には、プログラムは仮想アドレス"0x300000000"から始まる32KBのメモリ領域にアクセスすることができ、プログラムの特定のニーズに基づいてカスタムヒープを実装することができます。

Rust program heap usage
C program heap usage

※Heapとは、ヒープ領域(heap memory)はコンピュータープログラミングにおいて、動的に確保可能なメモリの領域のこと。ヒープ (heap) とは、『山積み』という言葉の中の『山』をさす英単語です。(Wikipediaより)


Float Support(フロートサポート)

Programs support a limited subset of Rust's float operations, though they are highly discouraged due to the overhead involved. If a program attempts to use a float operation that is not supported, the runtime will report an unresolved symbol error.
プログラムは、Rust の"float"演算の限られたサブセットをサポートしていますが、オーバーヘッドがかかるため、あまりお勧めできません。プログラムがサポートされていない"float"演算を使用しようとすると、ランタイムは未解決のシンボルエラーを報告します。

Static Writable Data(スタティックライトデータ)

Program shared objects do not support writable shared data. Programs are shared between multiple parallel executions using the same shared read-only code and data. This means that developers should not include any static writable or global variables in programs. In the future a copy-on-write mechanism could be added to support writable data.
プログラム共有オブジェクトは、書込み可能な共有データをサポートしていません。プログラムは、同じ共有された読み取り専用のコードとデータを使用して、複数の並列実行の間で共有されます。これは、開発者が静的な書込み可能な変数やグローバル変数をプログラムに含めるべきではないことを意味します。将来的には、書込み可能なデータをサポートするコピーオンライト機構が追加される可能性があります。

Signed division(符号分割)

The BPF instruction set does not support signed division. Adding a signed division instruction is a consideration.
BPF命令セットは符号付き除算をサポートしていません。符号付き除算命令を追加することが検討されています。

Loaders(ローダー)

Programs are deployed with and executed by runtime loaders, currently there are two supported loaders BPF Loader and BPF loader deprecated
プログラムはランタイムローダによってデプロイされ、実行されます。現在サポートされているローダには"BPFローダ"と非推奨な"BPF loader"があります。

Loaders may support different application binary interfaces so developers must write their programs for and deploy them to the same loader. If a program written for one loader is deployed to a different one the result is usually a AccessViolation error due to mismatched deserialization of the program's input parameters.
ローダは異なるアプリケーションバイナリインターフェースをサポートしている場合があるので、開発者は同じローダ用にプログラムを書いて、同じローダにデプロイしなければなりません。あるローダ(A)用に書かれたプログラムが別のローダ(B)にデプロイされた場合、通常はプログラムの入力パラメータのデシリアライズの不一致による"AccessViolation"エラーが発生します。

For all practical purposes program should always be written to target the latest BPF loader and the latest loader is the default for the command-line interface and the javascript APIs.
全ての実用的な目的のために、プログラムは常に最新のBPFローダをターゲットにして書かれるべきであり、最新のローダは"コマンドラインインターフェース"と"javascript API"のデフォルトです。

For language specific information about implementing a program for a particular loader see:
特定のローダ用のプログラムの実装についての言語別の情報は以下を参照してください。

Rust program entrypoints
C program entrypoints

Deployment(デプロイ)

BPF program deployment is the process of uploading a BPF shared object into a program account's data and marking the account executable. A client breaks the BPF shared object into smaller pieces and sends them as the instruction data of Write instructions to the loader where loader writes that data into the program's account data. Once all the pieces are received the client sends a Finalize instruction to the loader, the loader then validates that the BPF data is valid and marks the program account as executable. Once the program account is marked executable, subsequent transactions may issue instructions for that program to process.
BPFプログラムのデプロイは、BPF共有オブジェクトをプログラムのアカウントデータにアップロードし、そのアカウントを実行可能な状態にするプロセスです。クライアントはBPF共有オブジェクトをより小さな断片に分割し、それらを"Write"命令の命令データとしてローダに送信します。クライアントが全ての断片を受け取ると、クライアントはローダに"Finalize"命令を送り、ローダはBPFデータが有効であることを検証して、プログラムのアカウントを実行可能とマークします。プログラムアカウントが実行可能とマークされると、それ以降のトランザクションは、そのプログラムを処理するための命令を発行することが出来ます。

When an instruction is directed at an executable BPF program the loader configures the program's execution environment, serializes the program's input parameters, calls the program's entrypoint, and reports any errors encountered.
命令が実行可能なBPFプログラムに向けられた場合、ローダはプログラムの実行環境を構成し、プログラムの入力パラメータをシリアライズし、プログラムのエントリポイントを呼び出し、発生したエラーを報告します。

For further information see deploying
詳細については"deploying"を参照してください。

Input Parameter Serialization(インプットパラメータシリアライゼーション)

BPF loaders serialize the program input parameters into a byte array that is then passed to the program's entrypoint, where the program is responsible for deserializing it on-chain. One of the changes between the deprecated loader and the current loader is that the input parameters are serialized in a way that results in various parameters falling on aligned offsets within the aligned byte array. This allows deserialization implementations to directly reference the byte array and provide aligned pointers to the program.
BPFローダはプログラムの入力パラメータをバイトアレイにシリアライズし、それをプログラムのエントリポイントに渡します。非推奨のローダと現代のローダの間の変更点の一つは、入力パラメータが整列されたバイトアレイ内の、整列されたオフセット上に様々なパラメータが位置するような方法でシリアライズされることです。これにより、デシリアライズ実装は、バイトアレイを直接参照し、プログラムへの整列したポインタをを提供することが出来ます。

For language specific information about serialization see:
シリアライズに関する言語別の情報は以下を参照してください。

Rust program parameter deserialization
C program parameter deserialization
The latest loader serializes the program input parameters as follows (all encoding is ※※little endian):
最新のローダでは、プログラムの入力パラメータを以下のようにシリアル化しています。(エンコードは全てリトルエンディアンです。)

※※little endianとは、数値のメモリーへの格納方法です。 数値の上位桁がメモリーの下位にあるような場合に big endian といい, 数値の下位桁がメモリーの下位にあるような場合に little endian といいます。(元ネタは, ガリバー旅行記の小人国のエピソード)

例えば, 4バイトの数値 0x04030201 をメモリーに格納した場合以下のようになります。 (c.f. endian.h)

big endian では下位アドレスのメモリーから順に 04 03 02 01.
先頭のバイトに上位桁を格納しています. (MacOS X/PowerPC, Solaris/SPARC など)
little endian では下位アドレスのメモリーから順に 01 02 03 04.
先頭のバイトに下位桁を格納しています. (Windows/i386, Linux/i386 など)
PDP endian では下位アドレスのメモリーから順に 03 04 01 02.
(PDP)
(http://www.math.kobe-u.ac.jp/HOME/kodama/tips-C-endian.htmlより)

・8 byte unsigned number of accounts
・For each account
○1 byte indicating if this is a duplicate account, if not a duplicate then the value is 0xff, otherwise the value is the index of the account it is a duplicate of.
○7 bytes of padding
・if not duplicate
・1 byte padding
・1 byte boolean, true if account is a signer
・1 byte boolean, true if account is writable
・1 byte boolean, true if account is executable
・4 bytes of padding
・32 bytes of the account public key
・32 bytes of the account's owner public key
・8 byte unsigned number of lamports owned by the account
・8 bytes unsigned number of bytes of account data
・x bytes of account data
・10k bytes of padding, used for realloc
・enough padding to align the offset to 8 bytes.
・8 bytes rent epoch
・8 bytes of unsigned number of instruction data
・x bytes of instruction data
・32 bytes of the program id

この記事が気に入ったらサポートをしてみませんか?