Files
solana/docs/i18n/zh/docusaurus-plugin-content-docs/current/developing/runtime-facilities/programs.md

96 lines
4.9 KiB
Markdown
Raw Normal View History

---
title: "构建程序"
---
Solana包含少量内置程序这些程序是运行验证程序节点所必需的。 与第三方程序不同,内置程序是验证程序实现的一部分,可以作为群集升级的一部分进行升级。 可能会进行升级以添加功能,修复错误或提高性能。 个别指令的界面更改很少(如果有的话)发生。 相反,当需要更改时,将添加新指令,并且将先前的指令标记为已弃用。 应用程序可以在自己的时间表上进行升级,而无需担心升级过程中的中断。
对于每个内置程序将提供每个支持的指令的程序ID和说明。 事务可以混合和匹配来自不同程序的指令,也可以包括来自已部署程序的指令。
## 系统程序
创建帐户并在它们之间转移Lamport
- 程序ID`11111111111111111111111111111111`
- 说明:[SystemInstruction](https://docs.rs/solana-sdk/VERSION_FOR_DOCS_RS/solana_sdk/system_instruction/enum.SystemInstruction.html)
## 配置程序
将配置数据添加到链和允许对其进行修改的公钥列表中
- 程序ID`Config1111111111111111111111111111111111111111`
- 说明:[config_instruction](https://docs.rs/solana-config-program/VERSION_FOR_DOCS_RS/solana_config_program/config_instruction/index.html)
与其他程序不同Config程序未定义任何单独的指令。 它只有一条隐式指令,即“存储”指令。 它的指令数据是一组密钥,用于控制对帐户的访问以及存储在其中的数据。
## 权益计划
创建权益账户并将其委托给验证者
- 程序ID`Stake11111111111111111111111111111111111111`
- 说明: [StakeInstruction](https://docs.rs/solana-stake-program/VERSION_FOR_DOCS_RS/solana_stake_program/stake_instruction/enum.StakeInstruction.html)
## 投票程序
创建投票账户并对区块进行投票
- 程序ID`Vote111111111111111111111111111111111111111`
- 说明:[VoteInstruction](https://docs.rs/solana-vote-program/VERSION_FOR_DOCS_RS/solana_vote_program/vote_instruction/enum.VoteInstruction.html)
## BPF加载程序
将程序添加到链中并执行它们。
- 程序ID`BPFLoader11111111111111111111111111111111111`
- 说明:[LoaderInstruction](https://docs.rs/solana-sdk/VERSION_FOR_DOCS_RS/solana_sdk/loader_instruction/enum.LoaderInstruction.html)
BPF加载程序将其自身标记为它创建的用于存储程序的可执行帐户的“所有者”。 当用户通过程序ID调用指令时Solana运行时将同时加载您的可执行帐户及其所有者BPF Loader。 然后运行时将您的程序传递给BPF加载程序以处理指令。
## Secp256k1程序
验证secp256k1公钥恢复操作(ecrecover)。
- 程序ID`KeccakSecp256k11111111111111111111111111111111`
- 说明:[new_secp256k1_instruction](https://github.com/solana-labs/solana/blob/c1f3f9d27b5f9534f9a37704bae1d690d4335b6b/programs/secp256k1/src/lib.rs#L18)
Secp256k1程序处理一条指令该指令将在指令数据中序列化的以下结构的计数作为第一个字节
```
struct Secp256k1SignatureOffsets {
secp_signature_key_offset: u16, // offset to [signature,recovery_id,etherum_address] of 64+1+20 bytes
secp_signature_instruction_index: u8, // instruction index to find data
secp_pubkey_offset: u16, // offset to [signature,recovery_id] of 64+1 bytes
secp_signature_instruction_index: u8, // instruction index to find data
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, // index of instruction data to get 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 + 32]
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也可以从事务本身接收数据。
交易成本将计算要验证的签名数乘以签名成本验证乘数。
### 优化注意事项
该操作将必须在(至少部分) 反序列化之后进行但是所有输入都来自交易数据本身这使得它相对于交易处理和PoH验证并行执行相对容易。