# 从零开始学习Solana

By [Davirain](https://paragraph.com/@davirain-2) · 2024-05-15

---

解析Solana 交易
===========

下面是一个简单的调用solana-client 中 获取block的方法。

这里我使用 indx 1 solt 获取得到的新数据。

EncodeConfirmedBlock中的trasactions字段是包含了这个sols-1区块链中的所有tx。

对于每个tx，有signatures,还有message，meta，version。

重点都在message中。

Tx中的Message
-----------

1.  `header`:
    
    *   类型: `MessageHeader`
        
    *   描述: 包含交易头信息，如签名数量和只读账户信息。
        
2.  `account_keys`:
    
    *   类型: `Vec<String>`
        
    *   描述: 一个字符串向量，包含了交易中涉及的所有账户的公钥。
        
3.  `recent_blockhash`:
    
    *   类型: `String`
        
    *   描述: 最近的区块哈希，用于防止交易重放。
        
4.  `instructions`:
    
    *   类型: `Vec<UiCompiledInstruction>`
        
    *   描述: 包含了交易中的所有指令，每个指令包含执行的程序和相关账户信息。
        
5.  `address_table_lookups`:
    
    *   类型: `Option<Vec<UiAddressTableLookup>>`
        
    *   描述: 可选字段，包含地址表查找信息（如果有的话）。这个字段在序列化时如果是 `None`，将被跳过。
        

Instruction数据结构的解释
------------------

在 Solana 的交易处理过程中，`program_id_index` 是一个指向程序的索引，用于标识执行交易的智能合约或程序。具体来说，它是指向交易中包含的程序列表中的位置索引。这些程序可以是 Solana 的系统程序、用户定义的智能合约等。

### 详细解释

当一个交易在 Solana 区块链上执行时，它通常会引用一个或多个程序来处理交易的逻辑。为了提高效率，Solana 使用索引而不是直接存储程序 ID。这些索引引用了交易的 `accountKeys` 列表中的位置，这个列表包含了交易中所有涉及的账户和程序的公钥。

### 例子

假设我们有一个交易，它的 `accountKeys` 列表如下：

1.  `Account A`（用户账户）
    
2.  `Account B`（用户账户）
    
3.  `Program X`（智能合约）
    
4.  `Program Y`（智能合约）
    

在这个例子中，如果 `program_id_index` 是 `2`，则表示该指令是由 `Program X` 执行的（因为索引是从 0 开始的）。

### UiCompiledInstruction 结构体

在 `UiCompiledInstruction` 结构体中，`program_id_index` 的含义如下：

*   `program_id_index: u8`：这是一个无符号 8 位整数，表示指向 `accountKeys` 列表中的索引，指向执行该指令的程序。
    

### 示例 JSON 表示

假设有一个 JSON 表示如下：

    {
      "program_id_index": 2,
      "accounts": [0, 1],
      "data": "4d2",
      "stack_height": null
    }
    

这个 JSON 表示中：

*   `program_id_index: 2` 表示该指令是由 `accountKeys` 列表中的第三个元素（索引为 2 的元素）所指向的程序执行的。
    
*   `accounts: [0, 1]` 表示该指令涉及 `accountKeys` 列表中的第一个和第二个账户（索引为 0 和 1 的元素）。
    
*   `data: "4d2"` 表示指令的实际数据（通常是经过 Base58 或 Base64 编码的二进制数据）。
    
*   `stack_height` 是一个可选字段，可能用于调试或高级用途。
    

通过这种方式，`program_id_index` 在指令中起到了关键作用，用于确定执行该指令的具体程序。

下面是另一使用具体的例子给的解释：

### `UiRawMessage` 结构体

首先，我们有一个 `UiRawMessage` 结构体，它包含了一个 Solana 交易的详细信息。

#### `header` 字段

    header: MessageHeader {
        num_required_signatures: 1,
        num_readonly_signed_accounts: 0,
        num_readonly_unsigned_accounts: 3,
    },
    

*   `num_required_signatures: 1`：表示此交易需要 1 个签名。
    
*   `num_readonly_signed_accounts: 0`：表示签名的账户中没有只读账户。
    
*   `num_readonly_unsigned_accounts: 3`：表示在未签名的账户中有 3 个只读账户。
    

#### `account_keys` 字段

    account_keys: [
        "DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ",
        "8XgHUtBRY6qePVYERxosyX3MUq8NQkjtmFDSzQ2WpHTJ",
        "SysvarS1otHashes111111111111111111111111111",
        "SysvarC1ock11111111111111111111111111111111",
        "Vote111111111111111111111111111111111111111",
    ],
    

这是一个包含所有相关账户公钥的列表，包括签名账户和程序账户。在这个列表中：

1.  `"DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ"`
    
2.  `"8XgHUtBRY6qePVYERxosyX3MUq8NQkjtmFDSzQ2WpHTJ"`
    
3.  `"SysvarS1otHashes111111111111111111111111111"`
    
4.  `"SysvarC1ock11111111111111111111111111111111"`
    
5.  `"Vote111111111111111111111111111111111111111"`
    

#### `recent_blockhash` 字段

    recent_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
    

这是最近的区块哈希，用于防止交易重放。

#### `instructions` 字段

    instructions: [
        UiCompiledInstruction {
            program_id_index: 4,
            accounts: [
                1,
                2,
                3,
                0,
            ],
            data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM",
            stack_height: None,
        },
    ],
    

##### `UiCompiledInstruction` 解释

*   `program_id_index: 4`: 这个索引指向 `account_keys` 列表中的第五个元素，即 `"Vote111111111111111111111111111111111111111"`。这意味着这条指令是由 `Vote` 程序执行的。
    
*   `accounts: [1, 2, 3, 0]`: 这些索引指向 `account_keys` 列表中的具体账户。具体来说：
    
    *   `1` 对应 `"8XgHUtBRY6qePVYERxosyX3MUq8NQkjtmFDSzQ2WpHTJ"`
        
    *   `2` 对应 `"SysvarS1otHashes111111111111111111111111111"`
        
    *   `3` 对应 `"SysvarC1ock11111111111111111111111111111111"`
        
    *   `0` 对应 `"DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ"`
        
    
    这些账户是这条指令操作的对象。
    
*   `data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM"`: 这是指令的实际数据，通常是经过 Base58 编码的二进制数据。
    
*   `stack_height: None`: 这个字段在这个例子中是空的，可能用于调试或其他高级用途。
    

code
----

    let client = RpcClient::new("your solana rpc url");
    let result = client.get_block(*solt)?;
    println!("{:#?}", result); 
    
    EncodedConfirmedBlock {
        previous_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
        blockhash: "AcknnkY4ok5BZuk69WijDETKVRUPZoMtniZHMe4ZaK1e",
        parent_slot: 0,
        transactions: [
            EncodedTransactionWithStatusMeta {
                transaction: Json(
                    UiTransaction {
                        signatures: [
                            "39V8tR2Q8Ar3WwMBfVTRPFr7AakLHy5wp7skJNBL7ET6ARoikqc1TaMiuXEtHiNPLQKoeiVr5XnKH8QtjdonN4yM",
                        ],
                        message: Raw(
                            UiRawMessage {
                                header: MessageHeader {
                                    num_required_signatures: 1,
                                    num_readonly_signed_accounts: 0,
                                    num_readonly_unsigned_accounts: 3,
                                },
                                account_keys: [
                                    "GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ",
                                    "sCtiJieP8B3SwYnXemiLpRFRR8KJLMtsMVN25fAFWjW",
                                    "SysvarS1otHashes111111111111111111111111111",
                                    "SysvarC1ock11111111111111111111111111111111",
                                    "Vote111111111111111111111111111111111111111",
                                ],
                                recent_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
                                instructions: [
                                    UiCompiledInstruction {
                                        program_id_index: 4,
                                        accounts: [
                                            1,
                                            2,
                                            3,
                                            0,
                                        ],
                                        data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM",
                                        stack_height: None,
                                    },
                                ],
                                address_table_lookups: None,
                            },
                        ),
                    },
                ),
                meta: None,
                version: None,
            },
            EncodedTransactionWithStatusMeta {
                transaction: Json(
                    UiTransaction {
                        signatures: [
                            "4hPVA21e1KLQsEQkpSHk1UfkBBUfotajpkqESuV4tgqEdtEyDufaczAdZzSLexLhjytczDdSUFgwCTancgUWFzym",
                        ],
                        message: Raw(
                            UiRawMessage {
                                header: MessageHeader {
                                    num_required_signatures: 1,
                                    num_readonly_signed_accounts: 0,
                                    num_readonly_unsigned_accounts: 3,
                                },
                                account_keys: [
                                    "CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S",
                                    "9bRDrYShoQ77MZKYTMoAsoCkU7dAR24mxYCBjXLpfEJx",
                                    "SysvarS1otHashes111111111111111111111111111",
                                    "SysvarC1ock11111111111111111111111111111111",
                                    "Vote111111111111111111111111111111111111111",
                                ],
                                recent_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
                                instructions: [
                                    UiCompiledInstruction {
                                        program_id_index: 4,
                                        accounts: [
                                            1,
                                            2,
                                            3,
                                            0,
                                        ],
                                        data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM",
                                        stack_height: None,
                                    },
                                ],
                                address_table_lookups: None,
                            },
                        ),
                    },
                ),
                meta: None,
                version: None,
            },
            EncodedTransactionWithStatusMeta {
                transaction: Json(
                    UiTransaction {
                        signatures: [
                            "FAWA66fudpiwdRDDQ4DRxdJsRvawvauwg4vQkm98ZHFpXmW5N7xzRiTRpt8QiZ19s1aVbzKgXW6kEZanwHeDFNS",
                        ],
                        message: Raw(
                            UiRawMessage {
                                header: MessageHeader {
                                    num_required_signatures: 1,
                                    num_readonly_signed_accounts: 0,
                                    num_readonly_unsigned_accounts: 3,
                                },
                                account_keys: [
                                    "DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ",
                                    "8XgHUtBRY6qePVYERxosyX3MUq8NQkjtmFDSzQ2WpHTJ",
                                    "SysvarS1otHashes111111111111111111111111111",
                                    "SysvarC1ock11111111111111111111111111111111",
                                    "Vote111111111111111111111111111111111111111",
                                ],
                                recent_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
                                instructions: [
                                    UiCompiledInstruction {
                                        program_id_index: 4,
                                        accounts: [
                                            1,
                                            2,
                                            3,
                                            0,
                                        ],
                                        data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM",
                                        stack_height: None,
                                    },
                                ],
                                address_table_lookups: None,
                            },
                        ),
                    },
                ),
                meta: None,
                version: None,
            },
            EncodedTransactionWithStatusMeta {
                transaction: Json(
                    UiTransaction {
                        signatures: [
                            "58A6RFEk5AoFqXTtKfqLhLrs7mhJYWGQTZegoCXPZuneM6Spi47SNYk2M6d9MVzHbC9CpBVk5vrq24yyNgeQNK2p",
                        ],
                        message: Raw(
                            UiRawMessage {
                                header: MessageHeader {
                                    num_required_signatures: 1,
                                    num_readonly_signed_accounts: 0,
                                    num_readonly_unsigned_accounts: 3,
                                },
                                account_keys: [
                                    "7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2",
                                    "4785anyR2rYSas6cQGHtykgzwYEtChvFYhcEgdDw3gGL",
                                    "SysvarS1otHashes111111111111111111111111111",
                                    "SysvarC1ock11111111111111111111111111111111",
                                    "Vote111111111111111111111111111111111111111",
                                ],
                                recent_blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn",
                                instructions: [
                                    UiCompiledInstruction {
                                        program_id_index: 4,
                                        accounts: [
                                            1,
                                            2,
                                            3,
                                            0,
                                        ],
                                        data: "2ZjTR1vUs2pHXyTLpNez6FPzd1qvueZPaMpuuSaez2ARasvL8JYrcHe1U7SN8nkwgrrKwZ3FoRPVtCSfcqM",
                                        stack_height: None,
                                    },
                                ],
                                address_table_lookups: None,
                            },
                        ),
                    },
                ),
                meta: None,
                version: None,
            },
        ],
        rewards: [],
        block_time: None,
        block_height: None,
    }

---

*Originally published on [Davirain](https://paragraph.com/@davirain-2/solana)*
