SoproX
Search…
Solana Rust-based program
Recall that clients and on-chain programs communicate by a form of serialized data, on-chain programs also save data to accounts in the form too.
1
# hello-world template
2
# ./hello/src/program/src
3
.
4
β”œβ”€β”€ entrypoint.rs
5
β”œβ”€β”€ error.rs
6
β”œβ”€β”€ instruction.rs
7
β”œβ”€β”€ lib.rs
8
β”œβ”€β”€ processor.rs
9
└── schema
10
β”œβ”€β”€ dummy.rs
11
└── mod.rs
Copied!
This is how Rust-based source code look likes

Entrypoint.rs

Every calls will be handled at the beginning right here. Due to the simple mission and standardized code, we rarely need to modify this file.
1
entrypoint_deprecated!(process_instruction);
2
​
3
fn process_instruction<'a>(
4
program_id: &Pubkey,
5
accounts: &'a [AccountInfo<'a>],
6
instruction_data: &[u8],
7
) -> ProgramResult {
8
if let Err(error) = Processor::process(program_id, accounts, instruction_data) {
9
error.print::<AppError>();
10
return Err(error);
11
}
12
Ok(())
13
}
Copied!
This component is to pass program_is, accounts list, and instruction_data to Processor.rs as the code above has shown, which is all the thing it does.

Processor.rs

After taking serialized data from Entrypoint.rs, all computation will be executed in Processor.rs. You may remember that all the data is serialized. Therefore, to work on and then store the data, we have to define methods to "unpack" and "pack" them, which is the main purpose of Instruction.rs
1
let instruction = AppInstruction::unpack(instruction_data)?;
Copied!
First, Processor.rs passes instruction_data to Instruction.rs to unpack it and then get parameters from the return.
1
match instruction {
2
AppInstruction::SayHello { amount, toggle } => { ... }
3
}
Copied!
Next, depend on the instruction type, Processor.rs will decide which function would be called to handle the data.
Finally, return Ok or Error as results.

Instruction.rs

On instruction data, this component will parse corresponding parameters. The first byte of the instruction data always represents the instruction code. For example in hello-world program, if the first byte is 0, then it should parse the parameters for sayHello function.
1
let (&tag, rest) = instruction.split_first().ok_or(AppError::InvalidInstruction)?;
2
Ok(match tag {
3
0 => {
4
...
5
Self::SayHello { ... }
6
}
7
_ => return Err(AppError::InvalidInstruction.into())
8
})
Copied!

Error.rs

Another component in Solana Rust-based programs is Error.rs. This component is to defined errors and explanations of those errors. Other components can use Error.rs to throw a very detailed error without a lengthy coding. Because the logic of this file is quite simple, so we don't need an overkill document here 😱. The only thing developers must do is following the convention and create numerous errors of desire.

Schema

Recall that a Solana program did not has storage by itself. To store information, you need to do that on separate accounts, then leave account permission to the program. Because the rigid form of data, it must be fixed size, stored in these accounts, we may need several accounts to store different types of data. In Schema folder, we can easily define and manage all account structures by schemata.
For example, dummy.rs is a typical schema is a hello-world program.
1
pub struct Dummy {
2
pub amount: u32,
3
pub toggle: bool,
4
}
Copied!
The Dummy struct has 2 fields namely amount and toggle that program uses to understand the serialized data.
​
Last modified 1yr ago