solana/sdk/bpf/c/inc/sol/deserialize.h

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
/**@}*/