program_id
of the intended programaccounts
it intends to read from or write toinstruction_data
byte array that is specific to the intended programaccounts
it intends to read from or write toinstructions
blockhash
signatures
The Solana network collects two types of fees:
In Solana, transaction fees are deterministic: there is no concept of a fee market in which users can pay higher fees to increase their chances of being included in the next block. At the time of this writing, transaction fees are determined only by the number of signatures required (i.e. lamports_per_signature
), not by the amount of resources used. This is because there is currently a hard cap of 1232 bytes on all transactions.
All transactions require at least one writable
account to sign the transaction. Once submitted, the writable signer account that is serialized first will be the fee payer. This account will pay for the cost of the transaction regardless of whether the transaction succeeds or fails. If the fee payer does not have a sufficient balance to pay the transaction fee, the transaction will be dropped.
At the time of this writing, 50% of all transaction fees are collected by the validator that produces the block, while the remaining 50% are burned. This structure works to incentivize validators to process as many transactions as possible during their slots in the leader schedule.
executable
process_instruction
); parameters always include:
program_id
: pubkey
accounts
: array
,instruction_data
: byte array
There are 3 kinds of accounts on Solana:
Within data accounts, there are 2 types:
Each account has an address (usually a public key) and an owner (address of a program account). The full field list an account stores is found below.
There are a few important ownership rules:
Program accounts do not store state.
Pubkey实际上就是32个字符表示的base58的Account地址,在Instruction中,我们看到的ProgramId 就是这样的类型,因为Program本身其实是一个文件,也就是Account,只是是可执行的文件。
AccountInfo就是一个Account在链上的表达形式,可以认为是一个文件的属性,想象一下state函数列出的文件属性。其中,key表示文件名,也就是base58的地址。而文件大小可以认为是lamports,这里区别于我们操作系统里面的文件,操作系统里面的文件的大小是可以为0的,且文件存在,而Solana链上的Account如果其大小也就是lamports为0的话,就认为这个文件被删除了。这里的“executable”表示文件是否可执行,如果是可执行的,那么就是一个智能合约账号。而data里面则是文件的内容,类似电脑上的ls列出的文件属性,和cat列出来的文件内容。每个文件都要由一个程序来创建,这个程序称之为这个文件的拥有者,也就是这里的owner。
ProgramResult实际上类型为ProgramError的Result对象,而ProgramError是Solana自定义的一个Error的枚举,也就是Solana抛出来的错误枚举。在合约中,当正常逻辑执行结束后,我们通过Ok()来返回这里Reuslt正确的结果,如果出错了,则通过这里的Result中的ProgramError错误返回。
AccountMeta主要用于Instruction结构的定义,用于协助传递这个指令需要的其他账号信息,其中包括了账号的地址,这个账号是否为签名账号,以及这个账号对应的内容(AccountInfo)是否可以修改。
Instruction在上面已经有介绍了,代表一个处理指令,包含了要处理他的程序的地址program_id,以及这个程序处理时需要用到的AccountMeta表示的账号信息,还有这个指令对应的具体数据payload部分的data。
这里真实的用户协议数据是序列化后,存放在data里面的,所以整体流程是DApp客户端将自定义的指令数据序列化到data里面,然后将账号信息和data发到链上,Solana节点为其找到要执行的程序,并将账号信息和数据data传递给合约程序,合约程序里面将这个data数据反序列化,得到客户端传过来的具体参数。