Skip to content

Commit 88abad3

Browse files
committed
Refactor directory structure (anza-xyz#18)
* Use macro rules * Update directory structure
1 parent 7d4d8b0 commit 88abad3

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed

instruction-view/src/lib.rs

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
//! Instruction types.
2+
3+
use core::marker::PhantomData;
4+
5+
use crate::{account_info::AccountInfo, pubkey::Pubkey};
6+
7+
/// Information about a CPI instruction.
8+
#[repr(C)]
9+
#[derive(Debug, Clone)]
10+
pub struct Instruction<'a, 'b, 'c, 'd>
11+
where
12+
'a: 'b,
13+
{
14+
/// Public key of the program.
15+
pub program_id: &'c Pubkey,
16+
17+
/// Data expected by the program instruction.
18+
pub data: &'d [u8],
19+
20+
/// Metadata describing accounts that should be passed to the program.
21+
pub accounts: &'b [AccountMeta<'a>],
22+
}
23+
24+
/// Use to query and convey information about the sibling instruction components
25+
/// when calling the `sol_get_processed_sibling_instruction` syscall.
26+
#[repr(C)]
27+
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
28+
pub struct ProcessedSiblingInstruction {
29+
/// Length of the instruction data
30+
pub data_len: u64,
31+
32+
/// Number of AccountMeta structures
33+
pub accounts_len: u64,
34+
}
35+
36+
/// An `Account` for CPI invocations.
37+
///
38+
/// This struct contains the same information as an [`AccountInfo`], but has
39+
/// the memory layout as expected by `sol_invoke_signed_c` syscall.
40+
#[repr(C)]
41+
#[derive(Clone)]
42+
pub struct Account<'a> {
43+
// Public key of the account.
44+
key: *const Pubkey,
45+
46+
// Number of lamports owned by this account.
47+
lamports: *const u64,
48+
49+
// Length of data in bytes.
50+
data_len: u64,
51+
52+
// On-chain data within this account.
53+
data: *const u8,
54+
55+
// Program that owns this account.
56+
owner: *const Pubkey,
57+
58+
// The epoch at which this account will next owe rent.
59+
rent_epoch: u64,
60+
61+
// Transaction was signed by this account's key?
62+
is_signer: bool,
63+
64+
// Is the account writable?
65+
is_writable: bool,
66+
67+
// This account's data contains a loaded program (and is now read-only).
68+
executable: bool,
69+
70+
/// The pointers to the `AccountInfo` data are only valid for as long as the
71+
/// `&'a AccountInfo` lives. Instead of holding a reference to the actual `AccountInfo`,
72+
/// which would increase the size of the type, we claim to hold a reference without
73+
/// actually holding one using a `PhantomData<&'a AccountInfo>`.
74+
_account_info: PhantomData<&'a AccountInfo>,
75+
}
76+
77+
#[inline(always)]
78+
const fn offset<T, U>(ptr: *const T, offset: usize) -> *const U {
79+
unsafe { (ptr as *const u8).add(offset) as *const U }
80+
}
81+
82+
impl<'a> From<&'a AccountInfo> for Account<'a> {
83+
fn from(account: &'a AccountInfo) -> Self {
84+
Account {
85+
key: offset(account.raw, 8),
86+
lamports: offset(account.raw, 72),
87+
data_len: account.data_len() as u64,
88+
data: offset(account.raw, 88),
89+
owner: offset(account.raw, 40),
90+
rent_epoch: 0,
91+
is_signer: account.is_signer(),
92+
is_writable: account.is_writable(),
93+
executable: account.executable(),
94+
_account_info: PhantomData::<&'a AccountInfo>,
95+
}
96+
}
97+
}
98+
99+
/// Describes a single account read or written by a program during instruction
100+
/// execution.
101+
///
102+
/// When constructing an [`Instruction`], a list of all accounts that may be
103+
/// read or written during the execution of that instruction must be supplied.
104+
/// Any account that may be mutated by the program during execution, either its
105+
/// data or metadata such as held lamports, must be writable.
106+
///
107+
/// Note that because the Solana runtime schedules parallel transaction
108+
/// execution around which accounts are writable, care should be taken that only
109+
/// accounts which actually may be mutated are specified as writable.
110+
#[repr(C)]
111+
#[derive(Debug, Clone)]
112+
pub struct AccountMeta<'a> {
113+
// Public key of the account.
114+
pub pubkey: &'a Pubkey,
115+
116+
// Indicates whether the account is writable or not.
117+
pub is_writable: bool,
118+
119+
// Indicates whether the account signed the instruction or not.
120+
pub is_signer: bool,
121+
}
122+
123+
impl<'a> AccountMeta<'a> {
124+
pub fn new(pubkey: &'a Pubkey, is_writable: bool, is_signer: bool) -> Self {
125+
Self {
126+
pubkey,
127+
is_writable,
128+
is_signer,
129+
}
130+
}
131+
132+
#[inline(always)]
133+
pub fn readonly(pubkey: &'a Pubkey) -> Self {
134+
Self::new(pubkey, false, false)
135+
}
136+
137+
#[inline(always)]
138+
pub fn writable(pubkey: &'a Pubkey) -> Self {
139+
Self::new(pubkey, true, false)
140+
}
141+
142+
#[inline(always)]
143+
pub fn readonly_signer(pubkey: &'a Pubkey) -> Self {
144+
Self::new(pubkey, false, true)
145+
}
146+
147+
#[inline(always)]
148+
pub fn writable_signer(pubkey: &'a Pubkey) -> Self {
149+
Self::new(pubkey, true, true)
150+
}
151+
}
152+
153+
impl<'a> From<&'a AccountInfo> for AccountMeta<'a> {
154+
fn from(account: &'a crate::account_info::AccountInfo) -> Self {
155+
AccountMeta::new(account.key(), account.is_writable(), account.is_signer())
156+
}
157+
}
158+
159+
#[repr(C)]
160+
#[derive(Debug, Clone)]
161+
pub struct Seed<'a> {
162+
/// Seed bytes.
163+
pub(crate) seed: *const u8,
164+
165+
/// Length of the seed bytes.
166+
len: u64,
167+
168+
/// The pointer to the seed bytes is only valid while the `&'a [u8]` lives. Instead
169+
/// of holding a reference to the actual `[u8]`, which would increase the size of the
170+
/// type, we claim to hold a reference without actually holding one using a
171+
/// `PhantomData<&'a [u8]>`.
172+
_bytes: PhantomData<&'a [u8]>,
173+
}
174+
175+
impl<'a> From<&'a [u8]> for Seed<'a> {
176+
fn from(value: &'a [u8]) -> Self {
177+
Self {
178+
seed: value.as_ptr(),
179+
len: value.len() as u64,
180+
_bytes: PhantomData::<&[u8]>,
181+
}
182+
}
183+
}
184+
185+
/// Represents a [program derived address][pda] (PDA) signer controlled by the
186+
/// calling program.
187+
///
188+
/// [pda]: https://solana.com/docs/core/cpi#program-derived-addresses
189+
#[repr(C)]
190+
#[derive(Debug, Clone)]
191+
pub struct Signer<'a, 'b> {
192+
/// Signer seeds.
193+
pub(crate) seeds: *const Seed<'a>,
194+
195+
/// Number of seeds.
196+
pub(crate) len: u64,
197+
198+
/// The pointer to the seeds is only valid while the `&'b [Seed<'a>]` lives. Instead
199+
/// of holding a reference to the actual `[Seed<'a>]`, which would increase the size
200+
/// of the type, we claim to hold a reference without actually holding one using a
201+
/// `PhantomData<&'b [Seed<'a>]>`.
202+
_seeds: PhantomData<&'b [Seed<'a>]>,
203+
}
204+
205+
impl<'a, 'b> From<&'b [Seed<'a>]> for Signer<'a, 'b> {
206+
fn from(value: &'b [Seed<'a>]) -> Self {
207+
Self {
208+
seeds: value.as_ptr(),
209+
len: value.len() as u64,
210+
_seeds: PhantomData::<&'b [Seed<'a>]>,
211+
}
212+
}
213+
}

0 commit comments

Comments
 (0)