solana_sdk.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // SPDX-License-Identifier: Apache-2.0
  2. #pragma once
  3. /**
  4. * Numeric types
  5. */
  6. #ifndef __LP64__
  7. #error LP64 data model required
  8. #endif
  9. /** Indicates the instruction was processed successfully */
  10. #define SUCCESS 0
  11. /**
  12. * Builtin program status values occupy the upper 32 bits of the program return
  13. * value. Programs may define their own error values but they must be confined
  14. * to the lower 32 bits.
  15. */
  16. #define TO_BUILTIN(error) ((uint64_t)(error) << 32)
  17. /** Note: Not applicable to program written in C */
  18. #define ERROR_CUSTOM_ZERO TO_BUILTIN(1)
  19. /** The arguments provided to a program instruction where invalid */
  20. #define ERROR_INVALID_ARGUMENT TO_BUILTIN(2)
  21. /** An instruction's data contents was invalid */
  22. #define ERROR_INVALID_INSTRUCTION_DATA TO_BUILTIN(3)
  23. /** An account's data contents was invalid */
  24. #define ERROR_INVALID_ACCOUNT_DATA TO_BUILTIN(4)
  25. /** An account's data was too small */
  26. #define ERROR_ACCOUNT_DATA_TOO_SMALL TO_BUILTIN(5)
  27. /** An account's balance was too small to complete the instruction */
  28. #define ERROR_INSUFFICIENT_FUNDS TO_BUILTIN(6)
  29. /** The account did not have the expected program id */
  30. #define ERROR_INCORRECT_PROGRAM_ID TO_BUILTIN(7)
  31. /** A signature was required but not found */
  32. #define ERROR_MISSING_REQUIRED_SIGNATURES TO_BUILTIN(8)
  33. /** An initialize instruction was sent to an account that has already been initialized */
  34. #define ERROR_ACCOUNT_ALREADY_INITIALIZED TO_BUILTIN(9)
  35. /** An attempt to operate on an account that hasn't been initialized */
  36. #define ERROR_UNINITIALIZED_ACCOUNT TO_BUILTIN(10)
  37. /** The instruction expected additional account keys */
  38. #define ERROR_NOT_ENOUGH_ACCOUNT_KEYS TO_BUILTIN(11)
  39. /** Note: Not applicable to program written in C */
  40. #define ERROR_ACCOUNT_BORROW_FAILED TO_BUILTIN(12)
  41. /** The length of the seed is too long for address generation */
  42. #define MAX_SEED_LENGTH_EXCEEDED TO_BUILTIN(13)
  43. /** Provided seeds do not result in a valid address */
  44. #define INVALID_SEEDS TO_BUILTIN(14)
  45. /** Need more account */
  46. #define ERROR_NEW_ACCOUNT_NEEDED TO_BUILTIN(15)
  47. /**
  48. * Boolean type
  49. */
  50. #ifndef __cplusplus
  51. #include <stdbool.h>
  52. #endif
  53. /**
  54. * Prints a string to stdout
  55. */
  56. void sol_log_(const char *, uint64_t);
  57. #define sol_log(message) sol_log_(message, sol_strlen(message))
  58. /**
  59. * Prints a 64 bit values represented in hexadecimal to stdout
  60. */
  61. void sol_log_64_(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
  62. #define sol_log_64 sol_log_64_
  63. /**
  64. * Size of Public key in bytes
  65. */
  66. #define SIZE_PUBKEY 32
  67. /**
  68. * Public key
  69. */
  70. typedef struct
  71. {
  72. uint8_t x[SIZE_PUBKEY];
  73. } SolPubkey;
  74. /**
  75. * Compares two public keys
  76. *
  77. * @param one First public key
  78. * @param two Second public key
  79. * @return true if the same
  80. */
  81. static bool SolPubkey_same(const SolPubkey *one, const SolPubkey *two)
  82. {
  83. for (int i = 0; i < sizeof(*one); i++)
  84. {
  85. if (one->x[i] != two->x[i])
  86. {
  87. return false;
  88. }
  89. }
  90. return true;
  91. }
  92. /**
  93. * Keyed Account
  94. */
  95. typedef struct
  96. {
  97. SolPubkey *key; /** Public key of the account */
  98. uint64_t *lamports; /** Number of lamports owned by this account */
  99. uint64_t data_len; /** Length of data in bytes */
  100. uint8_t *data; /** On-chain data within this account */
  101. SolPubkey *owner; /** Program that owns this account */
  102. uint64_t rent_epoch; /** The epoch at which this account will next owe rent */
  103. bool is_signer; /** Transaction was signed by this account's key? */
  104. bool is_writable; /** Is the account writable? */
  105. bool executable; /** This account's data contains a loaded program (and is now read-only) */
  106. } SolAccountInfo;
  107. /**
  108. * Copies memory
  109. */
  110. static void sol_memcpy(void *dst, const void *src, int len)
  111. {
  112. for (int i = 0; i < len; i++)
  113. {
  114. *((uint8_t *)dst + i) = *((const uint8_t *)src + i);
  115. }
  116. }
  117. /**
  118. * Compares memory
  119. */
  120. static int sol_memcmp(const void *s1, const void *s2, int n)
  121. {
  122. for (int i = 0; i < n; i++)
  123. {
  124. uint8_t diff = *((uint8_t *)s1 + i) - *((const uint8_t *)s2 + i);
  125. if (diff)
  126. {
  127. return diff;
  128. }
  129. }
  130. return 0;
  131. }
  132. /**
  133. * Fill a byte string with a byte value
  134. */
  135. static void sol_memset(void *b, int c, size_t len)
  136. {
  137. uint8_t *a = (uint8_t *)b;
  138. while (len > 0)
  139. {
  140. *a = c;
  141. a++;
  142. len--;
  143. }
  144. }
  145. /**
  146. * Find length of string
  147. */
  148. static size_t sol_strlen(const char *s)
  149. {
  150. size_t len = 0;
  151. while (*s)
  152. {
  153. len++;
  154. s++;
  155. }
  156. return len;
  157. }
  158. /**
  159. * Computes the number of elements in an array
  160. */
  161. #define SOL_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
  162. /**
  163. * Panics
  164. *
  165. * Prints the line number where the panic occurred and then causes
  166. * the BPF VM to immediately halt execution. No accounts' data are updated
  167. */
  168. void sol_panic_(const char *, uint64_t, uint64_t, uint64_t);
  169. #define sol_panic() sol_panic_(__FILE__, sizeof(__FILE__), __LINE__, 0)
  170. /**
  171. * Asserts
  172. */
  173. #define sol_assert(expr) \
  174. if (!(expr)) \
  175. { \
  176. sol_panic(); \
  177. }
  178. /**
  179. * Seed used to create a program address or passed to sol_invoke_signed
  180. */
  181. typedef struct
  182. {
  183. const uint8_t *addr; /** Seed bytes */
  184. uint64_t len; /** Length of the seed bytes */
  185. } SolSignerSeed;
  186. /**
  187. * Structure that the program's entrypoint input data is deserialized into.
  188. */
  189. typedef struct
  190. {
  191. SolAccountInfo ka[10]; /** Pointer to an array of SolAccountInfo, must already
  192. point to an array of SolAccountInfos */
  193. uint64_t ka_num; /** Number of SolAccountInfo entries in `ka` */
  194. const uint8_t *input; /** pointer to the instruction data */
  195. uint64_t input_len; /** Length in bytes of the instruction data */
  196. SolPubkey *program_id; /** program_id of the currently executing program */
  197. const SolAccountInfo *ka_clock;
  198. const SolAccountInfo *ka_instructions;
  199. } SolParameters;
  200. /**
  201. * Maximum number of bytes a program may add to an account during a single realloc
  202. */
  203. #define MAX_PERMITTED_DATA_INCREASE (1024 * 10)
  204. /**
  205. * De-serializes the input parameters into usable types
  206. *
  207. * Use this function to deserialize the buffer passed to the program entrypoint
  208. * into usable types. This function does not perform copy deserialization,
  209. * instead it populates the pointers and lengths in SolAccountInfo and data so
  210. * that any modification to lamports or account data take place on the original
  211. * buffer. Doing so also eliminates the need to serialize back into the buffer
  212. * at the end of the program.
  213. *
  214. * @param input Source buffer containing serialized input parameters
  215. * @param params Pointer to a SolParameters structure
  216. * @return Boolean true if successful.
  217. */
  218. static uint64_t sol_deserialize(
  219. const uint8_t *input,
  220. SolParameters *params)
  221. {
  222. if (NULL == input || NULL == params)
  223. {
  224. return ERROR_INVALID_ARGUMENT;
  225. }
  226. params->ka_num = *(uint64_t *)input;
  227. input += sizeof(uint64_t);
  228. for (int i = 0; i < params->ka_num; i++)
  229. {
  230. uint8_t dup_info = input[0];
  231. input += sizeof(uint8_t);
  232. if (i >= SOL_ARRAY_SIZE(params->ka))
  233. {
  234. if (dup_info == UINT8_MAX)
  235. {
  236. input += sizeof(uint8_t);
  237. input += sizeof(uint8_t);
  238. input += sizeof(uint8_t);
  239. input += 4; // padding
  240. input += sizeof(SolPubkey);
  241. input += sizeof(SolPubkey);
  242. input += sizeof(uint64_t);
  243. uint64_t data_len = *(uint64_t *)input;
  244. input += sizeof(uint64_t);
  245. input += data_len;
  246. input += MAX_PERMITTED_DATA_INCREASE;
  247. input = (uint8_t *)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
  248. input += sizeof(uint64_t);
  249. }
  250. continue;
  251. }
  252. if (dup_info == UINT8_MAX)
  253. {
  254. // is signer?
  255. params->ka[i].is_signer = *(uint8_t *)input != 0;
  256. input += sizeof(uint8_t);
  257. // is writable?
  258. params->ka[i].is_writable = *(uint8_t *)input != 0;
  259. input += sizeof(uint8_t);
  260. // executable?
  261. params->ka[i].executable = *(uint8_t *)input;
  262. input += sizeof(uint8_t);
  263. input += 4; // padding
  264. // key
  265. params->ka[i].key = (SolPubkey *)input;
  266. input += sizeof(SolPubkey);
  267. // owner
  268. params->ka[i].owner = (SolPubkey *)input;
  269. input += sizeof(SolPubkey);
  270. // lamports
  271. params->ka[i].lamports = (uint64_t *)input;
  272. input += sizeof(uint64_t);
  273. // account data
  274. params->ka[i].data_len = *(uint64_t *)input;
  275. input += sizeof(uint64_t);
  276. params->ka[i].data = (uint8_t *)input;
  277. input += params->ka[i].data_len;
  278. input += MAX_PERMITTED_DATA_INCREASE;
  279. input = (uint8_t *)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
  280. // rent epoch
  281. params->ka[i].rent_epoch = *(uint64_t *)input;
  282. input += sizeof(uint64_t);
  283. }
  284. else
  285. {
  286. params->ka[i].is_signer = params->ka[dup_info].is_signer;
  287. params->ka[i].is_writable = params->ka[dup_info].is_writable;
  288. params->ka[i].executable = params->ka[dup_info].executable;
  289. params->ka[i].key = params->ka[dup_info].key;
  290. params->ka[i].owner = params->ka[dup_info].owner;
  291. params->ka[i].lamports = params->ka[dup_info].lamports;
  292. params->ka[i].data_len = params->ka[dup_info].data_len;
  293. params->ka[i].data = params->ka[dup_info].data;
  294. params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
  295. input += 7; // padding
  296. }
  297. }
  298. uint64_t data_len = *(uint64_t *)input;
  299. input += sizeof(uint64_t);
  300. params->input_len = data_len;
  301. params->input = input;
  302. input += data_len;
  303. params->program_id = (SolPubkey *)input;
  304. input += sizeof(SolPubkey);
  305. return 0;
  306. }
  307. /**
  308. * Byte array pointer and string
  309. */
  310. typedef struct
  311. {
  312. const uint8_t *addr; /** bytes */
  313. uint64_t len; /** number of bytes*/
  314. } SolBytes;
  315. /**
  316. * Length of a sha256 hash result
  317. */
  318. #define SHA256_RESULT_LENGTH 32
  319. /**
  320. * Sha256
  321. *
  322. * @param bytes Array of byte arrays
  323. * @param bytes_len Number of byte arrays
  324. * @param result 32 byte array to hold the result
  325. */
  326. static uint64_t sol_sha256(
  327. const SolBytes *bytes,
  328. int bytes_len,
  329. const uint8_t *result);
  330. /**
  331. * Account Meta
  332. */
  333. typedef struct
  334. {
  335. SolPubkey *pubkey; /** An account's public key */
  336. bool is_writable; /** True if the `pubkey` can be loaded as a read-write account */
  337. bool is_signer; /** True if an Instruction requires a Transaction signature matching `pubkey` */
  338. } SolAccountMeta;
  339. /**
  340. * Instruction
  341. */
  342. typedef struct
  343. {
  344. SolPubkey *program_id; /** Pubkey of the instruction processor that executes this instruction */
  345. SolAccountMeta *accounts; /** Metadata for what accounts should be passed to the instruction processor */
  346. uint64_t account_len; /** Number of SolAccountMetas */
  347. uint8_t *data; /** Opaque data passed to the instruction processor */
  348. uint64_t data_len; /** Length of the data in bytes */
  349. } SolInstruction;
  350. /**
  351. * Seeds used by a signer to create a program address or passed to
  352. * sol_invoke_signed
  353. */
  354. typedef struct
  355. {
  356. const SolSignerSeed *addr; /** An arry of a signer's seeds */
  357. uint64_t len; /** Number of seeds */
  358. } SolSignerSeeds;
  359. /**
  360. * Create a program address
  361. *
  362. * @param seeds Seed bytes used to sign program accounts
  363. * @param seeds_len Length of the seeds array
  364. * @param Progam id of the signer
  365. * @param Program address created, filled on return
  366. */
  367. static uint64_t sol_create_program_address(
  368. const SolSignerSeed *seeds,
  369. int seeds_len,
  370. const SolPubkey *program_id,
  371. const SolPubkey *address);
  372. /**
  373. * Cross-program invocation
  374. * * @{
  375. */
  376. /**
  377. * Invoke another program and sign for some of the keys
  378. *
  379. * @param instruction Instruction to process
  380. * @param account_infos Accounts used by instruction
  381. * @param account_infos_len Length of account_infos array
  382. * @param seeds Seed bytes used to sign program accounts
  383. * @param seeds_len Length of the seeds array
  384. */
  385. static uint64_t sol_invoke_signed(
  386. const SolInstruction *instruction,
  387. const SolAccountInfo *account_infos,
  388. int account_infos_len,
  389. const SolSignerSeeds *signers_seeds,
  390. int signers_seeds_len)
  391. {
  392. uint64_t sol_invoke_signed_c(
  393. const SolInstruction *instruction,
  394. const SolAccountInfo *account_infos,
  395. int account_infos_len,
  396. const SolSignerSeeds *signers_seeds,
  397. int signers_seeds_len);
  398. return sol_invoke_signed_c(
  399. instruction,
  400. account_infos,
  401. account_infos_len,
  402. signers_seeds,
  403. signers_seeds_len);
  404. }
  405. /**
  406. * Invoke another program
  407. *
  408. * @param instruction Instruction to process
  409. * @param account_infos Accounts used by instruction
  410. * @param account_infos_len Length of account_infos array
  411. */
  412. static uint64_t sol_invoke(
  413. const SolInstruction *instruction,
  414. const SolAccountInfo *account_infos,
  415. int account_infos_len)
  416. {
  417. const SolSignerSeeds signers_seeds[] = {{}};
  418. return sol_invoke_signed(
  419. instruction,
  420. account_infos,
  421. account_infos_len,
  422. signers_seeds,
  423. 0);
  424. }
  425. /**@}*/
  426. /**
  427. * Debugging utilities
  428. * @{
  429. */
  430. /**
  431. * Prints the hexadecimal representation of a public key
  432. *
  433. * @param key The public key to print
  434. */
  435. void sol_log_pubkey(
  436. const SolPubkey *pubkey);
  437. /**
  438. * Prints the hexadecimal representation of an array
  439. *
  440. * @param array The array to print
  441. */
  442. static void sol_log_array(const uint8_t *array, int len)
  443. {
  444. for (int j = 0; j < len; j++)
  445. {
  446. sol_log_64(0, 0, 0, j, array[j]);
  447. }
  448. }
  449. /**
  450. * Prints the program's input parameters
  451. *
  452. * @param params Pointer to a SolParameters structure
  453. */
  454. static void sol_log_params(const SolParameters *params)
  455. {
  456. sol_log("- Program identifier:");
  457. sol_log_pubkey(params->program_id);
  458. sol_log("- Number of KeyedAccounts");
  459. sol_log_64(0, 0, 0, 0, params->ka_num);
  460. for (int i = 0; i < params->ka_num; i++)
  461. {
  462. sol_log(" - Is signer");
  463. sol_log_64(0, 0, 0, 0, params->ka[i].is_signer);
  464. sol_log(" - Is writable");
  465. sol_log_64(0, 0, 0, 0, params->ka[i].is_writable);
  466. sol_log(" - Key");
  467. sol_log_pubkey(params->ka[i].key);
  468. sol_log(" - Lamports");
  469. sol_log_64(0, 0, 0, 0, *params->ka[i].lamports);
  470. sol_log(" - data");
  471. sol_log_array(params->ka[i].data, params->ka[i].data_len);
  472. sol_log(" - Owner");
  473. sol_log_pubkey(params->ka[i].owner);
  474. sol_log(" - Executable");
  475. sol_log_64(0, 0, 0, 0, params->ka[i].executable);
  476. sol_log(" - Rent Epoch");
  477. sol_log_64(0, 0, 0, 0, params->ka[i].rent_epoch);
  478. }
  479. sol_log("- Eth abi Instruction data\0");
  480. sol_log_array(params->input, params->input_len);
  481. }
  482. /**@}*/
  483. /**
  484. * Program instruction entrypoint
  485. *
  486. * @param input Buffer of serialized input parameters. Use sol_deserialize() to decode
  487. * @return 0 if the instruction executed successfully
  488. */
  489. uint64_t entrypoint(const uint8_t *input);
  490. #ifdef SOL_TEST
  491. /**
  492. * Stub log functions when building tests
  493. */
  494. #include <stdio.h>
  495. void sol_log_(const char *s, uint64_t len)
  496. {
  497. printf("sol_log: %s\n", s);
  498. }
  499. void sol_log_64(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5)
  500. {
  501. printf("sol_log_64: %llu, %llu, %llu, %llu, %llu\n", arg1, arg2, arg3, arg4, arg5);
  502. }
  503. #endif
  504. #ifdef __cplusplus
  505. }
  506. #endif
  507. /**@}*/