138 lines
4.0 KiB
C
138 lines
4.0 KiB
C
#pragma once
|
|
/**
|
|
* @brief Solana BPF loader deserializer to be used when deploying
|
|
* a program with `BPFLoader2111111111111111111111111111111111` or
|
|
* `BPFLoaderUpgradeab1e11111111111111111111111`
|
|
*/
|
|
|
|
#include <sol/types.h>
|
|
#include <sol/pubkey.h>
|
|
#include <sol/entrypoint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* Maximum number of bytes a program may add to an account during a single realloc
|
|
*/
|
|
#define MAX_PERMITTED_DATA_INCREASE (1024 * 10)
|
|
|
|
/**
|
|
* De-serializes the input parameters into usable types
|
|
*
|
|
* Use this function to deserialize the buffer passed to the program entrypoint
|
|
* into usable types. This function does not perform copy deserialization,
|
|
* instead it populates the pointers and lengths in SolAccountInfo and data so
|
|
* that any modification to lamports or account data take place on the original
|
|
* buffer. Doing so also eliminates the need to serialize back into the buffer
|
|
* at the end of the program.
|
|
*
|
|
* @param input Source buffer containing serialized input parameters
|
|
* @param params Pointer to a SolParameters structure
|
|
* @return Boolean true if successful.
|
|
*/
|
|
static bool sol_deserialize(
|
|
const uint8_t *input,
|
|
SolParameters *params,
|
|
uint64_t ka_num
|
|
) {
|
|
if (NULL == input || NULL == params) {
|
|
return false;
|
|
}
|
|
params->ka_num = *(uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
|
|
for (int i = 0; i < params->ka_num; i++) {
|
|
uint8_t dup_info = input[0];
|
|
input += sizeof(uint8_t);
|
|
|
|
if (i >= ka_num) {
|
|
if (dup_info == UINT8_MAX) {
|
|
input += sizeof(uint8_t);
|
|
input += sizeof(uint8_t);
|
|
input += sizeof(uint8_t);
|
|
input += 4; // padding
|
|
input += sizeof(SolPubkey);
|
|
input += sizeof(SolPubkey);
|
|
input += sizeof(uint64_t);
|
|
uint64_t data_len = *(uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
input += data_len;
|
|
input += MAX_PERMITTED_DATA_INCREASE;
|
|
input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
|
|
input += sizeof(uint64_t);
|
|
} else {
|
|
input += 7; // padding
|
|
}
|
|
continue;
|
|
}
|
|
if (dup_info == UINT8_MAX) {
|
|
// is signer?
|
|
params->ka[i].is_signer = *(uint8_t *) input != 0;
|
|
input += sizeof(uint8_t);
|
|
|
|
// is writable?
|
|
params->ka[i].is_writable = *(uint8_t *) input != 0;
|
|
input += sizeof(uint8_t);
|
|
|
|
// executable?
|
|
params->ka[i].executable = *(uint8_t *) input;
|
|
input += sizeof(uint8_t);
|
|
|
|
input += 4; // padding
|
|
|
|
// key
|
|
params->ka[i].key = (SolPubkey *) input;
|
|
input += sizeof(SolPubkey);
|
|
|
|
// owner
|
|
params->ka[i].owner = (SolPubkey *) input;
|
|
input += sizeof(SolPubkey);
|
|
|
|
// lamports
|
|
params->ka[i].lamports = (uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
|
|
// account data
|
|
params->ka[i].data_len = *(uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
params->ka[i].data = (uint8_t *) input;
|
|
input += params->ka[i].data_len;
|
|
input += MAX_PERMITTED_DATA_INCREASE;
|
|
input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
|
|
|
|
// rent epoch
|
|
params->ka[i].rent_epoch = *(uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
} else {
|
|
params->ka[i].is_signer = params->ka[dup_info].is_signer;
|
|
params->ka[i].is_writable = params->ka[dup_info].is_writable;
|
|
params->ka[i].executable = params->ka[dup_info].executable;
|
|
params->ka[i].key = params->ka[dup_info].key;
|
|
params->ka[i].owner = params->ka[dup_info].owner;
|
|
params->ka[i].lamports = params->ka[dup_info].lamports;
|
|
params->ka[i].data_len = params->ka[dup_info].data_len;
|
|
params->ka[i].data = params->ka[dup_info].data;
|
|
params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
|
|
input += 7; // padding
|
|
}
|
|
}
|
|
|
|
params->data_len = *(uint64_t *) input;
|
|
input += sizeof(uint64_t);
|
|
params->data = input;
|
|
input += params->data_len;
|
|
|
|
params->program_id = (SolPubkey *) input;
|
|
input += sizeof(SolPubkey);
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**@}*/
|