プログラム

Solanaでは、「スマートコントラクト」はプログラムと呼ばれています。 プログラムはオンチェーンにデプロイされ、プログラムのコンパイルされた実行可能なバイナリを含むアカウントに格納されます。ユーザーは インストラクションを含むトランザクションを送信することでプログラムと対話し、何をするべきかを指示します。

重要なポイント

  • プログラムは実行可能なコードを含むアカウントであり、インストラクションと呼ばれる関数に整理されています。
  • プログラム自体はステートレスですが、データを保存するための他のアカウントを作成・更新するインストラクションを含むことができます。
  • アップグレード権限を持つアカウントがプログラムを更新できます。この権限が削除されると、プログラムは不変となります。
  • ユーザーは検証可能なビルドを通じて、オンチェーンのプログラムアカウントのデータが公開されているソースコードと一致することを確認できます。

Solanaプログラムの作成

Solanaプログラムは主にRustプログラミング言語で書かれており、開発には一般的に2つのアプローチがあります:

  • Anchor: Solanaプログラム開発のために設計されたフレームワークです。Rustマクロを使用してボイラープレートコードを削減し、より速くシンプルにプログラムを書くことができます。初心者の方には、Anchorフレームワークから始めることをお勧めします。

  • ネイティブRust: このアプローチでは、フレームワークを使用せずにRustでSolanaプログラムを書きます。より柔軟性がありますが、複雑さも増します。

Solanaプログラムの更新

プログラムのデプロイとアップグレードについて詳しく学ぶには、 プログラムのデプロイページをご覧ください。

プログラムは「アップグレード権限」として指定されたアカウントによって 直接変更することができます。これは通常、最初にプログラムをデプロイしたアカウントです。 アップグレード権限が取り消され、nullに設定されると、プログラムは不変となり、それ以上更新することはできなくなります。

検証可能なプログラム

検証可能なビルドにより、誰でもプログラムのオンチェーンコードが公開ソースコードと一致するかどうかを確認でき、ソースとデプロイされたバージョン間の不一致を検出することが可能になります。

Solana開発者コミュニティは、検証可能なビルドをサポートするツールを導入し、開発者とユーザーの両方がオンチェーンプログラムが公開共有されたソースコードを正確に反映していることを確認できるようにしました。

  • 検証済みプログラムの検索: 検証済みプログラムをすぐに確認するには、ユーザーはSolana Explorerでプログラムアドレスを検索できます。検証済みプログラムの例はこちらでご覧いただけます。

  • 検証ツール: Ellipsis LabsによるSolana Verifiable Build CLIを使用すると、ユーザーは公開されたソースコードに対してオンチェーンプログラムを独自に検証できます。

  • Anchorにおける検証可能なビルドのサポート: Anchorは検証可能なビルドの組み込みサポートを提供しています。詳細はAnchorドキュメントで確認できます。

バークレーパケットフィルタ(BPF)

SolanaはLLVM(Low Level Virtual Machine)を使用してプログラムをELF(Executable and Linkable Format)ファイルにコンパイルします。これらのファイルには、「Solana Bytecode Format」(sBPF)と呼ばれるSolana独自バージョンのeBPFバイトコードが含まれています。ELFファイルにはプログラムのバイナリが含まれており、プログラムがデプロイされるとオンチェーンの実行可能アカウントに保存されます。

組み込みプログラム

ローダープログラム

すべてのプログラム自体は、そのローダーである別のプログラムによって所有されています。現在、5つのローダープログラムが存在します:

ローダープログラムID注記命令リンク
nativeNativeLoader1111111111111111111111111111111他の4つのローダーを所有
v1BPFLoader1111111111111111111111111111111111管理命令は無効化されていますが、プログラムは実行されます
v2BPFLoader2111111111111111111111111111111111管理命令は無効化されていますが、プログラムは実行されます命令
v3BPFLoaderUpgradeab1e11111111111111111111111段階的に廃止されています命令
v4LoaderV411111111111111111111111111111111111v4は標準ローダーになる予定です命令

これらのローダーはカスタムプログラムの作成と管理に必要です:

  • 新しいプログラムまたはバッファーのデプロイ
  • プログラムまたはバッファーのクローズ
  • 既存プログラムの再デプロイ/アップグレード
  • プログラムの権限の移転
  • プログラムの確定

Loader-v3とloader-v4は、初期デプロイ後のプログラム修正をサポートしています。これを行う権限は、各プログラムのアカウント所有権がローダーに属しているため、プログラムの権限によって規制されています。

プリコンパイルされたプログラム

Ed25519プログラム

プログラムプログラムID説明命令
Ed25519プログラムEd25519SigVerify111111111111111111111111111ed25519署名を検証します。署名が失敗した場合、エラーが返されます。Instructions

ed25519プログラムは命令を処理します。最初のu8はチェックする署名の数を示し、その後に1バイトのパディングが続きます。その後、チェックする各署名について、以下の構造体がシリアライズされます。

Ed25519SignatureOffsets
struct Ed25519SignatureOffsets {
signature_offset: u16, // offset to ed25519 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to public key of 32 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}

署名検証の疑似コード:

process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
instruction_index = ed25519_signature_instruction_index != u16::MAX ? ed25519_signature_instruction_index : current_instruction;
signature = instructions[instruction_index].data[ed25519_signature_offset..ed25519_signature_offset + 64]
instruction_index = ed25519_pubkey_instruction_index != u16::MAX ? ed25519_pubkey_instruction_index : current_instruction;
pubkey = instructions[instruction_index].data[ed25519_pubkey_offset..ed25519_pubkey_offset + 32]
instruction_index = ed25519_message_instruction_index != u16::MAX ? ed25519_message_instruction_index : current_instruction;
message = instructions[instruction_index].data[ed25519_message_data_offset..ed25519_message_data_offset + ed25519_message_data_size]
if pubkey.verify(signature, message) != Success {
return Error
}
}
return Success
}

