deserialize.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #pragma once
  2. /**
  3. * @brief Solana SBF loader deserializer to be used when deploying
  4. * a program with `SBFLoader2111111111111111111111111111111111` or
  5. * `SBFLoaderUpgradeab1e11111111111111111111111`
  6. */
  7. #include <sol/types.h>
  8. #include <sol/pubkey.h>
  9. #include <sol/entrypoint.h>
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. /**
  14. * Maximum number of bytes a program may add to an account during a single realloc
  15. */
  16. #define MAX_PERMITTED_DATA_INCREASE (1024 * 10)
  17. /**
  18. * De-serializes the input parameters into usable types
  19. *
  20. * Use this function to deserialize the buffer passed to the program entrypoint
  21. * into usable types. This function does not perform copy deserialization,
  22. * instead it populates the pointers and lengths in SolAccountInfo and data so
  23. * that any modification to lamports or account data take place on the original
  24. * buffer. Doing so also eliminates the need to serialize back into the buffer
  25. * at the end of the program.
  26. *
  27. * @param input Source buffer containing serialized input parameters
  28. * @param params Pointer to a SolParameters structure
  29. * @return Boolean true if successful.
  30. */
  31. static bool sol_deserialize(
  32. const uint8_t *input,
  33. SolParameters *params,
  34. uint64_t ka_num
  35. ) {
  36. if (NULL == input || NULL == params) {
  37. return false;
  38. }
  39. params->ka_num = *(uint64_t *) input;
  40. input += sizeof(uint64_t);
  41. for (int i = 0; i < params->ka_num; i++) {
  42. uint8_t dup_info = input[0];
  43. input += sizeof(uint8_t);
  44. if (i >= ka_num) {
  45. if (dup_info == UINT8_MAX) {
  46. input += sizeof(uint8_t);
  47. input += sizeof(uint8_t);
  48. input += sizeof(uint8_t);
  49. input += 4; // padding
  50. input += sizeof(SolPubkey);
  51. input += sizeof(SolPubkey);
  52. input += sizeof(uint64_t);
  53. uint64_t data_len = *(uint64_t *) input;
  54. input += sizeof(uint64_t);
  55. input += data_len;
  56. input += MAX_PERMITTED_DATA_INCREASE;
  57. input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
  58. input += sizeof(uint64_t);
  59. } else {
  60. input += 7; // padding
  61. }
  62. continue;
  63. }
  64. if (dup_info == UINT8_MAX) {
  65. // is signer?
  66. params->ka[i].is_signer = *(uint8_t *) input != 0;
  67. input += sizeof(uint8_t);
  68. // is writable?
  69. params->ka[i].is_writable = *(uint8_t *) input != 0;
  70. input += sizeof(uint8_t);
  71. // executable?
  72. params->ka[i].executable = *(uint8_t *) input;
  73. input += sizeof(uint8_t);
  74. input += 4; // padding
  75. // key
  76. params->ka[i].key = (SolPubkey *) input;
  77. input += sizeof(SolPubkey);
  78. // owner
  79. params->ka[i].owner = (SolPubkey *) input;
  80. input += sizeof(SolPubkey);
  81. // lamports
  82. params->ka[i].lamports = (uint64_t *) input;
  83. input += sizeof(uint64_t);
  84. // account data
  85. params->ka[i].data_len = *(uint64_t *) input;
  86. input += sizeof(uint64_t);
  87. params->ka[i].data = (uint8_t *) input;
  88. input += params->ka[i].data_len;
  89. input += MAX_PERMITTED_DATA_INCREASE;
  90. input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
  91. // rent epoch
  92. params->ka[i].rent_epoch = *(uint64_t *) input;
  93. input += sizeof(uint64_t);
  94. } else {
  95. params->ka[i].is_signer = params->ka[dup_info].is_signer;
  96. params->ka[i].is_writable = params->ka[dup_info].is_writable;
  97. params->ka[i].executable = params->ka[dup_info].executable;
  98. params->ka[i].key = params->ka[dup_info].key;
  99. params->ka[i].owner = params->ka[dup_info].owner;
  100. params->ka[i].lamports = params->ka[dup_info].lamports;
  101. params->ka[i].data_len = params->ka[dup_info].data_len;
  102. params->ka[i].data = params->ka[dup_info].data;
  103. params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
  104. input += 7; // padding
  105. }
  106. }
  107. params->data_len = *(uint64_t *) input;
  108. input += sizeof(uint64_t);
  109. params->data = input;
  110. input += params->data_len;
  111. params->program_id = (SolPubkey *) input;
  112. input += sizeof(SolPubkey);
  113. return true;
  114. }
  115. #ifdef __cplusplus
  116. }
  117. #endif
  118. /**@}*/