solana_sdk.h 16 KB

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