Secp256k1プログラム

プログラムプログラムID説明命令
Secp256k1プログラムKeccakSecp256k11111111111111111111111111111secp256k1公開鍵リカバリ操作(ecrecover)を検証します。Instructions

secp256k1プログラムは、命令データ内の最初のバイトとして、以下の構造体のシリアライズされたカウントを取る命令を処理します:

Secp256k1SignatureOffsets
struct Secp256k1SignatureOffsets {
secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytes
secp_signature_instruction_index: u8, // instruction index to find signature
secp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytes
secp_pubkey_instruction_index: u8, // instruction index to find pubkey
secp_message_data_offset: u16, // offset to start of message data
secp_message_data_size: u16, // size of message data
secp_message_instruction_index: u8, // instruction index to find message data
}

リカバリ検証の疑似コード:

process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
signature = instructions[secp_signature_instruction_index].data[secp_signature_offset..secp_signature_offset + 64]
recovery_id = instructions[secp_signature_instruction_index].data[secp_signature_offset + 64]
ref_eth_pubkey = instructions[secp_pubkey_instruction_index].data[secp_pubkey_offset..secp_pubkey_offset + 20]
message_hash = keccak256(instructions[secp_message_instruction_index].data[secp_message_data_offset..secp_message_data_offset + secp_message_data_size])
pubkey = ecrecover(signature, recovery_id, message_hash)
eth_pubkey = keccak256(pubkey[1..])[12..]
if eth_pubkey != ref_eth_pubkey {
return Error
}
}
return Success
}

これにより、ユーザーはトランザクション内の署名とメッセージデータに任意の命令データを指定できます。特別な命令sysvarを指定することで、トランザクション自体からデータを受け取ることもできます。

トランザクションのコストは、検証する署名の数に署名コスト検証乗数を掛けた値で計算されます。

Secp256r1 プログラム

プログラムプログラム ID説明命令
Secp256r1 プログラムSecp256r1SigVerify1111111111111111111111111最大8つのsecp256r1署名を検証します。署名、公開鍵、メッセージを受け取り、いずれかが失敗した場合はエラーを返します。Instructions

secp256r1プログラムは命令を処理します。最初の u8 は確認する署名の数を示し、その後に1バイトのパディングが続きます。その後、以下の構造体が、確認する署名ごとに1つずつシリアライズされます:

Secp256r1SignatureOffsets
struct Secp256r1SignatureOffsets {
signature_offset: u16, // offset to compact secp256r1 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to compressed public key of 33 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}

署名検証の擬似コード:

process_instruction() {
if data.len() < SIGNATURE_OFFSETS_START {
return Error
}
num_signatures = data[0] as usize
if num_signatures == 0 || num_signatures > 8 {
return Error
}
expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START
if data.len() < expected_data_size {
return Error
}
for i in 0..num_signatures {
offsets = parse_signature_offsets(data, i)
signature = get_data_slice(data, instruction_datas, offsets.signature_instruction_index, offsets.signature_offset, SIGNATURE_SERIALIZED_SIZE)
if s > half_curve_order {
return Error
}
pubkey = get_data_slice(data, instruction_datas, offsets.public_key_instruction_index, offsets.public_key_offset, COMPRESSED_PUBKEY_SERIALIZED_SIZE)
message = get_data_slice(data, instruction_datas, offsets.message_instruction_index, offsets.message_data_offset, offsets.message_data_size)
if !verify_signature(signature, pubkey, message) {
return Error
}
}
return Success
}

注意:署名の偶発的な可鍛性を避けるため、すべての署名に対して低いS値が強制されます。

コアプログラム

Solanaクラスターのジェネシスには、ネットワークの中核機能を提供する特別なプログラムのリストが含まれています。歴史的にこれらは「ネイティブ」プログラムと呼ばれ、以前はvalidatorコードと一緒に配布されていました。

プログラムプログラム ID説明命令
System Program11111111111111111111111111111111新しいアカウントの作成、アカウントデータの割り当て、アカウントの所有プログラムへの割り当て、System Programが所有するアカウントからのlamport転送、およびトランザクション手数料の支払いを行います。SystemInstruction
Vote ProgramVote111111111111111111111111111111111111111validatorの投票状態と報酬を追跡するアカウントを作成および管理します。VoteInstruction
Stake ProgramStake11111111111111111111111111111111111111validatorへの委任のためのステークと報酬を表すアカウントを作成および管理します。StakeInstruction
Config ProgramConfig1111111111111111111111111111111111111設定データをチェーンに追加し、それを変更できる公開鍵のリストを続けます。他のプログラムとは異なり、Configプログラムは個別の命令を定義していません。「store」という暗黙の命令が1つだけあります。その命令データは、アカウントへのアクセスを制御するキーのセットと、その中に格納するデータです。ConfigInstruction
Compute Budget ProgramComputeBudget111111111111111111111111111111トランザクションのコンピュートユニットの制限と価格を設定し、ユーザーがコンピュートリソースと優先順位付け手数料を制御できるようにします。ComputeBudgetInstruction
Address Lookup Table ProgramAddressLookupTab1e1111111111111111111111111アドレス検索テーブルを管理し、トランザクションがアカウントリストに収まる数よりも多くのアカウントを参照できるようにします。ProgramInstruction
ZK ElGamal Proof ProgramZkE1Gama1Proof11111111111111111111111111111ElGamal暗号化データのゼロ知識証明検証を提供します。

Is this page helpful?