从零开始学习Solana

解析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_index2,则表示该指令是由 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,
}