Solanaでは、スマートコントラクトはプログラムと呼ばれます。プログラムは、実行可能なコードを含むステートレスなアカウントです。このコードは、instructionsと呼ばれる関数に整理されています。ユーザーは、1つ以上のinstructionsを含むトランザクションを送信することでプログラムと対話します。トランザクションには、複数のプログラムからのinstructionsを含めることができます。
プログラムがデプロイされると、SolanaはLLVMを使用して、実行可能およびリンク可能な形式(ELF)にコンパイルします。ELFファイルには、Solana Bytecode Format(sBPF)のプログラムのバイナリが含まれており、実行可能なアカウント内にオンチェーンで保存されます。
sBPFは、SolanaのカスタムバージョンのeBPFバイトコードです。
プログラムの作成
プログラムの大部分はRustで記述されており、2つの一般的な開発アプローチがあります。
- Anchor: Anchorは、高速で簡単なSolana開発のために設計されたフレームワークです。Rustマクロを使用してボイラープレートコードを削減し、初心者に最適です。
- Native Rust: フレームワークを使用せずにRustでプログラムを記述します。このアプローチはより柔軟性がありますが、複雑さが増します。
プログラムの更新
既存のプログラムを変更するには、アカウントをアップグレード権限として指定する必要があります。(通常、最初にプログラムをデプロイしたアカウントと同じです。)アップグレード権限が取り消され、Noneに設定されると、プログラムは更新できなくなります。
プログラムの検証
Solanaは検証可能なビルドをサポートしており、ユーザーはプログラムのオンチェーンコードが公開されているソースコードと一致するかどうかを確認できます。Anchorフレームワークは、検証可能なビルドを作成するための組み込みサポートを提供しています。
既存のプログラムが検証済みかどうかを確認するには、Solana ExplorerでそのプログラムIDを検索してください。または、Ellipsis LabsのSolana Verifiable Build CLIを使用して、オンチェーンプログラムを独自に検証することもできます。
組み込みプログラム
System Program
System Programは、新しいアカウントを作成できる唯一のアカウントです。デフォルトでは、すべての新しいアカウントはSystem Programによって所有されますが、多くは作成時に新しい所有者に割り当てられます。System Programは以下の主要な機能を実行します。
| 機能 | 説明 |
|---|---|
| 新規アカウント作成 | System Programのみが新しいアカウントを作成できます。 |
| スペース割り当て | 各アカウントのデータフィールドのバイト容量を設定します。 |
| プログラム所有権の割り当て | System Programがアカウントを作成した後、指定されたプログラム所有者を別のプログラムアカウントに再割り当てできます。これにより、カスタムプログラムがSystem Programによって作成された新しいアカウントの所有権を取得します。 |
| SOLの転送 | System Accountから他のアカウントへlamports(SOL)を転送します。 |
System Programのアドレスは11111111111111111111111111111111です。
ローダープログラム
すべてのプログラムは別のプログラム、つまりローダーによって所有されています。ローダーは、プログラムのデプロイ、再デプロイ、アップグレード、またはクローズに使用されます。また、プログラムを確定し、プログラム権限を転送するためにも使用されます。
現在、以下の表に示すように5つのローダープログラムがあります。
| ローダー | プログラムID | 備考 | instructionsリンク |
|---|---|---|---|
| native | NativeLoader1111111111111111111111111111111 | 他の4つのローダーを所有 | — |
| v1 | BPFLoader1111111111111111111111111111111111 | 管理instructionsは無効ですが、プログラムは実行されます | — |
| v2 | BPFLoader2111111111111111111111111111111111 | 管理instructionsは無効ですが、プログラムは実行されます | instructions |
| v3 | BPFLoaderUpgradeab1e11111111111111111111111 | デプロイ後にプログラムを更新できます。プログラム実行可能ファイルは別のプログラムデータアカウントに保存されます | instructions |
| v4 | LoaderV411111111111111111111111111111111111 | 開発中(未リリース) | instructions |
Loader-v3またはloader-v4でデプロイされたプログラムは、アップグレード権限によって決定されるように、デプロイ後に変更可能な場合があります。
新しいプログラムがデプロイされる際、デフォルトで最新のローダーバージョンが使用されます。
プリコンパイル済みプログラム
ローダープログラムに加えて、Solanaは以下のプリコンパイル済みプログラムを提供しています。
Ed25519署名の検証
Ed25519プログラムは、1つ以上のed25519署名を検証するために使用されます。
| プログラム | プログラムID | 説明 | Instructions |
|---|---|---|---|
| Ed25519プログラム | Ed25519SigVerify111111111111111111111111111 | Ed25519署名を検証します。いずれかの署名が失敗した場合、エラーが返されます。 | Instructions |
Ed25519プログラムはinstructionを処理します。instructionの最初のu8には、チェックする署名の数が含まれており、その後に1バイトのパディングが続きます。その後、以下の構造体がチェックする各署名に対してシリアル化されます。
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_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().instructionsinstruction_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リカバリの検証
Secp256k1プログラムは、secp256k1公開鍵リカバリ操作を検証するために使用されます。
| プログラム | プログラムID | 説明 | Instructions |
|---|---|---|---|
| Secp256k1プログラム | KeccakSecp256k11111111111111111111111111111 | Secp256k1公開鍵リカバリ操作(ecrecover)を検証します。 | Instructions |
Secp256k1プログラムはinstructionを処理します。instructionの最初のバイトには、チェックする公開鍵の数が含まれています。その後、以下の構造体が各公開鍵に対して1回作成され、シリアル化されてinstruction dataに追加されます。
struct Secp256k1SignatureOffsets {secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessecp_signature_instruction_index: u8, // instruction index to find signaturesecp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytessecp_pubkey_instruction_index: u8, // instruction index to find pubkeysecp_message_data_offset: u16, // offset to start of message datasecp_message_data_size: u16, // size of message datasecp_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().instructionssignature = 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}
これにより、ユーザーは署名とメッセージデータのためにトランザクション内の任意のinstruction dataを指定できます。特別なinstructions sysvarを指定することで、トランザクション自体からデータを受け取ることもできます。
トランザクションのコストは、検証する署名の数に署名コスト検証乗数を掛けた値でカウントされます。
secp256r1プログラムは、最大8つのsecp256r1署名を検証するために使用されます。
| プログラム | プログラムID | 説明 | instructions |
|---|---|---|---|
| Secp256r1プログラム | Secp256r1SigVerify1111111111111111111111111 | 最大8つのsecp256r1署名を検証します。署名、公開鍵、メッセージを受け取ります。いずれかが失敗した場合、エラーを返します。 | Instructions |
secp256r1プログラムはinstructionを処理します。instructionの最初のu8は、チェックする署名の数のカウントであり、その後に1バイトのパディングが続きます。その後、各署名に対して以下の構造体が作成され、シリアル化されてinstruction
dataに追加されます。
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
偶発的な署名の可鍛性を避けるため、すべての署名に対して低いS値が強制されます。
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif 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}
コアプログラム
以下のリストのプログラムは、ネットワークのコア機能を提供します。
| プログラム | プログラムID | 説明 | instructions |
|---|---|---|---|
| System | 11111111111111111111111111111111 | 新しいアカウントの作成、アカウントデータの割り当て、所有プログラムへのアカウントの割り当て、システムプログラム所有アカウントからのlamportsの転送、およびトランザクション手数料の支払い | SystemInstruction |
| Vote | Vote111111111111111111111111111111111111111 | validatorの投票状態と報酬を追跡するアカウントの作成と管理 | VoteInstruction |
| Stake | Stake11111111111111111111111111111111111111 | validatorへの委任のためのステークと報酬を表すアカウントの作成と管理 | StakeInstruction |
| Config | Config1111111111111111111111111111111111111 | チェーンに設定データを追加し、その後に変更を許可される公開鍵のリストが続きます。他のプログラムとは異なり、Configプログラムは個別のinstructionsを定義しません。暗黙的なinstructionが1つだけあります:「store」。そのinstruction dataは、アカウントへのアクセスとその中に保存されているデータを制御するキーのセットです | ConfigInstruction |
| Compute Budget | ComputeBudget111111111111111111111111111111 | トランザクションのコンピュートユニット制限と価格を設定し、ユーザーがコンピュートリソースと優先順位手数料を制御できるようにします | ComputeBudgetInstruction |
| Address Lookup Table | AddressLookupTab1e1111111111111111111111111 | アドレスルックアップテーブルを管理します。これにより、トランザクションは、トランザクションのアカウントリストに収まる数よりも多くのアカウントを参照できます | ProgramInstruction |
| ZK ElGamal Proof | ZkE1Gama1Proof11111111111111111111111111111 | ElGamal暗号化データのゼロ知識証明検証を提供します | — |
Is this page helpful?