nitrate_program/cpi.rs
1// Copyright (c) 2024 nifty-oss maintainers
2// Copyright (c) 2024 Magnetar Fields
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Cross-program invocation helper types.
17
18use solana_program::pubkey::Pubkey;
19
20use crate::account_info::AccountInfo;
21
22/// An `AccountMeta`` as expected by `sol_invoke_signed_c`.
23#[repr(C)]
24#[derive(Debug, Clone)]
25pub struct CAccountMeta {
26 // Public key of the account.
27 pub pubkey: *const Pubkey,
28
29 // Is the account writable?
30 pub is_writable: bool,
31
32 // Transaction was signed by this account's key?
33 pub is_signer: bool,
34}
35
36impl From<&AccountInfo> for CAccountMeta {
37 fn from(account: &AccountInfo) -> Self {
38 CAccountMeta {
39 pubkey: offset(account.raw, 8),
40 is_writable: account.is_writable(),
41 is_signer: account.is_signer(),
42 }
43 }
44}
45
46/// An `AccountInfo`` as expected by `sol_invoke_signed_c`.
47#[repr(C)]
48#[derive(Clone)]
49pub struct CAccountInfo {
50 // Public key of the account.
51 pub key: *const Pubkey,
52
53 // Number of lamports owned by this account.
54 pub lamports: *const u64,
55
56 // Length of data in bytes.
57 pub data_len: u64,
58
59 // On-chain data within this account.
60 pub data: *const u8,
61
62 // Program that owns this account.
63 pub owner: *const Pubkey,
64
65 // The epoch at which this account will next owe rent.
66 pub rent_epoch: u64,
67
68 // Transaction was signed by this account's key?
69 pub is_signer: bool,
70
71 // Is the account writable?
72 pub is_writable: bool,
73
74 // This account's data contains a loaded program (and is now read-only).
75 pub executable: bool,
76}
77
78#[inline(always)]
79const fn offset<T, U>(ptr: *const T, offset: usize) -> *const U {
80 unsafe { (ptr as *const u8).add(offset) as *const U }
81}
82
83impl From<&AccountInfo> for CAccountInfo {
84 fn from(account: &AccountInfo) -> Self {
85 CAccountInfo {
86 key: offset(account.raw, 8),
87 lamports: offset(account.raw, 72),
88 data_len: account.data_len() as u64,
89 data: offset(account.raw, 88),
90 owner: offset(account.raw, 40),
91 rent_epoch: 0,
92 is_signer: account.is_signer(),
93 is_writable: account.is_writable(),
94 executable: account.executable(),
95 }
96 }
97}
98
99/*
100impl CAccountInfo {
101 /// A CPI utility function
102 #[inline(always)]
103 pub(crate) fn to_account_meta(&self) -> CAccountMeta {
104 CAccountMeta {
105 pubkey: self.key,
106 is_writable: self.is_writable,
107 is_signer: self.is_signer,
108 }
109 }
110
111 /// A CPI utility function.
112 /// Intended for PDAs that didn't sign transaction but must sign for cpi.
113 #[inline(always)]
114 pub(crate) fn to_account_meta_signer(&self) -> CAccountMeta {
115 CAccountMeta {
116 pubkey: self.key,
117 is_writable: self.is_writable,
118 is_signer: true,
119 }
120 }
121}
122*/
123
124/// An `Instruction` as expected by `sol_invoke_signed_c`.
125#[repr(C)]
126#[derive(Debug, PartialEq, Clone)]
127pub struct CInstruction {
128 /// Public key of the program.
129 pub program_id: *const Pubkey,
130
131 /// Accounts expected by the program instruction.
132 pub accounts: *const CAccountMeta,
133
134 /// Number of accounts expected by the program instruction.
135 pub accounts_len: u64,
136
137 /// Data expected by the program instruction.
138 pub data: *const u8,
139
140 /// Length of the data expected by the program instruction.
141 pub data_len: u64,
142}